PrinterCapabilitiesInfo.java revision aec1417ca9eb63209668ac17da90cf8a07c6076c
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 17package android.print; 18 19import android.os.Parcel; 20import android.os.Parcelable; 21import android.print.PrintAttributes.Margins; 22import android.print.PrintAttributes.MediaSize; 23import android.print.PrintAttributes.Resolution; 24import android.print.PrintAttributes.Tray; 25 26import java.util.ArrayList; 27import java.util.Arrays; 28import java.util.List; 29 30/** 31 * This class represents the capabilities of a printer. 32 */ 33public final class PrinterCapabilitiesInfo implements Parcelable { 34 /** 35 * Undefined default value. 36 * 37 * @hide 38 */ 39 public static final int DEFAULT_UNDEFINED = -1; 40 41 private static final int PROPERTY_MEDIA_SIZE = 0; 42 private static final int PROPERTY_RESOLUTION = 1; 43 private static final int PROPERTY_INPUT_TRAY = 2; 44 private static final int PROPERTY_OUTPUT_TRAY = 3; 45 private static final int PROPERTY_DUPLEX_MODE = 4; 46 private static final int PROPERTY_COLOR_MODE = 5; 47 private static final int PROPERTY_FITTING_MODE = 6; 48 private static final int PROPERTY_ORIENTATION = 7; 49 private static final int PROPERTY_COUNT = 8; 50 51 private static final Margins DEFAULT_MARGINS = new Margins(0, 0, 0, 0); 52 53 private Margins mMinMargins = DEFAULT_MARGINS; 54 private List<MediaSize> mMediaSizes; 55 private List<Resolution> mResolutions; 56 private List<Tray> mInputTrays; 57 private List<Tray> mOutputTrays; 58 59 private int mDuplexModes; 60 private int mColorModes; 61 private int mFittingModes; 62 private int mOrientations; 63 64 private final int[] mDefaults = new int[PROPERTY_COUNT]; 65 private Margins mDefaultMargins = DEFAULT_MARGINS; 66 67 /** 68 * @hide 69 */ 70 public PrinterCapabilitiesInfo() { 71 Arrays.fill(mDefaults, DEFAULT_UNDEFINED); 72 } 73 74 /** 75 * @hide 76 */ 77 public PrinterCapabilitiesInfo(PrinterCapabilitiesInfo prototype) { 78 copyFrom(prototype); 79 } 80 81 /** 82 * @hide 83 */ 84 public void copyFrom(PrinterCapabilitiesInfo other) { 85 mMinMargins = other.mMinMargins; 86 87 if (other.mMediaSizes != null) { 88 if (mMediaSizes != null) { 89 mMediaSizes.clear(); 90 mMediaSizes.addAll(other.mMediaSizes); 91 } else { 92 mMediaSizes = new ArrayList<MediaSize>(other.mMediaSizes); 93 } 94 } else { 95 mMediaSizes = null; 96 } 97 98 if (other.mResolutions != null) { 99 if (mResolutions != null) { 100 mResolutions.clear(); 101 mResolutions.addAll(other.mResolutions); 102 } else { 103 mResolutions = new ArrayList<Resolution>(other.mResolutions); 104 } 105 } else { 106 mResolutions = null; 107 } 108 109 if (other.mInputTrays != null) { 110 if (mInputTrays != null) { 111 mInputTrays.clear(); 112 mInputTrays.addAll(other.mInputTrays); 113 } else { 114 mInputTrays = new ArrayList<Tray>(other.mInputTrays); 115 } 116 } else { 117 mInputTrays = null; 118 } 119 120 if (other.mOutputTrays != null) { 121 if (mOutputTrays != null) { 122 mOutputTrays.clear(); 123 mOutputTrays.addAll(other.mOutputTrays); 124 } else { 125 mOutputTrays = new ArrayList<Tray>(other.mOutputTrays); 126 } 127 } else { 128 mOutputTrays = null; 129 } 130 131 mDuplexModes = other.mDuplexModes; 132 mColorModes = other.mColorModes; 133 mFittingModes = other.mFittingModes; 134 mOrientations = other.mOrientations; 135 136 final int defaultCount = other.mDefaults.length; 137 for (int i = 0; i < defaultCount; i++) { 138 mDefaults[i] = other.mDefaults[i]; 139 } 140 141 mDefaultMargins = other.mDefaultMargins; 142 } 143 144 /** 145 * Gets the supported media sizes. 146 * 147 * @return The media sizes. 148 */ 149 public List<MediaSize> getMediaSizes() { 150 return mMediaSizes; 151 } 152 153 /** 154 * Gets the supported resolutions. 155 * 156 * @return The resolutions. 157 */ 158 public List<Resolution> getResolutions() { 159 return mResolutions; 160 } 161 162 /** 163 * Gets the minimal supported margins. 164 * 165 * @return The minimal margins. 166 */ 167 public Margins getMinMargins() { 168 return mMinMargins; 169 } 170 171 /** 172 * Gets the available input trays. 173 * 174 * @return The input trays. 175 */ 176 public List<Tray> getInputTrays() { 177 return mInputTrays; 178 } 179 180 /** 181 * Gets the available output trays. 182 * 183 * @return The output trays. 184 */ 185 public List<Tray> getOutputTrays() { 186 return mOutputTrays; 187 } 188 189 /** 190 * Gets the supported duplex modes. 191 * 192 * @return The duplex modes. 193 * 194 * @see PrintAttributes#DUPLEX_MODE_NONE 195 * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE 196 * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE 197 */ 198 public int getDuplexModes() { 199 return mDuplexModes; 200 } 201 202 /** 203 * Gets the supported color modes. 204 * 205 * @return The color modes. 206 * 207 * @see PrintAttributes#COLOR_MODE_COLOR 208 * @see PrintAttributes#COLOR_MODE_MONOCHROME 209 */ 210 public int getColorModes() { 211 return mColorModes; 212 } 213 214 /** 215 * Gets the supported fitting modes. 216 * 217 * @return The fitting modes. 218 * 219 * @see PrintAttributes#FITTING_MODE_NONE 220 * @see PrintAttributes#FITTING_MODE_FIT_TO_PAGE 221 */ 222 public int getFittingModes() { 223 return mFittingModes; 224 } 225 226 /** 227 * Gets the supported orientations. 228 * 229 * @return The orientations. 230 * 231 * @see PrintAttributes#ORIENTATION_PORTRAIT 232 * @see PrintAttributes#ORIENTATION_LANDSCAPE 233 */ 234 public int getOrientations() { 235 return mOrientations; 236 } 237 238 /** 239 * Gets the default print attributes. 240 * 241 * @param outAttributes The attributes to populated. 242 */ 243 public void getDefaults(PrintAttributes outAttributes) { 244 outAttributes.clear(); 245 246 outAttributes.setMargins(mDefaultMargins); 247 248 final int mediaSizeIndex = mDefaults[PROPERTY_MEDIA_SIZE]; 249 if (mediaSizeIndex >= 0) { 250 outAttributes.setMediaSize(mMediaSizes.get(mediaSizeIndex)); 251 } 252 253 final int resolutionIndex = mDefaults[PROPERTY_RESOLUTION]; 254 if (resolutionIndex >= 0) { 255 outAttributes.setResolution(mResolutions.get(resolutionIndex)); 256 } 257 258 final int inputTrayIndex = mDefaults[PROPERTY_INPUT_TRAY]; 259 if (inputTrayIndex >= 0) { 260 outAttributes.setInputTray(mInputTrays.get(inputTrayIndex)); 261 } 262 263 final int outputTrayIndex = mDefaults[PROPERTY_OUTPUT_TRAY]; 264 if (outputTrayIndex >= 0) { 265 outAttributes.setOutputTray(mOutputTrays.get(outputTrayIndex)); 266 } 267 268 final int duplexMode = mDefaults[PROPERTY_DUPLEX_MODE]; 269 if (duplexMode > 0) { 270 outAttributes.setDuplexMode(duplexMode); 271 } 272 273 final int colorMode = mDefaults[PROPERTY_COLOR_MODE]; 274 if (colorMode > 0) { 275 outAttributes.setColorMode(colorMode); 276 } 277 278 final int fittingMode = mDefaults[PROPERTY_FITTING_MODE]; 279 if (fittingMode > 0) { 280 outAttributes.setFittingMode(fittingMode); 281 } 282 283 final int orientation = mDefaults[PROPERTY_ORIENTATION]; 284 if (orientation > 0) { 285 outAttributes.setOrientation(orientation); 286 } 287 } 288 289 private PrinterCapabilitiesInfo(Parcel parcel) { 290 mMinMargins = readMargins(parcel); 291 readMediaSizes(parcel); 292 readResolutions(parcel); 293 mInputTrays = readInputTrays(parcel); 294 mOutputTrays = readOutputTrays(parcel); 295 296 mColorModes = parcel.readInt(); 297 mDuplexModes = parcel.readInt(); 298 mFittingModes = parcel.readInt(); 299 mOrientations = parcel.readInt(); 300 301 readDefaults(parcel); 302 mDefaultMargins = readMargins(parcel); 303 } 304 305 @Override 306 public int describeContents() { 307 return 0; 308 } 309 310 @Override 311 public void writeToParcel(Parcel parcel, int flags) { 312 writeMargins(mMinMargins, parcel); 313 writeMediaSizes(parcel); 314 writeResolutions(parcel); 315 writeInputTrays(parcel); 316 writeOutputTrays(parcel); 317 318 parcel.writeInt(mColorModes); 319 parcel.writeInt(mDuplexModes); 320 parcel.writeInt(mFittingModes); 321 parcel.writeInt(mOrientations); 322 323 writeDefaults(parcel); 324 writeMargins(mDefaultMargins, parcel); 325 } 326 327 @Override 328 public int hashCode() { 329 final int prime = 31; 330 int result = 1; 331 result = prime * result + ((mMinMargins == null) ? 0 : mMinMargins.hashCode()); 332 result = prime * result + ((mMediaSizes == null) ? 0 : mMediaSizes.hashCode()); 333 result = prime * result + ((mResolutions == null) ? 0 : mResolutions.hashCode()); 334 result = prime * result + ((mInputTrays == null) ? 0 : mInputTrays.hashCode()); 335 result = prime * result + ((mOutputTrays == null) ? 0 : mOutputTrays.hashCode()); 336 result = prime * result + mColorModes; 337 result = prime * result + mDuplexModes; 338 result = prime * result + mFittingModes; 339 result = prime * result + mOrientations; 340 result = prime * result + Arrays.hashCode(mDefaults); 341 result = prime * result + ((mDefaultMargins == null) ? 0 : mDefaultMargins.hashCode()); 342 return result; 343 } 344 345 @Override 346 public boolean equals(Object obj) { 347 if (this == obj) { 348 return true; 349 } 350 if (obj == null) { 351 return false; 352 } 353 if (getClass() != obj.getClass()) { 354 return false; 355 } 356 PrinterCapabilitiesInfo other = (PrinterCapabilitiesInfo) obj; 357 if (mMinMargins == null) { 358 if (other.mMinMargins != null) { 359 return false; 360 } 361 } else if (!mMinMargins.equals(other.mMinMargins)) { 362 return false; 363 } 364 if (mMediaSizes == null) { 365 if (other.mMediaSizes != null) { 366 return false; 367 } 368 } else if (!mMediaSizes.equals(other.mMediaSizes)) { 369 return false; 370 } 371 if (mResolutions == null) { 372 if (other.mResolutions != null) { 373 return false; 374 } 375 } else if (!mResolutions.equals(other.mResolutions)) { 376 return false; 377 } 378 if (mInputTrays == null) { 379 if (other.mInputTrays != null) { 380 return false; 381 } 382 } else if (!mInputTrays.equals(other.mInputTrays)) { 383 return false; 384 } 385 if (mOutputTrays == null) { 386 if (other.mOutputTrays != null) { 387 return false; 388 } 389 } else if (!mOutputTrays.equals(other.mOutputTrays)) { 390 return false; 391 } 392 if (mDuplexModes != other.mDuplexModes) { 393 return false; 394 } 395 if (mColorModes != other.mColorModes) { 396 return false; 397 } 398 if (mFittingModes != other.mFittingModes) { 399 return false; 400 } 401 if (mOrientations != other.mOrientations) { 402 return false; 403 } 404 if (!Arrays.equals(mDefaults, other.mDefaults)) { 405 return false; 406 } 407 if (mDefaultMargins == null) { 408 if (other.mDefaultMargins != null) { 409 return false; 410 } 411 } else if (!mDefaultMargins.equals(other.mDefaultMargins)) { 412 return false; 413 } 414 return true; 415 } 416 417 @Override 418 public String toString() { 419 StringBuilder builder = new StringBuilder(); 420 builder.append("PrinterInfo{"); 421 builder.append("minMargins=").append(mMinMargins); 422 builder.append(", mediaSizes=").append(mMediaSizes); 423 builder.append(", resolutions=").append(mResolutions); 424 builder.append(", inputTrays=").append(mInputTrays); 425 builder.append(", outputTrays=").append(mOutputTrays); 426 builder.append(", duplexModes=").append(duplexModesToString()); 427 builder.append(", colorModes=").append(colorModesToString()); 428 builder.append(", fittingModes=").append(fittingModesToString()); 429 builder.append(", orientations=").append(orientationsToString()); 430 builder.append("\"}"); 431 return builder.toString(); 432 } 433 434 private String duplexModesToString() { 435 StringBuilder builder = new StringBuilder(); 436 builder.append('['); 437 int duplexModes = mDuplexModes; 438 while (duplexModes != 0) { 439 final int duplexMode = 1 << Integer.numberOfTrailingZeros(duplexModes); 440 duplexModes &= ~duplexMode; 441 if (builder.length() > 0) { 442 builder.append(", "); 443 } 444 builder.append(PrintAttributes.duplexModeToString(duplexMode)); 445 } 446 builder.append(']'); 447 return builder.toString(); 448 } 449 450 private String colorModesToString() { 451 StringBuilder builder = new StringBuilder(); 452 builder.append('['); 453 int colorModes = mColorModes; 454 while (colorModes != 0) { 455 final int colorMode = 1 << Integer.numberOfTrailingZeros(colorModes); 456 colorModes &= ~colorMode; 457 if (builder.length() > 0) { 458 builder.append(", "); 459 } 460 builder.append(PrintAttributes.colorModeToString(colorMode)); 461 } 462 builder.append(']'); 463 return builder.toString(); 464 } 465 466 private String fittingModesToString() { 467 StringBuilder builder = new StringBuilder(); 468 builder.append('['); 469 int fittingModes = mFittingModes; 470 while (fittingModes != 0) { 471 final int fittingMode = 1 << Integer.numberOfTrailingZeros(fittingModes); 472 fittingModes &= ~fittingMode; 473 if (builder.length() > 0) { 474 builder.append(", "); 475 } 476 builder.append(PrintAttributes.fittingModeToString(fittingMode)); 477 } 478 builder.append(']'); 479 return builder.toString(); 480 } 481 482 private String orientationsToString() { 483 StringBuilder builder = new StringBuilder(); 484 builder.append('['); 485 int orientations = mOrientations; 486 while (orientations != 0) { 487 final int orientation = 1 << Integer.numberOfTrailingZeros(orientations); 488 orientations &= ~orientation; 489 if (builder.length() > 0) { 490 builder.append(", "); 491 } 492 builder.append(PrintAttributes.orientationToString(orientation)); 493 } 494 builder.append(']'); 495 return builder.toString(); 496 } 497 498 private void writeMediaSizes(Parcel parcel) { 499 if (mMediaSizes == null) { 500 parcel.writeInt(0); 501 return; 502 } 503 final int mediaSizeCount = mMediaSizes.size(); 504 parcel.writeInt(mediaSizeCount); 505 for (int i = 0; i < mediaSizeCount; i++) { 506 mMediaSizes.get(i).writeToParcel(parcel); 507 } 508 } 509 510 private void readMediaSizes(Parcel parcel) { 511 final int mediaSizeCount = parcel.readInt(); 512 if (mediaSizeCount > 0 && mMediaSizes == null) { 513 mMediaSizes = new ArrayList<MediaSize>(); 514 } 515 for (int i = 0; i < mediaSizeCount; i++) { 516 mMediaSizes.add(MediaSize.createFromParcel(parcel)); 517 } 518 } 519 520 private void writeResolutions(Parcel parcel) { 521 if (mResolutions == null) { 522 parcel.writeInt(0); 523 return; 524 } 525 final int resolutionCount = mResolutions.size(); 526 parcel.writeInt(resolutionCount); 527 for (int i = 0; i < resolutionCount; i++) { 528 mResolutions.get(i).writeToParcel(parcel); 529 } 530 } 531 532 private void readResolutions(Parcel parcel) { 533 final int resolutionCount = parcel.readInt(); 534 if (resolutionCount > 0 && mResolutions == null) { 535 mResolutions = new ArrayList<Resolution>(); 536 } 537 for (int i = 0; i < resolutionCount; i++) { 538 mResolutions.add(Resolution.createFromParcel(parcel)); 539 } 540 } 541 542 private void writeMargins(Margins margins, Parcel parcel) { 543 if (margins == null) { 544 parcel.writeInt(0); 545 } else { 546 parcel.writeInt(1); 547 margins.writeToParcel(parcel); 548 } 549 } 550 551 private Margins readMargins(Parcel parcel) { 552 return (parcel.readInt() == 1) ? Margins.createFromParcel(parcel) : null; 553 } 554 555 private void writeInputTrays(Parcel parcel) { 556 if (mInputTrays == null) { 557 parcel.writeInt(0); 558 return; 559 } 560 final int inputTrayCount = mInputTrays.size(); 561 parcel.writeInt(inputTrayCount); 562 for (int i = 0; i < inputTrayCount; i++) { 563 mInputTrays.get(i).writeToParcel(parcel); 564 } 565 } 566 567 private List<Tray> readInputTrays(Parcel parcel) { 568 final int inputTrayCount = parcel.readInt(); 569 if (inputTrayCount <= 0) { 570 return null; 571 } 572 List<Tray> inputTrays = new ArrayList<Tray>(inputTrayCount); 573 for (int i = 0; i < inputTrayCount; i++) { 574 inputTrays.add(Tray.createFromParcel(parcel)); 575 } 576 return inputTrays; 577 } 578 579 private void writeOutputTrays(Parcel parcel) { 580 if (mOutputTrays == null) { 581 parcel.writeInt(0); 582 return; 583 } 584 final int outputTrayCount = mOutputTrays.size(); 585 parcel.writeInt(outputTrayCount); 586 for (int i = 0; i < outputTrayCount; i++) { 587 mOutputTrays.get(i).writeToParcel(parcel); 588 } 589 } 590 591 private List<Tray> readOutputTrays(Parcel parcel) { 592 final int outputTrayCount = parcel.readInt(); 593 if (outputTrayCount <= 0) { 594 return null; 595 } 596 List<Tray> outputTrays = new ArrayList<Tray>(outputTrayCount); 597 for (int i = 0; i < outputTrayCount; i++) { 598 outputTrays.add(Tray.createFromParcel(parcel)); 599 } 600 return outputTrays; 601 } 602 603 private void readDefaults(Parcel parcel) { 604 final int defaultCount = parcel.readInt(); 605 for (int i = 0; i < defaultCount; i++) { 606 mDefaults[i] = parcel.readInt(); 607 } 608 } 609 610 private void writeDefaults(Parcel parcel) { 611 final int defaultCount = mDefaults.length; 612 parcel.writeInt(defaultCount); 613 for (int i = 0; i < defaultCount; i++) { 614 parcel.writeInt(mDefaults[i]); 615 } 616 } 617 618 /** 619 * Builder for creating of a {@link PrinterInfo}. This class is responsible 620 * to enforce that all required attributes have at least one default value. 621 * In other words, this class creates only well-formed {@link PrinterInfo}s. 622 * <p> 623 * Look at the individual methods for a reference whether a property is 624 * required or if it is optional. 625 * </p> 626 */ 627 public static final class Builder { 628 private final PrinterCapabilitiesInfo mPrototype; 629 630 /** 631 * Creates a new instance. 632 * 633 * @param printerId The printer id. Cannot be null. 634 * 635 * @throws IllegalArgumentException If the printer id is null. 636 */ 637 public Builder(PrinterId printerId) { 638 if (printerId == null) { 639 throw new IllegalArgumentException("printerId cannot be null."); 640 } 641 mPrototype = new PrinterCapabilitiesInfo(); 642 } 643 644 /** 645 * Adds a supported media size. 646 * <p> 647 * <strong>Required:</strong> Yes 648 * </p> 649 * 650 * @param mediaSize A media size. 651 * @param isDefault Whether this is the default. 652 * @return This builder. 653 * @throws IllegalArgumentException If set as default and there 654 * is already a default. 655 * 656 * @see PrintAttributes.MediaSize 657 */ 658 public Builder addMediaSize(MediaSize mediaSize, boolean isDefault) { 659 if (mPrototype.mMediaSizes == null) { 660 mPrototype.mMediaSizes = new ArrayList<MediaSize>(); 661 } 662 final int insertionIndex = mPrototype.mMediaSizes.size(); 663 mPrototype.mMediaSizes.add(mediaSize); 664 if (isDefault) { 665 throwIfDefaultAlreadySpecified(PROPERTY_MEDIA_SIZE); 666 mPrototype.mDefaults[PROPERTY_MEDIA_SIZE] = insertionIndex; 667 } 668 return this; 669 } 670 671 /** 672 * Adds a supported resolution. 673 * <p> 674 * <strong>Required:</strong> Yes 675 * </p> 676 * 677 * @param resolution A resolution. 678 * @param isDefault Whether this is the default. 679 * @return This builder. 680 * 681 * @throws IllegalArgumentException If set as default and there 682 * is already a default. 683 * 684 * @see PrintAttributes.Resolution 685 */ 686 public Builder addResolution(Resolution resolution, boolean isDefault) { 687 if (mPrototype.mResolutions == null) { 688 mPrototype.mResolutions = new ArrayList<Resolution>(); 689 } 690 final int insertionIndex = mPrototype.mResolutions.size(); 691 mPrototype.mResolutions.add(resolution); 692 if (isDefault) { 693 throwIfDefaultAlreadySpecified(PROPERTY_RESOLUTION); 694 mPrototype.mDefaults[PROPERTY_RESOLUTION] = insertionIndex; 695 } 696 return this; 697 } 698 699 /** 700 * Sets the minimal margins. 701 * <p> 702 * <strong>Required:</strong> No 703 * </p> 704 * 705 * @param margins The margins. 706 * @param defaultMargins The default margins. 707 * @return This builder. 708 * 709 * @see PrintAttributes.Margins 710 */ 711 public Builder setMinMargins(Margins margins, Margins defaultMargins) { 712 if (margins.getLeftMils() > defaultMargins.getLeftMils() 713 || margins.getTopMils() > defaultMargins.getTopMils() 714 || margins.getRightMils() < defaultMargins.getRightMils() 715 || margins.getBottomMils() < defaultMargins.getBottomMils()) { 716 throw new IllegalArgumentException("Default margins" 717 + " cannot be outside of the min margins."); 718 } 719 mPrototype.mMinMargins = margins; 720 mPrototype.mDefaultMargins = defaultMargins; 721 return this; 722 } 723 724 /** 725 * Adds an input tray. 726 * <p> 727 * <strong>Required:</strong> No 728 * </p> 729 * 730 * @param inputTray A tray. 731 * @param isDefault Whether this is the default. 732 * @return This builder. 733 * 734 * @throws IllegalArgumentException If set as default and there 735 * is already a default. 736 * 737 * @see PrintAttributes.Tray 738 */ 739 public Builder addInputTray(Tray inputTray, boolean isDefault) { 740 if (mPrototype.mInputTrays == null) { 741 mPrototype.mInputTrays = new ArrayList<Tray>(); 742 } 743 final int insertionIndex = mPrototype.mInputTrays.size(); 744 mPrototype.mInputTrays.add(inputTray); 745 if (isDefault) { 746 throwIfDefaultAlreadySpecified(PROPERTY_INPUT_TRAY); 747 mPrototype.mDefaults[PROPERTY_INPUT_TRAY] = insertionIndex; 748 } 749 return this; 750 } 751 752 /** 753 * Adds an output tray. 754 * <p> 755 * <strong>Required:</strong> No 756 * </p> 757 * 758 * @param outputTray A tray. 759 * @param isDefault Whether this is the default. 760 * @return This builder. 761 * 762 * @throws IllegalArgumentException If set as default and there 763 * is already a default. 764 * 765 * @see PrintAttributes.Tray 766 */ 767 public Builder addOutputTray(Tray outputTray, boolean isDefault) { 768 if (mPrototype.mOutputTrays == null) { 769 mPrototype.mOutputTrays = new ArrayList<Tray>(); 770 } 771 final int insertionIndex = mPrototype.mOutputTrays.size(); 772 mPrototype.mOutputTrays.add(outputTray); 773 if (isDefault) { 774 throwIfDefaultAlreadySpecified(PROPERTY_OUTPUT_TRAY); 775 mPrototype.mDefaults[PROPERTY_OUTPUT_TRAY] = insertionIndex; 776 } 777 return this; 778 } 779 780 /** 781 * Sets the color modes. 782 * <p> 783 * <strong>Required:</strong> Yes 784 * </p> 785 * 786 * @param colorModes The color mode bit mask. 787 * @param defaultColorMode The default color mode. 788 * @return This builder. 789 * 790 * @throws IllegalArgumentException If color modes contains an invalid 791 * mode bit or if the default color mode is invalid. 792 * 793 * @see PrintAttributes#COLOR_MODE_COLOR 794 * @see PrintAttributes#COLOR_MODE_MONOCHROME 795 */ 796 public Builder setColorModes(int colorModes, int defaultColorMode) { 797 int currentModes = colorModes; 798 while (currentModes > 0) { 799 final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes)); 800 currentModes &= ~currentMode; 801 PrintAttributes.enforceValidColorMode(currentMode); 802 } 803 if ((colorModes & defaultColorMode) == 0) { 804 throw new IllegalArgumentException("Default color mode not in color modes."); 805 } 806 PrintAttributes.enforceValidColorMode(colorModes); 807 mPrototype.mColorModes = colorModes; 808 mPrototype.mDefaults[PROPERTY_COLOR_MODE] = defaultColorMode; 809 return this; 810 } 811 812 /** 813 * Set the duplex modes. 814 * <p> 815 * <strong>Required:</strong> No 816 * </p> 817 * 818 * @param duplexModes The duplex mode bit mask. 819 * @param defaultDuplexMode The default duplex mode. 820 * @return This builder. 821 * 822 * @throws IllegalArgumentException If duplex modes contains an invalid 823 * mode bit or if the default duplex mode is invalid. 824 * 825 * @see PrintAttributes#DUPLEX_MODE_NONE 826 * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE 827 * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE 828 */ 829 public Builder setDuplexModes(int duplexModes, int defaultDuplexMode) { 830 int currentModes = duplexModes; 831 while (currentModes > 0) { 832 final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes)); 833 currentModes &= ~currentMode; 834 PrintAttributes.enforceValidDuplexMode(currentMode); 835 } 836 if ((duplexModes & defaultDuplexMode) == 0) { 837 throw new IllegalArgumentException("Default duplex mode not in duplex modes."); 838 } 839 PrintAttributes.enforceValidDuplexMode(defaultDuplexMode); 840 mPrototype.mDuplexModes = duplexModes; 841 mPrototype.mDefaults[PROPERTY_DUPLEX_MODE] = defaultDuplexMode; 842 return this; 843 } 844 845 /** 846 * Sets the fitting modes. 847 * <p> 848 * <strong>Required:</strong> No 849 * </p> 850 * 851 * @param fittingModes The fitting mode bit mask. 852 * @param defaultFittingMode The default fitting mode. 853 * @return This builder. 854 * 855 * @throws IllegalArgumentException If fitting modes contains an invalid 856 * mode bit or if the default fitting mode is invalid. 857 * 858 * @see PrintAttributes#FITTING_MODE_NONE 859 * @see PrintAttributes#FITTING_MODE_FIT_TO_PAGE 860 */ 861 public Builder setFittingModes(int fittingModes, int defaultFittingMode) { 862 int currentModes = fittingModes; 863 while (currentModes > 0) { 864 final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes)); 865 currentModes &= ~currentMode; 866 PrintAttributes.enforceValidFittingMode(currentMode); 867 } 868 if ((fittingModes & defaultFittingMode) == 0) { 869 throw new IllegalArgumentException("Default fitting mode not in fiting modes."); 870 } 871 PrintAttributes.enforceValidFittingMode(defaultFittingMode); 872 mPrototype.mFittingModes = fittingModes; 873 mPrototype.mDefaults[PROPERTY_FITTING_MODE] = defaultFittingMode; 874 return this; 875 } 876 877 /** 878 * Sets the orientations. 879 * <p> 880 * <strong>Required:</strong> Yes 881 * </p> 882 * 883 * @param orientations The orientation bit mask. 884 * @param defaultOrientation The default orientation. 885 * @return This builder. 886 * 887 * @throws IllegalArgumentException If orientations contains an invalid 888 * mode bit or if the default orientation is invalid. 889 * 890 * @see PrintAttributes#ORIENTATION_PORTRAIT 891 * @see PrintAttributes#ORIENTATION_LANDSCAPE 892 */ 893 public Builder setOrientations(int orientations, int defaultOrientation) { 894 int currentOrientaions = orientations; 895 while (currentOrientaions > 0) { 896 final int currentOrnt = (1 << Integer.numberOfTrailingZeros(currentOrientaions)); 897 currentOrientaions &= ~currentOrnt; 898 PrintAttributes.enforceValidOrientation(currentOrnt); 899 } 900 if ((orientations & defaultOrientation) == 0) { 901 throw new IllegalArgumentException("Default orientation not in orientations."); 902 } 903 PrintAttributes.enforceValidOrientation(defaultOrientation); 904 mPrototype.mOrientations = orientations; 905 mPrototype.mDefaults[PROPERTY_ORIENTATION] = defaultOrientation; 906 return this; 907 } 908 909 /** 910 * Crates a new {@link PrinterCapabilitiesInfo} enforcing that all 911 * required properties have need specified. See individual methods 912 * in this class for reference about required attributes. 913 * 914 * @return A new {@link PrinterCapabilitiesInfo}. 915 * 916 * @throws IllegalStateException If a required attribute was not specified. 917 */ 918 public PrinterCapabilitiesInfo create() { 919 if (mPrototype.mMediaSizes == null || mPrototype.mMediaSizes.isEmpty()) { 920 throw new IllegalStateException("No media size specified."); 921 } 922 if (mPrototype.mDefaults[PROPERTY_MEDIA_SIZE] == DEFAULT_UNDEFINED) { 923 throw new IllegalStateException("No default media size specified."); 924 } 925 if (mPrototype.mResolutions == null || mPrototype.mResolutions.isEmpty()) { 926 throw new IllegalStateException("No resolution specified."); 927 } 928 if (mPrototype.mDefaults[PROPERTY_RESOLUTION] == DEFAULT_UNDEFINED) { 929 throw new IllegalStateException("No default resolution specified."); 930 } 931 if (mPrototype.mColorModes == 0) { 932 throw new IllegalStateException("No color mode specified."); 933 } 934 if (mPrototype.mDefaults[PROPERTY_COLOR_MODE] == DEFAULT_UNDEFINED) { 935 throw new IllegalStateException("No default color mode specified."); 936 } 937 if (mPrototype.mOrientations == 0) { 938 throw new IllegalStateException("No oprientation specified."); 939 } 940 if (mPrototype.mDefaults[PROPERTY_ORIENTATION] == DEFAULT_UNDEFINED) { 941 throw new IllegalStateException("No default orientation specified."); 942 } 943 if (mPrototype.mMinMargins == null) { 944 mPrototype.mMinMargins = new Margins(0, 0, 0, 0); 945 } 946 if (mPrototype.mDefaultMargins == null) { 947 mPrototype.mDefaultMargins = mPrototype.mMinMargins; 948 } 949 return new PrinterCapabilitiesInfo(mPrototype); 950 } 951 952 private void throwIfDefaultAlreadySpecified(int propertyIndex) { 953 if (mPrototype.mDefaults[propertyIndex] != DEFAULT_UNDEFINED) { 954 throw new IllegalArgumentException("Default already specified."); 955 } 956 } 957 } 958 959 public static final Parcelable.Creator<PrinterCapabilitiesInfo> CREATOR = 960 new Parcelable.Creator<PrinterCapabilitiesInfo>() { 961 @Override 962 public PrinterCapabilitiesInfo createFromParcel(Parcel parcel) { 963 return new PrinterCapabilitiesInfo(parcel); 964 } 965 966 @Override 967 public PrinterCapabilitiesInfo[] newArray(int size) { 968 return new PrinterCapabilitiesInfo[size]; 969 } 970 }; 971} 972 973