1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.print; 18 19 import android.annotation.IntDef; 20 import android.annotation.IntRange; 21 import android.annotation.NonNull; 22 import android.os.Parcel; 23 import android.os.Parcelable; 24 import android.text.TextUtils; 25 import com.android.internal.util.Preconditions; 26 27 import java.lang.annotation.Retention; 28 import java.lang.annotation.RetentionPolicy; 29 30 /** 31 * This class encapsulates information about a document for printing 32 * purposes. This meta-data is used by the platform and print services, 33 * components that interact with printers. For example, this class 34 * contains the number of pages contained in the document it describes and 35 * this number of pages is shown to the user allowing him/her to select 36 * the range to print. Also a print service may optimize the printing 37 * process based on the content type, such as document or photo. 38 * <p> 39 * Instances of this class are created by the printing application and 40 * passed to the {@link PrintDocumentAdapter.LayoutResultCallback#onLayoutFinished( 41 * PrintDocumentInfo, boolean) PrintDocumentAdapter.LayoutResultCallback.onLayoutFinished( 42 * PrintDocumentInfo, boolean)} callback after successfully laying out the 43 * content which is performed in {@link PrintDocumentAdapter#onLayout(PrintAttributes, 44 * PrintAttributes, android.os.CancellationSignal, PrintDocumentAdapter.LayoutResultCallback, 45 * android.os.Bundle) PrintDocumentAdapter.onLayout(PrintAttributes, 46 * PrintAttributes, android.os.CancellationSignal, 47 * PrintDocumentAdapter.LayoutResultCallback, android.os.Bundle)}. 48 * </p> 49 * <p> 50 * An example usage looks like this: 51 * <pre> 52 * 53 * . . . 54 * 55 * public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, 56 * CancellationSignal cancellationSignal, LayoutResultCallback callback, 57 * Bundle metadata) { 58 * 59 * // Assume the app defined a LayoutResult class which contains 60 * // the layout result data and that the content is a document. 61 * LayoutResult result = doSomeLayoutWork(); 62 * 63 * PrintDocumentInfo info = new PrintDocumentInfo 64 * .Builder("printed_file.pdf") 65 * .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT) 66 * .setPageCount(result.getPageCount()) 67 * .build(); 68 * 69 * callback.onLayoutFinished(info, result.getContentChanged()); 70 * } 71 * 72 * . . . 73 * 74 * </pre> 75 * </p> 76 */ 77 public final class PrintDocumentInfo implements Parcelable { 78 79 /** 80 * Constant for unknown page count. 81 */ 82 public static final int PAGE_COUNT_UNKNOWN = -1; 83 84 /** @hide */ 85 @Retention(RetentionPolicy.SOURCE) 86 @IntDef({ 87 CONTENT_TYPE_UNKNOWN, CONTENT_TYPE_DOCUMENT, CONTENT_TYPE_PHOTO 88 }) 89 public @interface ContentType { 90 } 91 /** 92 * Content type: unknown. 93 */ 94 public static final int CONTENT_TYPE_UNKNOWN = -1; 95 96 /** 97 * Content type: document. 98 * <p> 99 * A print service may use normal paper to print the content instead 100 * of dedicated photo paper. Also it may use a lower quality printing 101 * process as the content is not as sensitive to print quality variation 102 * as a photo is. 103 * </p> 104 */ 105 public static final int CONTENT_TYPE_DOCUMENT = 0; 106 107 /** 108 * Content type: photo. 109 * <p> 110 * A print service may use dedicated photo paper to print the content 111 * instead of normal paper. Also it may use a higher quality printing 112 * process as the content is more sensitive to print quality variation 113 * than a document. 114 * </p> 115 */ 116 public static final int CONTENT_TYPE_PHOTO = 1; 117 118 private @NonNull String mName; 119 private @IntRange(from = -1) int mPageCount; 120 private int mContentType; 121 private long mDataSize; 122 123 /** 124 * Creates a new instance. 125 */ 126 private PrintDocumentInfo() { 127 /* do nothing */ 128 } 129 130 /** 131 * Creates a new instance. 132 * 133 * @param prototype from which to clone. 134 */ 135 private PrintDocumentInfo(@NonNull PrintDocumentInfo prototype) { 136 mName = prototype.mName; 137 mPageCount = prototype.mPageCount; 138 mContentType = prototype.mContentType; 139 mDataSize = prototype.mDataSize; 140 } 141 142 /** 143 * Creates a new instance. 144 * 145 * @param parcel Data from which to initialize. 146 */ 147 private PrintDocumentInfo(Parcel parcel) { 148 mName = Preconditions.checkStringNotEmpty(parcel.readString()); 149 mPageCount = parcel.readInt(); 150 Preconditions.checkArgument(mPageCount == PAGE_COUNT_UNKNOWN || mPageCount > 0); 151 mContentType = parcel.readInt(); 152 mDataSize = Preconditions.checkArgumentNonnegative(parcel.readLong()); 153 } 154 155 /** 156 * Gets the document name. This name may be shown to 157 * the user. 158 * 159 * @return The document name. 160 */ 161 public @NonNull String getName() { 162 return mName; 163 } 164 165 /** 166 * Gets the total number of pages. 167 * 168 * @return The number of pages. 169 * 170 * @see #PAGE_COUNT_UNKNOWN 171 */ 172 public @IntRange(from = -1) int getPageCount() { 173 return mPageCount; 174 } 175 176 /** 177 * Gets the content type. 178 * 179 * @return The content type. 180 * 181 * @see #CONTENT_TYPE_UNKNOWN 182 * @see #CONTENT_TYPE_DOCUMENT 183 * @see #CONTENT_TYPE_PHOTO 184 */ 185 public int getContentType() { 186 return mContentType; 187 } 188 189 /** 190 * Gets the document data size in bytes. 191 * 192 * @return The data size. 193 */ 194 public @IntRange(from = 0) long getDataSize() { 195 return mDataSize; 196 } 197 198 /** 199 * Sets the document data size in bytes. 200 * 201 * @param dataSize The data size. 202 * 203 * @hide 204 */ 205 public void setDataSize(@IntRange(from = 0) long dataSize) { 206 mDataSize = dataSize; 207 } 208 209 @Override 210 public int describeContents() { 211 return 0; 212 } 213 214 @Override 215 public void writeToParcel(Parcel parcel, int flags) { 216 parcel.writeString(mName); 217 parcel.writeInt(mPageCount); 218 parcel.writeInt(mContentType); 219 parcel.writeLong(mDataSize); 220 } 221 222 @Override 223 public int hashCode() { 224 final int prime = 31; 225 int result = 1; 226 result = prime * result + ((mName != null) ? mName.hashCode() : 0); 227 result = prime * result + mContentType; 228 result = prime * result + mPageCount; 229 result = prime * result + (int) mDataSize; 230 result = prime * result + (int) (mDataSize >> 32); 231 return result; 232 } 233 234 @Override 235 public boolean equals(Object obj) { 236 if (this == obj) { 237 return true; 238 } 239 if (obj == null) { 240 return false; 241 } 242 if (getClass() != obj.getClass()) { 243 return false; 244 } 245 PrintDocumentInfo other = (PrintDocumentInfo) obj; 246 if (!TextUtils.equals(mName, other.mName)) { 247 return false; 248 } 249 if (mContentType != other.mContentType) { 250 return false; 251 } 252 if (mPageCount != other.mPageCount) { 253 return false; 254 } 255 if (mDataSize != other.mDataSize) { 256 return false; 257 } 258 return true; 259 } 260 261 @Override 262 public String toString() { 263 StringBuilder builder = new StringBuilder(); 264 builder.append("PrintDocumentInfo{"); 265 builder.append("name=").append(mName); 266 builder.append(", pageCount=").append(mPageCount); 267 builder.append(", contentType=").append(contentTypeToString(mContentType)); 268 builder.append(", dataSize=").append(mDataSize); 269 builder.append("}"); 270 return builder.toString(); 271 } 272 273 private String contentTypeToString(int contentType) { 274 switch (contentType) { 275 case CONTENT_TYPE_DOCUMENT: { 276 return "CONTENT_TYPE_DOCUMENT"; 277 } 278 case CONTENT_TYPE_PHOTO: { 279 return "CONTENT_TYPE_PHOTO"; 280 } 281 default: { 282 return "CONTENT_TYPE_UNKNOWN"; 283 } 284 } 285 } 286 287 /** 288 * Builder for creating a {@link PrintDocumentInfo}. 289 */ 290 public static final class Builder { 291 private final PrintDocumentInfo mPrototype; 292 293 /** 294 * Constructor. 295 * 296 * <p> 297 * The values of the relevant properties are initialized with defaults. 298 * Please refer to the documentation of the individual setters for 299 * information about the default values. 300 * </p> 301 * 302 * @param name The document name which may be shown to the user and 303 * is the file name if the content it describes is saved as a PDF. 304 * Cannot be empty. 305 */ 306 public Builder(@NonNull String name) { 307 if (TextUtils.isEmpty(name)) { 308 throw new IllegalArgumentException("name cannot be empty"); 309 } 310 mPrototype = new PrintDocumentInfo(); 311 mPrototype.mName = name; 312 } 313 314 /** 315 * Sets the total number of pages. 316 * <p> 317 * <strong>Default: </strong> {@link #PAGE_COUNT_UNKNOWN} 318 * </p> 319 * 320 * @param pageCount The number of pages. Must be greater than or equal to zero or 321 * {@link PrintDocumentInfo#PAGE_COUNT_UNKNOWN}. 322 * @return This builder. 323 */ 324 public @NonNull Builder setPageCount(@IntRange(from = -1) int pageCount) { 325 if (pageCount < 0 && pageCount != PAGE_COUNT_UNKNOWN) { 326 throw new IllegalArgumentException("pageCount" 327 + " must be greater than or equal to zero or" 328 + " DocumentInfo#PAGE_COUNT_UNKNOWN"); 329 } 330 mPrototype.mPageCount = pageCount; 331 return this; 332 } 333 334 /** 335 * Sets the content type. 336 * <p> 337 * <strong>Default: </strong> {@link #CONTENT_TYPE_UNKNOWN} 338 * </p> 339 * 340 * @param type The content type. 341 * @return This builder. 342 * @see #CONTENT_TYPE_UNKNOWN 343 * @see #CONTENT_TYPE_DOCUMENT 344 * @see #CONTENT_TYPE_PHOTO 345 */ 346 public @NonNull Builder setContentType(@ContentType int type) { 347 mPrototype.mContentType = type; 348 return this; 349 } 350 351 /** 352 * Creates a new {@link PrintDocumentInfo} instance. 353 * 354 * @return The new instance. 355 */ 356 public @NonNull PrintDocumentInfo build() { 357 // Zero pages is the same as unknown as in this case 358 // we will have to ask for all pages and look a the 359 // wiritten PDF file for the page count. 360 if (mPrototype.mPageCount == 0) { 361 mPrototype.mPageCount = PAGE_COUNT_UNKNOWN; 362 } 363 return new PrintDocumentInfo(mPrototype); 364 } 365 } 366 367 public static final Parcelable.Creator<PrintDocumentInfo> CREATOR = 368 new Creator<PrintDocumentInfo>() { 369 @Override 370 public PrintDocumentInfo createFromParcel(Parcel parcel) { 371 return new PrintDocumentInfo(parcel); 372 } 373 374 @Override 375 public PrintDocumentInfo[] newArray(int size) { 376 return new PrintDocumentInfo[size]; 377 } 378 }; 379 } 380