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