Merge "Print APIs update." into klp-dev

This commit is contained in:
Svetoslav Ganov
2013-08-28 00:07:08 +00:00
committed by Android (Google) Code Review
10 changed files with 671 additions and 128 deletions

View File

@ -19017,6 +19017,7 @@ package android.preference {
package android.print { package android.print {
public final class PageRange implements android.os.Parcelable { public final class PageRange implements android.os.Parcelable {
ctor public PageRange(int, int);
method public int describeContents(); method public int describeContents();
method public int getEnd(); method public int getEnd();
method public int getStart(); method public int getStart();
@ -19044,8 +19045,9 @@ package android.print {
field public static final int DUPLEX_MODE_LONG_EDGE = 2; // 0x2 field public static final int DUPLEX_MODE_LONG_EDGE = 2; // 0x2
field public static final int DUPLEX_MODE_NONE = 1; // 0x1 field public static final int DUPLEX_MODE_NONE = 1; // 0x1
field public static final int DUPLEX_MODE_SHORT_EDGE = 4; // 0x4 field public static final int DUPLEX_MODE_SHORT_EDGE = 4; // 0x4
field public static final int FITTING_MODE_FIT_TO_PAGE = 2; // 0x2
field public static final int FITTING_MODE_NONE = 1; // 0x1 field public static final int FITTING_MODE_NONE = 1; // 0x1
field public static final int FITTING_MODE_SCALE_TO_FILL = 4; // 0x4
field public static final int FITTING_MODE_SCALE_TO_FIT = 2; // 0x2
field public static final int ORIENTATION_LANDSCAPE = 2; // 0x2 field public static final int ORIENTATION_LANDSCAPE = 2; // 0x2
field public static final int ORIENTATION_PORTRAIT = 1; // 0x1 field public static final int ORIENTATION_PORTRAIT = 1; // 0x1
} }
@ -19070,6 +19072,7 @@ package android.print {
method public int getLeftMils(); method public int getLeftMils();
method public int getRightMils(); method public int getRightMils();
method public int getTopMils(); method public int getTopMils();
field public static final android.print.PrintAttributes.Margins NO_MARGINS;
} }
public static final class PrintAttributes.MediaSize { public static final class PrintAttributes.MediaSize {
@ -19157,21 +19160,33 @@ package android.print {
public final class PrintDocumentInfo implements android.os.Parcelable { public final class PrintDocumentInfo implements android.os.Parcelable {
method public int describeContents(); method public int describeContents();
method public int getColorMode();
method public int getContentType(); method public int getContentType();
method public int getFittingMode();
method public android.print.PrintAttributes.Margins getMargins();
method public android.print.PrintAttributes.MediaSize getMediaSize();
method public java.lang.String getName(); method public java.lang.String getName();
method public int getOrientation();
method public int getPageCount(); method public int getPageCount();
method public void writeToParcel(android.os.Parcel, int); method public void writeToParcel(android.os.Parcel, int);
field public static final int CONTENT_TYPE_DOCUMENT = 0; // 0x0 field public static final int CONTENT_TYPE_DOCUMENT = 0; // 0x0
field public static final int CONTENT_TYPE_PHOTO = 1; // 0x1 field public static final int CONTENT_TYPE_PHOTO = 1; // 0x1
field public static final int CONTENT_TYPE_UNKNOWN = -1; // 0xffffffff field public static final int CONTENT_TYPE_UNKNOWN = -1; // 0xffffffff
field public static final android.os.Parcelable.Creator CREATOR; field public static final android.os.Parcelable.Creator CREATOR;
field public static final android.print.PrintAttributes.MediaSize MEDIA_SIZE_UNKNOWN;
field public static final int PAGE_COUNT_UNKNOWN = -1; // 0xffffffff field public static final int PAGE_COUNT_UNKNOWN = -1; // 0xffffffff
} }
public static final class PrintDocumentInfo.Builder { public static final class PrintDocumentInfo.Builder {
ctor public PrintDocumentInfo.Builder(java.lang.String, android.print.PrintAttributes);
ctor public PrintDocumentInfo.Builder(java.lang.String); ctor public PrintDocumentInfo.Builder(java.lang.String);
method public android.print.PrintDocumentInfo create(); method public android.print.PrintDocumentInfo create();
method public android.print.PrintDocumentInfo.Builder setColorMode(int);
method public android.print.PrintDocumentInfo.Builder setContentType(int); method public android.print.PrintDocumentInfo.Builder setContentType(int);
method public android.print.PrintDocumentInfo.Builder setFittingMode(int);
method public android.print.PrintDocumentInfo.Builder setMargins(android.print.PrintAttributes.Margins);
method public android.print.PrintDocumentInfo.Builder setMediaSize(android.print.PrintAttributes.MediaSize);
method public android.print.PrintDocumentInfo.Builder setOrientation(int);
method public android.print.PrintDocumentInfo.Builder setPageCount(int); method public android.print.PrintDocumentInfo.Builder setPageCount(int);
} }
@ -19259,7 +19274,9 @@ package android.print {
method public int getStatus(); method public int getStatus();
method public void writeToParcel(android.os.Parcel, int); method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR; field public static final android.os.Parcelable.Creator CREATOR;
field public static final int STATUS_READY = 1; // 0x1 field public static final int STATUS_BUSY = 2; // 0x2
field public static final int STATUS_IDLE = 1; // 0x1
field public static final int STATUS_UNAVAILABLE = 3; // 0x3
} }
public static final class PrinterInfo.Builder { public static final class PrinterInfo.Builder {
@ -19269,6 +19286,7 @@ package android.print {
method public android.print.PrinterInfo.Builder setCapabilities(android.print.PrinterCapabilitiesInfo); method public android.print.PrinterInfo.Builder setCapabilities(android.print.PrinterCapabilitiesInfo);
method public android.print.PrinterInfo.Builder setDescription(java.lang.String); method public android.print.PrinterInfo.Builder setDescription(java.lang.String);
method public android.print.PrinterInfo.Builder setName(java.lang.String); method public android.print.PrinterInfo.Builder setName(java.lang.String);
method public android.print.PrinterInfo.Builder setStatus(int);
} }
} }
@ -19291,19 +19309,27 @@ package android.print.pdf {
public static final class PdfDocument.PageInfo { public static final class PdfDocument.PageInfo {
method public android.graphics.Rect getContentSize(); method public android.graphics.Rect getContentSize();
method public int getDesity();
method public android.graphics.Matrix getInitialTransform(); method public android.graphics.Matrix getInitialTransform();
method public int getPageNumber(); method public int getPageNumber();
method public android.graphics.Rect getPageSize(); method public android.graphics.Rect getPageSize();
} }
public static final class PdfDocument.PageInfo.Builder { public static final class PdfDocument.PageInfo.Builder {
ctor public PdfDocument.PageInfo.Builder(android.graphics.Rect, int, int); ctor public PdfDocument.PageInfo.Builder(android.graphics.Rect, int);
method public android.print.pdf.PdfDocument.PageInfo create(); method public android.print.pdf.PdfDocument.PageInfo create();
method public android.print.pdf.PdfDocument.PageInfo.Builder setContentSize(android.graphics.Rect); method public android.print.pdf.PdfDocument.PageInfo.Builder setContentSize(android.graphics.Rect);
method public android.print.pdf.PdfDocument.PageInfo.Builder setInitialTransform(android.graphics.Matrix); method public android.print.pdf.PdfDocument.PageInfo.Builder setInitialTransform(android.graphics.Matrix);
} }
public final class PrintedPdfDocument {
method public void close();
method public void finishPage(android.print.pdf.PdfDocument.Page);
method public java.util.List<android.print.pdf.PdfDocument.PageInfo> getPages();
method public static android.print.pdf.PrintedPdfDocument open(android.content.Context, android.print.PrintAttributes);
method public android.print.pdf.PdfDocument.Page startPage(int);
method public void writeTo(java.io.OutputStream);
}
} }
package android.printservice { package android.printservice {

View File

@ -42,8 +42,6 @@ public final class PageRange implements Parcelable {
* @throws IllegalArgumentException If start is less than zero. * @throws IllegalArgumentException If start is less than zero.
* @throws IllegalArgumentException If end is less than zero. * @throws IllegalArgumentException If end is less than zero.
* @throws IllegalArgumentException If start greater than end. * @throws IllegalArgumentException If start greater than end.
*
* @hide
*/ */
public PageRange(int start, int end) { public PageRange(int start, int end) {
if (start < 0) { if (start < 0) {

View File

@ -50,9 +50,15 @@ public final class PrintAttributes implements Parcelable {
/** Fitting mode: No fitting. */ /** Fitting mode: No fitting. */
public static final int FITTING_MODE_NONE = 0x00000001; public static final int FITTING_MODE_NONE = 1 << 0;
/** Fitting mode: Fit the content to the page. */ /** Fitting mode: Scale the content to fit in the page
public static final int FITTING_MODE_FIT_TO_PAGE = 0x00000002; * without cropping it in any dimension. */
public static final int FITTING_MODE_SCALE_TO_FIT = 1 << 1;
/**
* Fitting mode: Uniformly scale the content to fill the entire page
* potentially cropping the content if it overflows in one dimension.
*/
public static final int FITTING_MODE_SCALE_TO_FILL = 1 << 2;
private static final int VALID_DUPLEX_MODES = private static final int VALID_DUPLEX_MODES =
@ -62,7 +68,7 @@ public final class PrintAttributes implements Parcelable {
COLOR_MODE_MONOCHROME | COLOR_MODE_COLOR; COLOR_MODE_MONOCHROME | COLOR_MODE_COLOR;
private static final int VALID_FITTING_MODES = private static final int VALID_FITTING_MODES =
FITTING_MODE_NONE | FITTING_MODE_FIT_TO_PAGE; FITTING_MODE_NONE | FITTING_MODE_SCALE_TO_FIT | FITTING_MODE_SCALE_TO_FILL;
private static final int VALID_ORIENTATIONS = private static final int VALID_ORIENTATIONS =
ORIENTATION_PORTRAIT | ORIENTATION_LANDSCAPE; ORIENTATION_PORTRAIT | ORIENTATION_LANDSCAPE;
@ -252,7 +258,8 @@ public final class PrintAttributes implements Parcelable {
* @return The fitting mode or zero if not set. * @return The fitting mode or zero if not set.
* *
* @see #FITTING_MODE_NONE * @see #FITTING_MODE_NONE
* @see #FITTING_MODE_FIT_TO_PAGE * @see #FITTING_MODE_SCALE_TO_FILL
* @see #FITTING_MODE_SCALE_TO_FIT
*/ */
public int getFittingMode() { public int getFittingMode() {
return mFittingMode; return mFittingMode;
@ -264,12 +271,13 @@ public final class PrintAttributes implements Parcelable {
* @param The fitting mode. * @param The fitting mode.
* *
* @see #FITTING_MODE_NONE * @see #FITTING_MODE_NONE
* @see #FITTING_MODE_FIT_TO_PAGE * @see #FITTING_MODE_SCALE_TO_FILL
* @see #FITTING_MODE_SCALE_TO_FIT
* *
* @hide * @hide
*/ */
public void setFittingMode(int fittingMode) { public void setFittingMode(int fittingMode) {
enfoceValidFittingMode(fittingMode); enforceValidFittingMode(fittingMode);
mFittingMode = fittingMode; mFittingMode = fittingMode;
} }
@ -1220,6 +1228,8 @@ public final class PrintAttributes implements Parcelable {
* This class specifies content margins. * This class specifies content margins.
*/ */
public static final class Margins { public static final class Margins {
public static final Margins NO_MARGINS = new Margins(0, 0, 0, 0);
private final int mLeftMils; private final int mLeftMils;
private final int mTopMils; private final int mTopMils;
private final int mRightMils; private final int mRightMils;
@ -1232,24 +1242,13 @@ public final class PrintAttributes implements Parcelable {
* @param topMils The top margin in mils (thousands of an inch). * @param topMils The top margin in mils (thousands of an inch).
* @param rightMils The right margin in mils (thousands of an inch). * @param rightMils The right margin in mils (thousands of an inch).
* @param bottomMils The bottom margin in mils (thousands of an inch). * @param bottomMils The bottom margin in mils (thousands of an inch).
*
* @throws IllegalArgumentException If the leftMils is less than zero.
* @throws IllegalArgumentException If the topMils is less than zero.
* @throws IllegalArgumentException If the rightMils is less than zero.
* @throws IllegalArgumentException If the bottomMils is less than zero.
*/ */
public Margins(int leftMils, int topMils, int rightMils, int bottomMils) { public Margins(int leftMils, int topMils, int rightMils, int bottomMils) {
if (leftMils < 0) { if (leftMils > rightMils) {
throw new IllegalArgumentException("leftMils cannot be less than zero."); throw new IllegalArgumentException("leftMils cannot be less than rightMils.");
} }
if (topMils < 0) { if (topMils > bottomMils) {
throw new IllegalArgumentException("topMils cannot be less than zero."); throw new IllegalArgumentException("topMils cannot be less than bottomMils.");
}
if (rightMils < 0) {
throw new IllegalArgumentException("rightMils cannot be less than zero.");
}
if (bottomMils < 0) {
throw new IllegalArgumentException("bottomMils cannot be less than zero.");
} }
mTopMils = topMils; mTopMils = topMils;
mLeftMils = leftMils; mLeftMils = leftMils;
@ -1504,8 +1503,11 @@ public final class PrintAttributes implements Parcelable {
case FITTING_MODE_NONE: { case FITTING_MODE_NONE: {
return "FITTING_MODE_NONE"; return "FITTING_MODE_NONE";
} }
case FITTING_MODE_FIT_TO_PAGE: { case FITTING_MODE_SCALE_TO_FIT: {
return "FITTING_MODE_FIT_TO_PAGE"; return "FITTING_MODE_SCALE_TO_FIT";
}
case FITTING_MODE_SCALE_TO_FILL: {
return "FITTING_MODE_SCALE_TO_FILL";
} }
default: default:
return "FITTING_MODE_UNKNOWN"; return "FITTING_MODE_UNKNOWN";
@ -1513,25 +1515,25 @@ public final class PrintAttributes implements Parcelable {
} }
static void enforceValidDuplexMode(int duplexMode) { static void enforceValidDuplexMode(int duplexMode) {
if ((duplexMode & VALID_DUPLEX_MODES) == 0) { if ((duplexMode & VALID_DUPLEX_MODES) == 0 && Integer.bitCount(duplexMode) == 1) {
throw new IllegalArgumentException("invalid duplex mode: " + duplexMode); throw new IllegalArgumentException("invalid duplex mode: " + duplexMode);
} }
} }
static void enforceValidColorMode(int colorMode) { static void enforceValidColorMode(int colorMode) {
if ((colorMode & VALID_COLOR_MODES) == 0) { if ((colorMode & VALID_COLOR_MODES) == 0 && Integer.bitCount(colorMode) == 1) {
throw new IllegalArgumentException("invalid color mode: " + colorMode); throw new IllegalArgumentException("invalid color mode: " + colorMode);
} }
} }
static void enfoceValidFittingMode(int fittingMode) { static void enforceValidFittingMode(int fittingMode) {
if ((fittingMode & VALID_FITTING_MODES) == 0) { if ((fittingMode & VALID_FITTING_MODES) == 0 && Integer.bitCount(fittingMode) == 1) {
throw new IllegalArgumentException("invalid fitting mode: " + fittingMode); throw new IllegalArgumentException("invalid fitting mode: " + fittingMode);
} }
} }
static void enforceValidOrientation(int orientation) { static void enforceValidOrientation(int orientation) {
if ((orientation & VALID_ORIENTATIONS) == 0) { if ((orientation & VALID_ORIENTATIONS) == 0 && Integer.bitCount(orientation) == 1) {
throw new IllegalArgumentException("invalid orientation: " + orientation); throw new IllegalArgumentException("invalid orientation: " + orientation);
} }
} }

View File

@ -101,6 +101,28 @@ public abstract class PrintDocumentAdapter {
* LayoutResultCallback#onLayoutFailed(CharSequence)}, if an error occurred. * LayoutResultCallback#onLayoutFailed(CharSequence)}, if an error occurred.
* </p> * </p>
* <p> * <p>
* When doing a layout you may satisfy some of the constraints in the print
* attributes such as applying the appropriate fitting, emitting content in the
* requested orientation, using the specified margins, generating content with
* the desired color mode, producing output with the given media size. Ideally,
* you will satisfy all of these constraints. It is important that if you
* satisfy a given constraint, you update the {@link PrintDocumentInfo} that
* is returned in the given {@link LayoutResultCallback}. This way the printer
* will have more accurate information about the content, thus producing a
* better output. For example, assume that your application is printing
* an image and the print attributes request landscape and fitting mode scale
* to fill. The result of this operation should be the entire media is filled
* and the content is rotated ninety degrees. In this case it is beneficial
* you do the rotation and select a higher resolution image to utilize
* the wider media (the height is now the width), rather to use a lower
* resolution image that is later stretched by the printer. If you applied
* the rotation you have to update the returned print document info to
* reflect that the content is already in landscape by calling
* {@link PrintDocumentInfo.Builder#setOrientation(int)} with {@link
* PrintAttributes#ORIENTATION_LANDSCAPE}. In this case the printer does not
* have to rotate the content.
* </p>
* <p>
* <strong>Note:</strong> If the content is large and a layout will be * <strong>Note:</strong> If the content is large and a layout will be
* performed, it is a good practice to schedule the work on a dedicated * performed, it is a good practice to schedule the work on a dedicated
* thread and register an observer in the provided {@link * thread and register an observer in the provided {@link

View File

@ -18,6 +18,8 @@ package android.print;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import android.print.PrintAttributes.Margins;
import android.print.PrintAttributes.MediaSize;
import android.text.TextUtils; import android.text.TextUtils;
/** /**
@ -26,12 +28,17 @@ import android.text.TextUtils;
public final class PrintDocumentInfo implements Parcelable { public final class PrintDocumentInfo implements Parcelable {
/** /**
* Constant for unknown page count (default). * Constant for an unknown media size.
*/
public static final MediaSize MEDIA_SIZE_UNKNOWN = new MediaSize("Unknown", "Unknown", 1, 1);
/**
* Constant for unknown page count..
*/ */
public static final int PAGE_COUNT_UNKNOWN = -1; public static final int PAGE_COUNT_UNKNOWN = -1;
/** /**
* Content type: unknown (default). * Content type: unknown.
*/ */
public static final int CONTENT_TYPE_UNKNOWN = -1; public static final int CONTENT_TYPE_UNKNOWN = -1;
@ -48,13 +55,17 @@ public final class PrintDocumentInfo implements Parcelable {
private String mName; private String mName;
private int mPageCount; private int mPageCount;
private int mContentType; private int mContentType;
private int mOrientation;
private int mFittingMode;
private int mColorMode;
private Margins mMargins;
private MediaSize mMediaSize;
/** /**
* Creates a new instance. * Creates a new instance.
*/ */
private PrintDocumentInfo() { private PrintDocumentInfo() {
mPageCount = PAGE_COUNT_UNKNOWN; /* do nothing */
mContentType = CONTENT_TYPE_UNKNOWN;
} }
/** /**
@ -66,6 +77,11 @@ public final class PrintDocumentInfo implements Parcelable {
mName = prototype.mName; mName = prototype.mName;
mPageCount = prototype.mPageCount; mPageCount = prototype.mPageCount;
mContentType = prototype.mContentType; mContentType = prototype.mContentType;
mOrientation = prototype.mOrientation;
mFittingMode = prototype.mFittingMode;
mColorMode = prototype.mColorMode;
mMargins = prototype.mMargins;
mMediaSize = prototype.mMediaSize;
} }
/** /**
@ -77,6 +93,11 @@ public final class PrintDocumentInfo implements Parcelable {
mName = parcel.readString(); mName = parcel.readString();
mPageCount = parcel.readInt(); mPageCount = parcel.readInt();
mContentType = parcel.readInt(); mContentType = parcel.readInt();
mOrientation = parcel.readInt();
mFittingMode = parcel.readInt();
mColorMode = parcel.readInt();
mMargins = Margins.createFromParcel(parcel);
mMediaSize = MediaSize.createFromParcel(parcel);
} }
/** /**
@ -112,6 +133,61 @@ public final class PrintDocumentInfo implements Parcelable {
return mContentType; return mContentType;
} }
/**
* Gets the document orientation.
*
* @return The orientation.
*
* @see PrintAttributes#ORIENTATION_PORTRAIT PrintAttributes.ORIENTATION_PORTRAIT
* @see PrintAttributes#ORIENTATION_LANDSCAPE PrintAttributes.ORIENTATION_LANDSCAPE
*/
public int getOrientation() {
return mOrientation;
}
/**
* Gets the document fitting mode.
*
* @return The fitting mode.
*
* @see PrintAttributes#FITTING_MODE_NONE PrintAttributes.FITTING_MODE_NONE
* @see PrintAttributes#FITTING_MODE_SCALE_TO_FILL PrintAttributes.FITTING_MODE_SCALE_TO_FILL
* @see PrintAttributes#FITTING_MODE_SCALE_TO_FIT PrintAttributes.FITTING_MODE_SCALE_TO_FIT
*/
public int getFittingMode() {
return mFittingMode;
}
/**
* Gets document color mode.
*
* @return The color mode.
*
* @see PrintAttributes#COLOR_MODE_COLOR PrintAttributes.COLOR_MODE_COLOR
* @see PrintAttributes#COLOR_MODE_MONOCHROME PrintAttributes.COLOR_MODE_MONOCHROME
*/
public int getColorMode() {
return mColorMode;
}
/**
* Gets the document margins.
*
* @return The margins.
*/
public Margins getMargins() {
return mMargins;
}
/**
* Gets the media size.
*
* @return The media size.
*/
public MediaSize getMediaSize() {
return mMediaSize;
}
@Override @Override
public int describeContents() { public int describeContents() {
return 0; return 0;
@ -122,6 +198,11 @@ public final class PrintDocumentInfo implements Parcelable {
parcel.writeString(mName); parcel.writeString(mName);
parcel.writeInt(mPageCount); parcel.writeInt(mPageCount);
parcel.writeInt(mContentType); parcel.writeInt(mContentType);
parcel.writeInt(mOrientation);
parcel.writeInt(mFittingMode);
parcel.writeInt(mColorMode);
mMargins.writeToParcel(parcel);
mMediaSize.writeToParcel(parcel);
} }
@Override @Override
@ -131,6 +212,11 @@ public final class PrintDocumentInfo implements Parcelable {
result = prime * result + ((mName != null) ? mName.hashCode() : 0); result = prime * result + ((mName != null) ? mName.hashCode() : 0);
result = prime * result + mContentType; result = prime * result + mContentType;
result = prime * result + mPageCount; result = prime * result + mPageCount;
result = prime * result + mOrientation;
result = prime * result + mFittingMode;
result = prime * result + mColorMode;
result = prime * result + (mMargins != null ? mMargins.hashCode() : 0);
result = prime * result + (mMediaSize != null ? mMediaSize.hashCode() : 0);
return result; return result;
} }
@ -155,6 +241,29 @@ public final class PrintDocumentInfo implements Parcelable {
if (mPageCount != other.mPageCount) { if (mPageCount != other.mPageCount) {
return false; return false;
} }
if (mOrientation != other.mOrientation) {
return false;
}
if (mFittingMode != other.mFittingMode) {
return false;
}
if (mColorMode != other.mColorMode) {
return false;
}
if (mMargins == null) {
if (other.mMargins != null) {
return false;
}
} else if (!mMargins.equals(other.mMargins)) {
return false;
}
if (mMediaSize == null) {
if (other.mMediaSize != null) {
return false;
}
} else if (!mMediaSize.equals(other.mMediaSize)) {
return false;
}
return true; return true;
} }
@ -165,6 +274,11 @@ public final class PrintDocumentInfo implements Parcelable {
builder.append("name=").append(mName); builder.append("name=").append(mName);
builder.append(", pageCount=").append(mPageCount); builder.append(", pageCount=").append(mPageCount);
builder.append(", contentType=").append(contentTyepToString(mContentType)); builder.append(", contentType=").append(contentTyepToString(mContentType));
builder.append(", orientation=").append(PrintAttributes.orientationToString(mOrientation));
builder.append(", fittingMode=").append(PrintAttributes.fittingModeToString(mFittingMode));
builder.append(", colorMode=").append(PrintAttributes.colorModeToString(mColorMode));
builder.append(", margins=").append(mMargins);
builder.append(", mediaSize=").append(mMediaSize);
builder.append("}"); builder.append("}");
return builder.toString(); return builder.toString();
} }
@ -191,21 +305,62 @@ public final class PrintDocumentInfo implements Parcelable {
/** /**
* Constructor. * Constructor.
* <p>
* The values of the relevant properties are initialized from the
* provided print attributes. For example, the orientation is set
* to be the same as the orientation returned by calling {@link
* PrintAttributes#getOrientation() PrintAttributes.getOrientation()}.
* </p>
* *
* @param name The document name. Cannot be empty. * @param name The document name. Cannot be empty.
* @param attributes Print attributes. Cannot be null.
* *
* @throws IllegalArgumentException If the name is empty. * @throws IllegalArgumentException If the name is empty.
*/ */
public Builder(String name, PrintAttributes attributes) {
if (TextUtils.isEmpty(name)) {
throw new IllegalArgumentException("name cannot be empty");
}
if (attributes == null) {
throw new IllegalArgumentException("attributes cannot be null");
}
mPrototype = new PrintDocumentInfo();
mPrototype.mName = name;
mPrototype.mOrientation = attributes.getOrientation();
mPrototype.mFittingMode = attributes.getFittingMode();
mPrototype.mColorMode = attributes.getColorMode();
mPrototype.mMargins = attributes.getMargins();
mPrototype.mMediaSize = attributes.getMediaSize();
}
/**
* Constructor.
* <p>
* The values of the relevant properties are initialized with default
* values. Please refer to the documentation of the individual setters
* for information about the default values.
* </p>
*
* @param name The document name. Cannot be empty.
*/
public Builder(String name) { public Builder(String name) {
if (TextUtils.isEmpty(name)) { if (TextUtils.isEmpty(name)) {
throw new IllegalArgumentException("name cannot be empty"); throw new IllegalArgumentException("name cannot be empty");
} }
mPrototype = new PrintDocumentInfo(); mPrototype = new PrintDocumentInfo();
mPrototype.mName = name; mPrototype.mName = name;
mPrototype.mOrientation = PrintAttributes.ORIENTATION_PORTRAIT;
mPrototype.mFittingMode = PrintAttributes.FITTING_MODE_NONE;
mPrototype.mColorMode = PrintAttributes.COLOR_MODE_COLOR;
mPrototype.mMargins = Margins.NO_MARGINS;
mPrototype.mMediaSize = MEDIA_SIZE_UNKNOWN;
} }
/** /**
* Sets the total number of pages. * Sets the total number of pages.
* <p>
* <strong>Default: </strong> {@link #PAGE_COUNT_UNKNOWN}
* </p>
* *
* @param pageCount The number of pages. Must be greater than * @param pageCount The number of pages. Must be greater than
* or equal to zero or {@link PrintDocumentInfo#PAGE_COUNT_UNKNOWN}. * or equal to zero or {@link PrintDocumentInfo#PAGE_COUNT_UNKNOWN}.
@ -222,6 +377,9 @@ public final class PrintDocumentInfo implements Parcelable {
/** /**
* Sets the content type. * Sets the content type.
* <p>
* <strong>Default: </strong> {@link #CONTENT_TYPE_UNKNOWN}
* </p>
* *
* @param type The content type. * @param type The content type.
* *
@ -234,6 +392,95 @@ public final class PrintDocumentInfo implements Parcelable {
return this; return this;
} }
/**
* Sets the orientation.
* <p>
* <strong>Default: </strong> {@link PrintAttributes#ORIENTATION_PORTRAIT
* PrintAttributes.ORIENTATION_PORTRAIT}
* </p>
*
* @param orientation The orientation.
*
* @see PrintAttributes#ORIENTATION_PORTRAIT PrintAttributes.ORIENTATION_PORTRAIT
* @see PrintAttributes#ORIENTATION_LANDSCAPE PrintAttributes.ORIENTATION_LANDSCAPE
*/
public Builder setOrientation(int orientation) {
PrintAttributes.enforceValidOrientation(orientation);
mPrototype.mOrientation = orientation;
return this;
}
/**
* Sets the content fitting mode.
* <p>
* <strong>Default: </strong> {@link PrintAttributes#FITTING_MODE_NONE
* PrintAttributes.FITTING_MODE_NONE}
* </p>
*
* @param fittingMode The fitting mode.
*
* @see PrintAttributes#FITTING_MODE_NONE PrintAttributes.FITTING_MODE_NONE
* @see PrintAttributes#FITTING_MODE_SCALE_TO_FILL PrintAttributes.FITTING_MODE_SCALE_TO_FILL
* @see PrintAttributes#FITTING_MODE_SCALE_TO_FIT PrintAttributes.FITTING_MODE_SCALE_TO_FIT
*/
public Builder setFittingMode(int fittingMode) {
PrintAttributes.enforceValidFittingMode(fittingMode);
mPrototype.mFittingMode = fittingMode;
return this;
}
/**
* Sets the content color mode.
* <p>
* <strong>Default: </strong> {@link PrintAttributes#COLOR_MODE_COLOR
* PrintAttributes.COLOR_MODE_COLOR}
* </p>
*
* @param colorMode The color mode.
*
* @see PrintAttributes#COLOR_MODE_COLOR PrintAttributes.COLOR_MODE_COLOR
* @see PrintAttributes#COLOR_MODE_MONOCHROME PrintAttributes.COLOR_MODE_MONOCHROME
*/
public Builder setColorMode(int colorMode) {
PrintAttributes.enforceValidColorMode(colorMode);
mPrototype.mColorMode = colorMode;
return this;
}
/**
* Sets the document margins.
* <p>
* <strong>Default: </strong> {@link PrintAttributes.Margins#NO_MARGINS Margins.NO_MARGINS}
* </p>
*
* @param margins The margins. Cannot be null.
*/
public Builder setMargins(Margins margins) {
if (margins == null) {
throw new IllegalArgumentException("margins cannot be null");
}
mPrototype.mMargins = margins;
return this;
}
/**
* Sets the document media size.
* <p>
* <strong>Default: </strong>#MEDIA_SIZE_UNKNOWN
* </p>
*
* @param mediaSize The media size. Cannot be null.
*
* @see #MEDIA_SIZE_UNKNOWN
*/
public Builder setMediaSize(MediaSize mediaSize) {
if (mediaSize == null) {
throw new IllegalArgumentException("media size cannot be null");
}
mPrototype.mMediaSize = mediaSize;
return this;
}
/** /**
* Creates a new {@link PrintDocumentInfo} instance. * Creates a new {@link PrintDocumentInfo} instance.
* *

View File

@ -863,12 +863,12 @@ public final class PrinterCapabilitiesInfo implements Parcelable {
while (currentModes > 0) { while (currentModes > 0) {
final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes)); final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
currentModes &= ~currentMode; currentModes &= ~currentMode;
PrintAttributes.enfoceValidFittingMode(currentMode); PrintAttributes.enforceValidFittingMode(currentMode);
} }
if ((fittingModes & defaultFittingMode) == 0) { if ((fittingModes & defaultFittingMode) == 0) {
throw new IllegalArgumentException("Default fitting mode not in fiting modes."); throw new IllegalArgumentException("Default fitting mode not in fiting modes.");
} }
PrintAttributes.enfoceValidFittingMode(defaultFittingMode); PrintAttributes.enforceValidFittingMode(defaultFittingMode);
mPrototype.mFittingModes = fittingModes; mPrototype.mFittingModes = fittingModes;
mPrototype.mDefaults[PROPERTY_FITTING_MODE] = defaultFittingMode; mPrototype.mDefaults[PROPERTY_FITTING_MODE] = defaultFittingMode;
return this; return this;

View File

@ -25,10 +25,14 @@ import android.text.TextUtils;
*/ */
public final class PrinterInfo implements Parcelable { public final class PrinterInfo implements Parcelable {
/** Printer status: the printer is ready to print. */ /** Printer status: the printer is idle and ready to print. */
public static final int STATUS_READY = 1; public static final int STATUS_IDLE = 1;
// TODO: Add printer status constants. /** Printer status: the printer is busy printing. */
public static final int STATUS_BUSY = 2;
/** Printer status: the printer is not available. */
public static final int STATUS_UNAVAILABLE = 3;
private PrinterId mId; private PrinterId mId;
@ -236,6 +240,21 @@ public final class PrinterInfo implements Parcelable {
mPrototype.copyFrom(other); mPrototype.copyFrom(other);
} }
/**
* Sets the printer status.
*
* @param status The status.
* @return This builder.
*
* @see PrinterInfo#STATUS_IDLE
* @see PrinterInfo#STATUS_BUSY
* @see PrinterInfo#STATUS_UNAVAILABLE
*/
public Builder setStatus(int status) {
mPrototype.mStatus = status;
return this;
}
/** /**
* Sets the printer name. * Sets the printer name.
* *
@ -279,7 +298,9 @@ public final class PrinterInfo implements Parcelable {
} }
private boolean isValidStatus(int status) { private boolean isValidStatus(int status) {
return (status == PrinterInfo.STATUS_READY); return (status == STATUS_IDLE
|| status == STATUS_IDLE
|| status == STATUS_UNAVAILABLE);
} }
} }

View File

@ -44,7 +44,7 @@ import java.util.List;
* PdfDocument document = PdfDocument.open(); * PdfDocument document = PdfDocument.open();
* *
* // crate a page description * // crate a page description
* PageInfo pageInfo = new PageInfo.Builder(new Rect(0, 0, 100, 100), 1, 300).create(); * PageInfo pageInfo = new PageInfo.Builder(new Rect(0, 0, 100, 100), 1).create();
* *
* // start a page * // start a page
* Page page = document.startPage(pageInfo); * Page page = document.startPage(pageInfo);
@ -125,8 +125,7 @@ public final class PdfDocument {
throw new IllegalStateException("Previous page not finished!"); throw new IllegalStateException("Previous page not finished!");
} }
Canvas canvas = new PdfCanvas(nativeCreatePage(pageInfo.mPageSize, Canvas canvas = new PdfCanvas(nativeCreatePage(pageInfo.mPageSize,
pageInfo.mContentSize, pageInfo.mInitialTransform.native_instance), pageInfo.mContentSize, pageInfo.mInitialTransform.native_instance));
pageInfo.mDensity);
mCurrentPage = new Page(canvas, pageInfo); mCurrentPage = new Page(canvas, pageInfo);
return mCurrentPage; return mCurrentPage;
} }
@ -230,25 +229,14 @@ public final class PdfDocument {
private final class PdfCanvas extends Canvas { private final class PdfCanvas extends Canvas {
public PdfCanvas(int nativeCanvas, int density) { public PdfCanvas(int nativeCanvas) {
super(nativeCanvas); super(nativeCanvas);
super.setDensity(density);
} }
@Override @Override
public void setBitmap(Bitmap bitmap) { public void setBitmap(Bitmap bitmap) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public void setDensity(int density) {
throw new UnsupportedOperationException();
}
@Override
public void setScreenDensity(int density) {
throw new UnsupportedOperationException();
}
} }
/** /**
@ -259,7 +247,6 @@ public final class PdfDocument {
private Rect mContentSize; private Rect mContentSize;
private Matrix mInitialTransform; private Matrix mInitialTransform;
private int mPageNumber; private int mPageNumber;
private int mDensity;
/** /**
* Creates a new instance. * Creates a new instance.
@ -269,7 +256,7 @@ public final class PdfDocument {
} }
/** /**
* Gets the page size in pixels. * Gets the page size in PostScript points (1/72th of an inch).
* *
* @return The page size. * @return The page size.
*/ */
@ -278,7 +265,7 @@ public final class PdfDocument {
} }
/** /**
* Get the content size in pixels. * Get the content size in PostScript points (1/72th of an inch).
* *
* @return The content size. * @return The content size.
*/ */
@ -306,15 +293,6 @@ public final class PdfDocument {
return mPageNumber; return mPageNumber;
} }
/**
* Gets the density of the page in DPI.
*
* @return The density.
*/
public int getDesity() {
return mDensity;
}
/** /**
* Builder for creating a {@link PageInfo}. * Builder for creating a {@link PageInfo}.
*/ */
@ -324,11 +302,10 @@ public final class PdfDocument {
/** /**
* Creates a new builder with the mandatory page info attributes. * Creates a new builder with the mandatory page info attributes.
* *
* @param pageSize The page size in points, <strong>not</strong> dips. * @param pageSize The page size in PostScript (1/72th of an inch).
* @param pageNumber The page number. * @param pageNumber The page number.
* @param density The page density in DPI.
*/ */
public Builder(Rect pageSize, int pageNumber, int density) { public Builder(Rect pageSize, int pageNumber) {
if (pageSize.width() == 0 || pageSize.height() == 0) { if (pageSize.width() == 0 || pageSize.height() == 0) {
throw new IllegalArgumentException("page width and height" + throw new IllegalArgumentException("page width and height" +
" must be greater than zero!"); " must be greater than zero!");
@ -336,16 +313,12 @@ public final class PdfDocument {
if (pageNumber < 0) { if (pageNumber < 0) {
throw new IllegalArgumentException("pageNumber cannot be less than zero!"); throw new IllegalArgumentException("pageNumber cannot be less than zero!");
} }
if (density <= 0) {
throw new IllegalArgumentException("density must be greater than zero!");
}
mPageInfo.mPageSize = pageSize; mPageInfo.mPageSize = pageSize;
mPageInfo.mPageNumber = pageNumber; mPageInfo.mPageNumber = pageNumber;
mPageInfo.mDensity = density;
} }
/** /**
* Sets the content size in pixels. * Sets the content size in PostScript point (1/72th of an inch).
* *
* @param contentSize The content size. * @param contentSize The content size.
*/ */

View File

@ -0,0 +1,162 @@
/*
* Copyright (C) 2013 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.
*/
package android.print.pdf;
import android.content.Context;
import android.graphics.Rect;
import android.print.PrintAttributes;
import android.print.PrintAttributes.Margins;
import android.print.PrintAttributes.MediaSize;
import android.print.pdf.PdfDocument;
import android.print.pdf.PdfDocument.Page;
import android.print.pdf.PdfDocument.PageInfo;
import java.io.OutputStream;
import java.util.List;
/**
* This class is a helper for printing content to a different media
* size. This class is responsible for computing a correct page size
* given some print constraints, i.e. {@link PrintAttributes}. It is
* an adapter around a {@link PdfDocument}.
*/
public final class PrintedPdfDocument {
private static final int MILS_PER_INCH = 1000;
private static final int POINTS_IN_INCH = 72;
private final PdfDocument mDocument = PdfDocument.open();
private final Rect mPageSize = new Rect();
private final Rect mContentSize = new Rect();
/**
* Opens a new document. The document pages are computed based on
* the passes in {@link PrintAttributes}.
* <p>
* <strong>Note:</strong> You must close the document after you are
* done by calling {@link #close()}
* </p>
*
* @param context Context instance for accessing resources.
* @param attributes The print attributes.
* @return The document.
*
* @see #close()
*/
public static PrintedPdfDocument open(Context context, PrintAttributes attributes) {
return new PrintedPdfDocument(context, attributes);
}
/**
* Creates a new instance.
*
* @param context Context instance for accessing resources and services.
* @param attributes The {@link PrintAttributes} to user.
*/
private PrintedPdfDocument(Context context, PrintAttributes attributes) {
MediaSize mediaSize = attributes.getMediaSize();
// Compute the size of the target canvas from the attributes.
final int pageWidth = (int) (((float) mediaSize.getWidthMils() / MILS_PER_INCH)
* POINTS_IN_INCH);
final int pageHeight = (int) (((float) mediaSize.getHeightMils() / MILS_PER_INCH)
* POINTS_IN_INCH);
mPageSize.set(0, 0, pageWidth, pageHeight);
// Compute the content size from the attributes.
Margins margins = attributes.getMargins();
final int marginLeft = (int) (((float) margins.getLeftMils() /MILS_PER_INCH)
* POINTS_IN_INCH);
final int marginTop = (int) (((float) margins.getTopMils() / MILS_PER_INCH)
* POINTS_IN_INCH);
final int marginRight = (int) (((float) margins.getRightMils() / MILS_PER_INCH)
* POINTS_IN_INCH);
final int marginBottom = (int) (((float) margins.getBottomMils() / MILS_PER_INCH)
* POINTS_IN_INCH);
mContentSize.set(mPageSize.left + marginLeft, mPageSize.top + marginTop,
mPageSize.right - marginRight, mPageSize.bottom - marginBottom);
}
/**
* Starts a page using a page size computed from the print attributes
* passed in {@link #open(Context, PrintAttributes)} and the given page
* number to create appropriate {@link PageInfo}.
* <p>
* After the page is created you can draw arbitrary content on the page's
* canvas which you can get by calling {@link Page#getCanvas() Page.getCanvas()}.
* After you are done drawing the content you should finish the page by calling
* {@link #finishPage(Page)}. After the page is finished you should no longer
* access the page or its canvas.
* </p>
* <p>
* <strong>Note:</strong> Do not call this method after {@link #close()}.
* </p>
*
* @param pageNumber The page number.
* @return A blank page.
*
* @see #finishPage(Page)
*/
public Page startPage(int pageNumber) {
PageInfo pageInfo = new PageInfo.Builder(mPageSize, 0).create();
Page page = mDocument.startPage(pageInfo);
return page;
}
/**
* Finishes a started page. You should always finish the last started page.
* <p>
* <strong>Note:</strong> Do not call this method after {@link #close()}.
* </p>
*
* @param page The page.
*
* @see #startPage(int)
*/
public void finishPage(Page page) {
mDocument.finishPage(page);
}
/**
* Writes the document to an output stream.
* <p>
* <strong>Note:</strong> Do not call this method after {@link #close()}.
* </p>
*
* @param out The output stream.
*/
public void writeTo(OutputStream out) {
mDocument.writeTo(out);
}
/**
* Gets the pages of the document.
*
* @return The pages.
*/
public List<PageInfo> getPages() {
return mDocument.getPages();
}
/**
* Closes this document. This method should be called after you
* are done working with the document. After this call the document
* is considered closed and none of its methods should be called.
*/
public void close() {
mDocument.close();
}
}

View File

@ -42,6 +42,7 @@ import android.print.IPrintDocumentAdapter;
import android.print.IWriteResultCallback; import android.print.IWriteResultCallback;
import android.print.PageRange; import android.print.PageRange;
import android.print.PrintAttributes; import android.print.PrintAttributes;
import android.print.PrintAttributes.Margins;
import android.print.PrintAttributes.MediaSize; import android.print.PrintAttributes.MediaSize;
import android.print.PrintAttributes.Resolution; import android.print.PrintAttributes.Resolution;
import android.print.PrintDocumentAdapter; import android.print.PrintDocumentAdapter;
@ -388,14 +389,20 @@ public class PrintJobConfigActivity extends Activity {
final boolean infoChanged = !info.equals(mDocument.info); final boolean infoChanged = !info.equals(mDocument.info);
if (infoChanged) { if (infoChanged) {
mDocument.info = info; mDocument.info = info;
// Set the info.
PrintSpoolerService.peekInstance().setPrintJobPrintDocumentInfoNoPersistence( PrintSpoolerService.peekInstance().setPrintJobPrintDocumentInfoNoPersistence(
mPrintJobId, info); mPrintJobId, info);
} }
// Update the fitting mode based on the document type.
updateCurrentFittingMode(info);
// If the document info or the layout changed, then // If the document info or the layout changed, then
// drop the pages since we have to fetch them again. // drop the pages since we have to fetch them again.
if (infoChanged || layoutChanged) { if (infoChanged || layoutChanged) {
mDocument.pages = null; mDocument.pages = null;
PrintSpoolerService.peekInstance().setPrintJobPagesNoPersistence(
mPrintJobId, null);
} }
// No pages means that the user selected an invalid range while we // No pages means that the user selected an invalid range while we
@ -489,7 +496,7 @@ public class PrintJobConfigActivity extends Activity {
} else if (PageRangeUtils.contains(mDocument.pages, mRequestedPages)) { } else if (PageRangeUtils.contains(mDocument.pages, mRequestedPages)) {
// We requested specific pages and got more but not all pages. // We requested specific pages and got more but not all pages.
// Hence, we have to offset appropriately the printed pages to // Hence, we have to offset appropriately the printed pages to
// excle the pages we did not request. Note that pages is // exclude the pages we did not request. Note that pages is
// guaranteed to be not null and not empty. // guaranteed to be not null and not empty.
final int offset = mDocument.pages[0].getStart() - pages[0].getStart(); final int offset = mDocument.pages[0].getStart() - pages[0].getStart();
PageRange[] offsetPages = Arrays.copyOf(mDocument.pages, mDocument.pages.length); PageRange[] offsetPages = Arrays.copyOf(mDocument.pages, mDocument.pages.length);
@ -514,6 +521,10 @@ public class PrintJobConfigActivity extends Activity {
} }
if (mEditor.isDone()) { if (mEditor.isDone()) {
// Update the print attributes based on whether the application
// handled some of the print attribute constraints, e.g. rotation.
updateAndSaveCurrentPrintAttributes(mDocument.info);
if (mEditor.isPrintingToPdf()) { if (mEditor.isPrintingToPdf()) {
PrintJobInfo printJob = PrintSpoolerService.peekInstance() PrintJobInfo printJob = PrintSpoolerService.peekInstance()
.getPrintJobInfo(mPrintJobId, PrintManager.APP_ID_ANY); .getPrintJobInfo(mPrintJobId, PrintManager.APP_ID_ANY);
@ -536,6 +547,58 @@ public class PrintJobConfigActivity extends Activity {
PrintJobConfigActivity.this.finish(); PrintJobConfigActivity.this.finish();
} }
private void updateCurrentFittingMode(PrintDocumentInfo document) {
// Update the fitting mode based on content type.
switch (document.getContentType()) {
case PrintDocumentInfo.CONTENT_TYPE_DOCUMENT: {
mCurrPrintAttributes.setFittingMode(
PrintAttributes.FITTING_MODE_SCALE_TO_FIT);
} break;
case PrintDocumentInfo.CONTENT_TYPE_PHOTO: {
mCurrPrintAttributes.setFittingMode(
PrintAttributes.FITTING_MODE_SCALE_TO_FILL);
}
}
}
private void updateAndSaveCurrentPrintAttributes(PrintDocumentInfo document) {
PrintAttributes attributes = mTempPrintAttributes;
attributes.copyFrom(mCurrPrintAttributes);
// Update the orientation
if (document.getOrientation() == PrintAttributes.ORIENTATION_LANDSCAPE) {
if (attributes.getOrientation() == PrintAttributes.ORIENTATION_LANDSCAPE) {
// If the document is in landscape and we want to print it in
// landscape, then we do not need to rotate, so portrait.
attributes.setOrientation(PrintAttributes.ORIENTATION_PORTRAIT);
} else {
// If the document is in landscape and we want to print it in
// portrait, then we have to rotate the content, so landscape.
attributes.setOrientation(PrintAttributes.ORIENTATION_LANDSCAPE);
}
}
// Update margins.
Margins documentMargins = document.getMargins();
if (documentMargins.getLeftMils() != 0
|| documentMargins.getTopMils() != 0
|| documentMargins.getRightMils() != 0
|| documentMargins.getBottomMils() != 0) {
// If the application has applied some of the margins, then
// the printer should only apply the difference.
Margins oldMargins = attributes.getMargins();
attributes.setMargins(new Margins(
oldMargins.getLeftMils() - documentMargins.getLeftMils(),
oldMargins.getTopMils() - documentMargins.getTopMils(),
oldMargins.getRightMils() - documentMargins.getRightMils(),
oldMargins.getBottomMils() - documentMargins.getBottomMils()));
}
PrintSpoolerService.peekInstance().setPrintJobAttributesNoPersistence(
mPrintJobId, attributes);
}
private final class ControllerHandler extends Handler { private final class ControllerHandler extends Handler {
public static final int MSG_ON_LAYOUT_FINISHED = 1; public static final int MSG_ON_LAYOUT_FINISHED = 1;
public static final int MSG_ON_LAYOUT_FAILED = 2; public static final int MSG_ON_LAYOUT_FAILED = 2;
@ -1409,8 +1472,6 @@ public class PrintJobConfigActivity extends Activity {
mOrientationSpinner.setEnabled(false); mOrientationSpinner.setEnabled(false);
mRangeOptionsSpinner.setEnabled(false); mRangeOptionsSpinner.setEnabled(false);
mPageRangeEditText.setEnabled(false); mPageRangeEditText.setEnabled(false);
// TODO: Remove entirely or implement print preview.
// mPrintPreviewButton.setEnabled(false);
mPrintButton.setEnabled(false); mPrintButton.setEnabled(false);
return false; return false;
} }
@ -1474,10 +1535,6 @@ public class PrintJobConfigActivity extends Activity {
mPageRangeEditText.setVisibility(View.INVISIBLE); mPageRangeEditText.setVisibility(View.INVISIBLE);
mPageRangeTitle.setVisibility(View.INVISIBLE); mPageRangeTitle.setVisibility(View.INVISIBLE);
// // Print preview
// mPrintPreviewButton.setEnabled(false);
// mPrintPreviewButton.setText(getString(R.string.print_preview));
// Print // Print
mPrintButton.setEnabled(false); mPrintButton.setEnabled(false);
@ -1548,6 +1605,8 @@ public class PrintJobConfigActivity extends Activity {
// Color mode. // Color mode.
final int colorModes = capabilities.getColorModes(); final int colorModes = capabilities.getColorModes();
// If the color modes changed, we update the adapter and the spinner.
boolean colorModesChanged = false; boolean colorModesChanged = false;
if (Integer.bitCount(colorModes) != mColorModeSpinnerAdapter.getCount()) { if (Integer.bitCount(colorModes) != mColorModeSpinnerAdapter.getCount()) {
colorModesChanged = true; colorModesChanged = true;
@ -1567,6 +1626,11 @@ public class PrintJobConfigActivity extends Activity {
} }
} }
if (colorModesChanged) { if (colorModesChanged) {
// Remember the old color mode to try selecting it again.
int oldColorModeNewIndex = AdapterView.INVALID_POSITION;
final int oldColorMode = mCurrPrintAttributes.getColorMode();
// Rebuild the adapter data.
mColorModeSpinnerAdapter.clear(); mColorModeSpinnerAdapter.clear();
String[] colorModeLabels = getResources().getStringArray( String[] colorModeLabels = getResources().getStringArray(
R.array.color_mode_labels); R.array.color_mode_labels);
@ -1575,6 +1639,10 @@ public class PrintJobConfigActivity extends Activity {
final int colorBitOffset = Integer.numberOfTrailingZeros( final int colorBitOffset = Integer.numberOfTrailingZeros(
remainingColorModes); remainingColorModes);
final int colorMode = 1 << colorBitOffset; final int colorMode = 1 << colorBitOffset;
if (colorMode == oldColorMode) {
// Update the index of the old selection.
oldColorModeNewIndex = colorBitOffset;
}
remainingColorModes &= ~colorMode; remainingColorModes &= ~colorMode;
mColorModeSpinnerAdapter.add(new SpinnerItem<Integer>(colorMode, mColorModeSpinnerAdapter.add(new SpinnerItem<Integer>(colorMode,
colorModeLabels[colorBitOffset])); colorModeLabels[colorBitOffset]));
@ -1585,11 +1653,14 @@ public class PrintJobConfigActivity extends Activity {
mColorModeSpinner.setSelection(AdapterView.INVALID_POSITION); mColorModeSpinner.setSelection(AdapterView.INVALID_POSITION);
} else { } else {
mColorModeSpinner.setEnabled(true); mColorModeSpinner.setEnabled(true);
if (oldColorModeNewIndex != AdapterView.INVALID_POSITION) {
// Select the old color mode - nothing really changed.
setColorModeSpinnerSelectionNoCallback(oldColorModeNewIndex);
} else {
final int selectedColorModeIndex = Integer.numberOfTrailingZeros( final int selectedColorModeIndex = Integer.numberOfTrailingZeros(
(colorModes & defaultAttributes.getColorMode())); (colorModes & defaultAttributes.getColorMode()));
if (mColorModeSpinner.getSelectedItemPosition() != selectedColorModeIndex) { someAttributeSelectionChanged = setColorModeSpinnerSelectionNoCallback(
mIgnoreNextColorModeChange = true; selectedColorModeIndex);
mColorModeSpinner.setSelection(selectedColorModeIndex);
} }
} }
} }
@ -1597,6 +1668,8 @@ public class PrintJobConfigActivity extends Activity {
// Orientation. // Orientation.
final int orientations = capabilities.getOrientations(); final int orientations = capabilities.getOrientations();
// If the orientations changed, we update the adapter and the spinner.
boolean orientationsChanged = false; boolean orientationsChanged = false;
if (Integer.bitCount(orientations) != mOrientationSpinnerAdapter.getCount()) { if (Integer.bitCount(orientations) != mOrientationSpinnerAdapter.getCount()) {
orientationsChanged = true; orientationsChanged = true;
@ -1617,6 +1690,10 @@ public class PrintJobConfigActivity extends Activity {
} }
} }
if (orientationsChanged) { if (orientationsChanged) {
// Remember the old orientation to try selecting it again.
int oldOrientationNewIndex = AdapterView.INVALID_POSITION;
final int oldOrientation = mCurrPrintAttributes.getOrientation();
mOrientationSpinnerAdapter.clear(); mOrientationSpinnerAdapter.clear();
String[] orientationLabels = getResources().getStringArray( String[] orientationLabels = getResources().getStringArray(
R.array.orientation_labels); R.array.orientation_labels);
@ -1625,6 +1702,10 @@ public class PrintJobConfigActivity extends Activity {
final int orientationBitOffset = Integer.numberOfTrailingZeros( final int orientationBitOffset = Integer.numberOfTrailingZeros(
remainingOrientations); remainingOrientations);
final int orientation = 1 << orientationBitOffset; final int orientation = 1 << orientationBitOffset;
if (orientation == oldOrientation) {
// Update the index of the old selection.
oldOrientationNewIndex = orientationBitOffset;
}
remainingOrientations &= ~orientation; remainingOrientations &= ~orientation;
mOrientationSpinnerAdapter.add(new SpinnerItem<Integer>(orientation, mOrientationSpinnerAdapter.add(new SpinnerItem<Integer>(orientation,
orientationLabels[orientationBitOffset])); orientationLabels[orientationBitOffset]));
@ -1635,12 +1716,15 @@ public class PrintJobConfigActivity extends Activity {
mOrientationSpinner.setSelection(AdapterView.INVALID_POSITION); mOrientationSpinner.setSelection(AdapterView.INVALID_POSITION);
} else { } else {
mOrientationSpinner.setEnabled(true); mOrientationSpinner.setEnabled(true);
if (oldOrientationNewIndex != AdapterView.INVALID_POSITION) {
// Select the old orientation - nothing really changed.
setOrientationSpinnerSelectionNoCallback(oldOrientationNewIndex);
} else {
final int selectedOrientationIndex = Integer.numberOfTrailingZeros( final int selectedOrientationIndex = Integer.numberOfTrailingZeros(
(orientations & defaultAttributes.getOrientation())); (orientations & defaultAttributes.getOrientation()));
if (mOrientationSpinner.getSelectedItemPosition() someAttributeSelectionChanged =
!= selectedOrientationIndex) { setOrientationSpinnerSelectionNoCallback(
mIgnoreNextOrientationChange = true; selectedOrientationIndex);
mOrientationSpinner.setSelection(selectedOrientationIndex);
} }
} }
} }
@ -1648,8 +1732,11 @@ public class PrintJobConfigActivity extends Activity {
// Range options // Range options
PrintDocumentInfo info = mDocument.info; PrintDocumentInfo info = mDocument.info;
if (info != null && (info.getPageCount() > 1 if (info != null && (info.getPageCount() > 0
|| info.getPageCount() == PrintDocumentInfo.PAGE_COUNT_UNKNOWN)) { || info.getPageCount() == PrintDocumentInfo.PAGE_COUNT_UNKNOWN)) {
if (info.getPageCount() == 1) {
mRangeOptionsSpinner.setEnabled(false);
} else {
mRangeOptionsSpinner.setEnabled(true); mRangeOptionsSpinner.setEnabled(true);
if (mRangeOptionsSpinner.getSelectedItemPosition() > 0) { if (mRangeOptionsSpinner.getSelectedItemPosition() > 0) {
if (!mPageRangeEditText.isEnabled()) { if (!mPageRangeEditText.isEnabled()) {
@ -1666,6 +1753,7 @@ public class PrintJobConfigActivity extends Activity {
mPageRangeEditText.setVisibility(View.INVISIBLE); mPageRangeEditText.setVisibility(View.INVISIBLE);
mPageRangeTitle.setVisibility(View.INVISIBLE); mPageRangeTitle.setVisibility(View.INVISIBLE);
} }
}
final int pageCount = mDocument.info.getPageCount(); final int pageCount = mDocument.info.getPageCount();
mRangeOptionsTitle.setText(getString(R.string.label_pages, mRangeOptionsTitle.setText(getString(R.string.label_pages,
(pageCount == PrintDocumentInfo.PAGE_COUNT_UNKNOWN) (pageCount == PrintDocumentInfo.PAGE_COUNT_UNKNOWN)
@ -1702,15 +1790,8 @@ public class PrintJobConfigActivity extends Activity {
&& (TextUtils.isEmpty(mPageRangeEditText.getText()) || hasErrors())) && (TextUtils.isEmpty(mPageRangeEditText.getText()) || hasErrors()))
|| (mRangeOptionsSpinner.getSelectedItemPosition() == 0 || (mRangeOptionsSpinner.getSelectedItemPosition() == 0
&& (!mController.hasPerformedLayout() || hasErrors()))) { && (!mController.hasPerformedLayout() || hasErrors()))) {
// mPrintPreviewButton.setEnabled(false);
mPrintButton.setEnabled(false); mPrintButton.setEnabled(false);
} else { } else {
// mPrintPreviewButton.setEnabled(true);
// if (hasPdfViewer()) {
// mPrintPreviewButton.setText(getString(R.string.print_preview));
// } else {
// mPrintPreviewButton.setText(getString(R.string.install_for_print_preview));
// }
mPrintButton.setEnabled(true); mPrintButton.setEnabled(true);
} }
@ -1742,6 +1823,24 @@ public class PrintJobConfigActivity extends Activity {
return false; return false;
} }
private boolean setColorModeSpinnerSelectionNoCallback(int position) {
if (mColorModeSpinner.getSelectedItemPosition() != position) {
mIgnoreNextColorModeChange = true;
mColorModeSpinner.setSelection(position);
return true;
}
return false;
}
private boolean setOrientationSpinnerSelectionNoCallback(int position) {
if (mOrientationSpinner.getSelectedItemPosition() != position) {
mIgnoreNextOrientationChange = true;
mOrientationSpinner.setSelection(position);
return true;
}
return false;
}
private void updateUiForNewPrinterCapabilities() { private void updateUiForNewPrinterCapabilities() {
// The printer changed so we want to start with a clean slate // The printer changed so we want to start with a clean slate
// for the print options and let them be populated from the // for the print options and let them be populated from the
@ -1786,13 +1885,6 @@ public class PrintJobConfigActivity extends Activity {
&& mPageRangeEditText.getError() != null; && mPageRangeEditText.getError() != null;
} }
// private boolean hasPdfViewer() {
// Intent intent = new Intent(Intent.ACTION_VIEW);
// intent.setType("application/pdf");
// return !getPackageManager().queryIntentActivities(intent,
// PackageManager.MATCH_DEFAULT_ONLY).isEmpty();
// }
private final class SpinnerItem<T> { private final class SpinnerItem<T> {
final T value; final T value;
CharSequence label; CharSequence label;
@ -1998,7 +2090,7 @@ public class PrintJobConfigActivity extends Activity {
.create(); .create();
return new PrinterInfo.Builder(printerId, getString(R.string.save_as_pdf), return new PrinterInfo.Builder(printerId, getString(R.string.save_as_pdf),
PrinterInfo.STATUS_READY) PrinterInfo.STATUS_IDLE)
.setCapabilities(capabilities) .setCapabilities(capabilities)
.create(); .create();
} }