PrintAttributes.java revision 4b9a4d16872bbb50712e007b419ac0b35ff1582d
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.content.pm.PackageManager;
20import android.content.pm.PackageManager.NameNotFoundException;
21import android.content.res.Resources.NotFoundException;
22import android.os.Parcel;
23import android.os.Parcelable;
24import android.text.TextUtils;
25import android.util.Log;
26
27import com.android.internal.R;
28
29/**
30 * This class represents the attributes of a print job.
31 */
32public final class PrintAttributes implements Parcelable {
33    /** Duplex mode: No duplexing */
34    public static final int DUPLEX_MODE_NONE = 1 << 0;
35    /** Duplex mode: Turn a page along its long edge, e.g. like a book */
36    public static final int DUPLEX_MODE_LONG_EDGE = 1 << 1;
37    /** Duplex mode: Turn a page along its short edge, e.g. like a notepad */
38    public static final int DUPLEX_MODE_SHORT_EDGE = 1 << 2;
39
40
41    /** Orientation: Portrait page orientation. */
42    public static final int ORIENTATION_PORTRAIT = 1 << 0;
43    /** Orientation: Landscape page orientation. */
44    public static final int ORIENTATION_LANDSCAPE = 1 << 1;
45
46
47    /** Color mode: Monochrome color scheme, e.g. one color is used. */
48    public static final int COLOR_MODE_MONOCHROME = 1 << 0;
49    /** Color mode: Color color scheme, e.g. many colors are used. */
50    public static final int COLOR_MODE_COLOR = 1 << 1;
51
52
53    /** Fitting mode: No fitting. */
54    public static final int FITTING_MODE_NONE = 0x00000001;
55    /** Fitting mode: Fit the content to the page. */
56    public static final int FITTING_MODE_FIT_TO_PAGE = 0x00000002;
57
58
59    private static final int VALID_DUPLEX_MODES =
60            DUPLEX_MODE_NONE | DUPLEX_MODE_LONG_EDGE | DUPLEX_MODE_SHORT_EDGE;
61
62    private static final int VALID_COLOR_MODES =
63            COLOR_MODE_MONOCHROME | COLOR_MODE_COLOR;
64
65    private static final int VALID_FITTING_MODES =
66            FITTING_MODE_NONE | FITTING_MODE_FIT_TO_PAGE;
67
68    private static final int VALID_ORIENTATIONS =
69            ORIENTATION_PORTRAIT | ORIENTATION_LANDSCAPE;
70
71    private MediaSize mMediaSize;
72    private Resolution mResolution;
73    private Margins mMargins;
74    private Tray mInputTray;
75    private Tray mOutputTray;
76
77    private int mDuplexMode;
78    private int mColorMode;
79    private int mFittingMode;
80    private int mOrientation;
81    private int mCopies;
82
83    PrintAttributes() {
84        /* hide constructor */
85    }
86
87    private PrintAttributes(Parcel parcel) {
88        mMediaSize = (parcel.readInt() ==  1) ? MediaSize.createFromParcel(parcel) : null;
89        mResolution = (parcel.readInt() ==  1) ? Resolution.createFromParcel(parcel) : null;
90        mMargins = (parcel.readInt() ==  1) ? Margins.createFromParcel(parcel) : null;
91        mInputTray = (parcel.readInt() ==  1) ? Tray.createFromParcel(parcel) : null;
92        mOutputTray = (parcel.readInt() ==  1) ? Tray.createFromParcel(parcel) : null;
93        mDuplexMode = parcel.readInt();
94        mColorMode = parcel.readInt();
95        mFittingMode = parcel.readInt();
96        mOrientation = parcel.readInt();
97        mCopies = parcel.readInt();
98    }
99
100    /**
101     * Gets the media size.
102     *
103     * @return The media size or <code>null</code> if not set.
104     */
105    public MediaSize getMediaSize() {
106        return mMediaSize;
107    }
108
109    /**
110     * Sets the media size.
111     *
112     * @param The media size.
113     *
114     * @hide
115     */
116    public void setMediaSize(MediaSize mediaSize) {
117        mMediaSize = mediaSize;
118    }
119
120    /**
121     * Gets the resolution.
122     *
123     * @return The resolution or <code>null</code> if not set.
124     */
125    public Resolution getResolution() {
126        return mResolution;
127    }
128
129    /**
130     * Sets the resolution.
131     *
132     * @param The resolution.
133     *
134     * @hide
135     */
136    public void setResolution(Resolution resolution) {
137        mResolution = resolution;
138    }
139
140    /**
141     * Gets the margins.
142     *
143     * @return The margins or <code>null</code> if not set.
144     */
145    public Margins getMargins() {
146        return mMargins;
147    }
148
149    /**
150     * Sets the margins.
151     *
152     * @param The margins.
153     *
154     * @hide
155     */
156    public void setMargins(Margins margins) {
157        mMargins = margins;
158    }
159
160    /**
161     * Sets the input tray.
162     *
163     * @return The input tray or <code>null</code> if not set.
164     */
165    public Tray getInputTray() {
166        return mInputTray;
167    }
168
169    /**
170     * Gets the input tray.
171     *
172     * @param The input tray.
173     *
174     * @hide
175     */
176    public void setInputTray(Tray inputTray) {
177        mInputTray = inputTray;
178    }
179
180    /**
181     * Gets the output tray.
182     *
183     * @return The output tray or <code>null</code> if not set.
184     */
185    public Tray getOutputTray() {
186        return mOutputTray;
187    }
188
189    /**
190     * Sets the output tray.
191     *
192     * @param The output tray.
193     *
194     * @hide
195     */
196    public void setOutputTray(Tray outputTray) {
197        mOutputTray = outputTray;
198    }
199
200    /**
201     * Gets the duplex mode.
202     *
203     * @return The duplex mode or zero if not set.
204     *
205     * @see #DUPLEX_MODE_NONE
206     * @see #DUPLEX_MODE_SHORT_EDGE
207     * @see #DUPLEX_MODE_LONG_EDGE
208     */
209    public int getDuplexMode() {
210        return mDuplexMode;
211    }
212
213    /**
214     * Sets the duplex mode.
215     *
216     * @param The duplex mode.
217     *
218     * @hide
219     */
220    public void setDuplexMode(int duplexMode) {
221        enforceValidDuplexMode(duplexMode);
222        mDuplexMode = duplexMode;
223    }
224
225    /**
226     * Gets the color mode.
227     *
228     * @return The color mode or zero if not set.
229     *
230     * @see #COLOR_MODE_COLOR
231     * @see #COLOR_MODE_MONOCHROME
232     */
233    public int getColorMode() {
234        return mColorMode;
235    }
236
237    /**
238     * Sets the color mode.
239     *
240     * @param The color mode.
241     *
242     * @see #COLOR_MODE_MONOCHROME
243     * @see #COLOR_MODE_COLOR
244     *
245     * @hide
246     */
247    public void setColorMode(int colorMode) {
248        enforceValidColorMode(colorMode);
249        mColorMode = colorMode;
250    }
251
252    /**
253     * Gets the fitting mode.
254     *
255     * @return The fitting mode or zero if not set.
256     *
257     * @see #FITTING_MODE_NONE
258     * @see #FITTING_MODE_FIT_TO_PAGE
259     */
260    public int getFittingMode() {
261        return mFittingMode;
262    }
263
264    /**
265     * Sets the fitting mode.
266     *
267     * @param The fitting mode.
268     *
269     * @see #FITTING_MODE_NONE
270     * @see #FITTING_MODE_FIT_TO_PAGE
271     *
272     * @hide
273     */
274    public void setFittingMode(int fittingMode) {
275        enfoceValidFittingMode(fittingMode);
276        mFittingMode = fittingMode;
277    }
278
279    /**
280     * Gets the orientation.
281     *
282     * @return The orientation or zero if not set.
283     *
284     * @see #ORIENTATION_PORTRAIT
285     * @see #ORIENTATION_LANDSCAPE
286     */
287    public int getOrientation() {
288        return mOrientation;
289    }
290
291    /**
292     * Sets the orientation.
293     *
294     * @param The orientation.
295     *
296     * @see #ORIENTATION_PORTRAIT
297     * @see #ORIENTATION_LANDSCAPE
298     *
299     * @hide
300     */
301    public void setOrientation(int orientation) {
302        enforceValidOrientation(orientation);
303        mOrientation = orientation;
304    }
305
306    /**
307     * Gets the number of copies.
308     *
309     * @return The number of copies or zero if not set.
310     */
311    public int getCopies() {
312        return mCopies;
313    }
314
315    /**
316     * Sets the number of copies.
317     *
318     * @param copyCount The number of copies.
319     *
320     * @hide
321     */
322    public void setCopies(int copyCount) {
323        if (copyCount < 1) {
324            throw new IllegalArgumentException("Copies must be more than one.");
325        }
326        mCopies = copyCount;
327    }
328
329    @Override
330    public void writeToParcel(Parcel parcel, int flags) {
331        if (mMediaSize != null) {
332            parcel.writeInt(1);
333            mMediaSize.writeToParcel(parcel);
334        } else {
335            parcel.writeInt(0);
336        }
337        if (mResolution != null) {
338            parcel.writeInt(1);
339            mResolution.writeToParcel(parcel);
340        } else {
341            parcel.writeInt(0);
342        }
343        if (mMargins != null) {
344            parcel.writeInt(1);
345            mMargins.writeToParcel(parcel);
346        } else {
347            parcel.writeInt(0);
348        }
349        if (mInputTray != null) {
350            parcel.writeInt(1);
351            mInputTray.writeToParcel(parcel);
352        } else {
353            parcel.writeInt(0);
354        }
355        if (mOutputTray != null) {
356            parcel.writeInt(1);
357            mOutputTray.writeToParcel(parcel);
358        } else {
359            parcel.writeInt(0);
360        }
361        parcel.writeInt(mDuplexMode);
362        parcel.writeInt(mColorMode);
363        parcel.writeInt(mFittingMode);
364        parcel.writeInt(mOrientation);
365        parcel.writeInt(mCopies);
366    }
367
368    @Override
369    public int describeContents() {
370        return 0;
371    }
372
373    /** hide */
374    public void clear() {
375        mMediaSize = null;
376        mResolution = null;
377        mMargins = null;
378        mInputTray = null;
379        mOutputTray = null;
380        mDuplexMode = 0;
381        mColorMode = 0;
382        mFittingMode = 0;
383        mOrientation = 0;
384        mCopies = 0;
385    }
386
387    /**
388     * This class specifies a supported media size.
389     */
390    public static final class MediaSize {
391        private static final String LOG_TAG = "MediaSize";
392
393        // TODO: Verify media sizes and add more standard ones.
394
395        // ISO sizes
396
397        /** ISO A0 media size: 841mm x 1189mm (33.11" x 46.81") */
398        public static final MediaSize ISO_A0 =
399                new MediaSize("ISO_A0", "android", R.string.mediaSize_iso_a0, 33110, 46810);
400        /** ISO A1 media size: 594mm x 841mm (23.39" x 33.11") */
401        public static final MediaSize ISO_A1 =
402                new MediaSize("ISO_A1", "android", R.string.mediaSize_iso_a1, 23390, 33110);
403        /** ISO A2 media size: 420mm x 594mm (16.54" x 23.39") */
404        public static final MediaSize ISO_A2 =
405                new MediaSize("ISO_A2", "android", R.string.mediaSize_iso_a2, 16540, 23390);
406        /** ISO A3 media size: 297mm x 420mm (11.69" x 16.54") */
407        public static final MediaSize ISO_A3 =
408                new MediaSize("ISO_A3", "android", R.string.mediaSize_iso_a3, 11690, 16540);
409        /** ISO A4 media size: 210mm x 297mm (8.27" x 11.69") */
410        public static final MediaSize ISO_A4 =
411                new MediaSize("ISO_A4", "android", R.string.mediaSize_iso_a4, 8270, 11690);
412        /** ISO A5 media size: 148mm x 210mm (5.83" x 8.27") */
413        public static final MediaSize ISO_A5 =
414                new MediaSize("ISO_A5", "android", R.string.mediaSize_iso_a5, 5830, 8270);
415        /** ISO A6 media size: 105mm x 148mm (4.13" x 5.83") */
416        public static final MediaSize ISO_A6 =
417                new MediaSize("ISO_A6", "android", R.string.mediaSize_iso_a6, 4130, 5830);
418        /** ISO A7 media size: 74mm x 105mm (2.91" x 4.13") */
419        public static final MediaSize ISO_A7 =
420                new MediaSize("ISO_A7", "android", R.string.mediaSize_iso_a7, 2910, 4130);
421        /** ISO A8 media size: 52mm x 74mm (2.05" x 2.91") */
422        public static final MediaSize ISO_A8 =
423                new MediaSize("ISO_A8", "android", R.string.mediaSize_iso_a8, 2050, 2910);
424        /** ISO A9 media size: 37mm x 52mm (1.46" x 2.05") */
425        public static final MediaSize ISO_A9 =
426                new MediaSize("ISO_A9", "android", R.string.mediaSize_iso_a9, 1460, 2050);
427        /** ISO A10 media size: 26mm x 37mm (1.02" x 1.46") */
428        public static final MediaSize ISO_A10 =
429                new MediaSize("ISO_A10", "android", R.string.mediaSize_iso_a10, 1020, 1460);
430
431        /** ISO B0 media size: 1000mm x 1414mm (39.37" x 55.67") */
432        public static final MediaSize ISO_B0 =
433                new MediaSize("ISO_B0", "android", R.string.mediaSize_iso_b0, 39370, 55670);
434        /** ISO B1 media size: 707mm x 1000mm (27.83" x 39.37") */
435        public static final MediaSize ISO_B1 =
436                new MediaSize("ISO_B1", "android", R.string.mediaSize_iso_b1, 27830, 39370);
437        /** ISO B2 media size: 500mm x 707mm (19.69" x 27.83") */
438        public static final MediaSize ISO_B2 =
439                new MediaSize("ISO_B2", "android", R.string.mediaSize_iso_b2, 19690, 27830);
440        /** ISO B3 media size: 353mm x 500mm (13.90" x 19.69") */
441        public static final MediaSize ISO_B3 =
442                new MediaSize("ISO_B3", "android", R.string.mediaSize_iso_b3, 13900, 19690);
443        /** ISO B4 media size: 250mm x 353mm (9.84" x 13.90") */
444        public static final MediaSize ISO_B4 =
445                new MediaSize("ISO_B4", "android", R.string.mediaSize_iso_b4, 9840, 13900);
446        /** ISO B5 media size: 176mm x 250mm (6.93" x 9.84") */
447        public static final MediaSize ISO_B5 =
448                new MediaSize("ISO_B5", "android", R.string.mediaSize_iso_b5, 6930, 9840);
449        /** ISO B6 media size: 125mm x 176mm (4.92" x 6.93") */
450        public static final MediaSize ISO_B6 =
451                new MediaSize("ISO_B6", "android", R.string.mediaSize_iso_b6, 4920, 6930);
452        /** ISO B7 media size: 88mm x 125mm (3.46" x 4.92") */
453        public static final MediaSize ISO_B7 =
454                new MediaSize("ISO_B7", "android", R.string.mediaSize_iso_b7, 3460, 4920);
455        /** ISO B8 media size: 62mm x 88mm (2.44" x 3.46") */
456        public static final MediaSize ISO_B8 =
457                new MediaSize("ISO_B8", "android", R.string.mediaSize_iso_b8, 2440, 3460);
458        /** ISO B9 media size: 44mm x 62mm (1.73" x 2.44") */
459        public static final MediaSize ISO_B9 =
460                new MediaSize("ISO_B9", "android", R.string.mediaSize_iso_b9, 1730, 2440);
461        /** ISO B10 media size: 31mm x 44mm (1.22" x 1.73") */
462        public static final MediaSize ISO_B10 =
463                new MediaSize("ISO_B10", "android", R.string.mediaSize_iso_b10, 1220, 1730);
464
465        /** ISO C0 media size: 917mm x 1297mm (36.10" x 51.06") */
466        public static final MediaSize ISO_C0 =
467                new MediaSize("ISO_C0", "android", R.string.mediaSize_iso_c0, 36100, 51060);
468        /** ISO C1 media size: 648mm x 917mm (25.51" x 36.10") */
469        public static final MediaSize ISO_C1 =
470                new MediaSize("ISO_C1", "android", R.string.mediaSize_iso_c1, 25510, 36100);
471        /** ISO C2 media size: 458mm x 648mm (18.03" x 25.51") */
472        public static final MediaSize ISO_C2 =
473                new MediaSize("ISO_C2", "android", R.string.mediaSize_iso_c2, 18030, 25510);
474        /** ISO C3 media size: 324mm x 458mm (12.76" x 18.03") */
475        public static final MediaSize ISO_C3 =
476                new MediaSize("ISO_C3", "android", R.string.mediaSize_iso_c3, 12760, 18030);
477        /** ISO C4 media size: 229mm x 324mm (9.02" x 12.76") */
478        public static final MediaSize ISO_C4 =
479                new MediaSize("ISO_C4", "android", R.string.mediaSize_iso_c4, 9020, 12760);
480        /** ISO C5 media size: 162mm x 229mm (6.38" x 9.02") */
481        public static final MediaSize ISO_C5 =
482                new MediaSize("ISO_C5", "android", R.string.mediaSize_iso_c5, 6380, 9020);
483        /** ISO C6 media size: 114mm x 162mm (4.49" x 6.38") */
484        public static final MediaSize ISO_C6 =
485                new MediaSize("ISO_C6", "android", R.string.mediaSize_iso_c6, 4490, 6380);
486        /** ISO C7 media size: 81mm x 114mm (3.19" x 4.49") */
487        public static final MediaSize ISO_C7 =
488                new MediaSize("ISO_C7", "android", R.string.mediaSize_iso_c7, 3190, 4490);
489        /** ISO C8 media size: 57mm x 81mm (2.24" x 3.19") */
490        public static final MediaSize ISO_C8 =
491                new MediaSize("ISO_C8", "android", R.string.mediaSize_iso_c8, 2240, 3190);
492        /** ISO C9 media size: 40mm x 57mm (1.57" x 2.24") */
493        public static final MediaSize ISO_C9 =
494                new MediaSize("ISO_C9", "android", R.string.mediaSize_iso_c9, 1570, 2240);
495        /** ISO C10 media size: 28mm x 40mm (1.10" x 1.57") */
496        public static final MediaSize ISO_C10 =
497                new MediaSize("ISO_C10", "android", R.string.mediaSize_iso_c10, 1100, 1570);
498
499        // North America
500
501        /** North America Letter media size: 8.5" x 11" */
502        public static final MediaSize NA_LETTER =
503                new MediaSize("NA_LETTER", "android", R.string.mediaSize_na_letter, 8500, 11000);
504        /** North America Government-Letter media size: 8.0" x 10.5" */
505        public static final MediaSize NA_GOVT_LETTER =
506                new MediaSize("NA_GOVT_LETTER", "android",
507                        R.string.mediaSize_na_gvrnmt_letter, 8000, 10500);
508        /** North America Legal media size: 8.5" x 14" */
509        public static final MediaSize NA_LEGAL =
510                new MediaSize("NA_LEGAL", "android", R.string.mediaSize_na_legal, 8500, 14000);
511        /** North America Junior Legal media size: 8.0" x 5.0" */
512        public static final MediaSize NA_JUNIOR_LEGAL =
513                new MediaSize("NA_JUNIOR_LEGAL", "android",
514                        R.string.mediaSize_na_junior_legal, 8000, 5000);
515        /** North America Ledger media size: 17" x 11" */
516        public static final MediaSize NA_LEDGER =
517                new MediaSize("NA_LEDGER", "android", R.string.mediaSize_na_ledger, 17000, 11000);
518        /** North America Tabloid media size: 11" x 17" */
519        public static final MediaSize NA_TBLOID =
520                new MediaSize("NA_TABLOID", "android",
521                        R.string.mediaSize_na_tabloid, 11000, 17000);
522
523        private final String mId;
524        private final String mPackageName;
525        private final int mLabelResId;
526        private final int mWidthMils;
527        private final int mHeightMils;
528
529        /**
530         * Gets the unique media size id.
531         *
532         * @return The unique media size id.
533         */
534        public String getId() {
535            return mId;
536        }
537
538        /**
539         * Gets the human readable media size label.
540         *
541         * @return The human readable label.
542         */
543        public CharSequence getLabel(PackageManager packageManager) {
544            try {
545                return packageManager.getResourcesForApplication(
546                        mPackageName).getString(mLabelResId);
547            } catch (NotFoundException nfe) {
548                Log.w(LOG_TAG, "Could not load resouce" + mLabelResId
549                        + " from package " + mPackageName);
550            } catch (NameNotFoundException nnfee) {
551                Log.w(LOG_TAG, "Could not load resouce" + mLabelResId
552                        + " from package " + mPackageName);
553            }
554            return null;
555        }
556
557        /**
558         * Gets the media width in mils (thousands of an inch).
559         *
560         * @return The media width.
561         */
562        public int getWidthMils() {
563            return mWidthMils;
564        }
565
566        /**
567         * Gets the media height in mils (thousands of an inch).
568         *
569         * @return The media height.
570         */
571        public int getHeightMils() {
572            return mHeightMils;
573        }
574
575        /**
576         * Creates a new instance.
577         *
578         * @param id The unique media size id.
579         * @param packageName The name of the creating package.
580         * @param labelResId The resource if of a human readable label.
581         * @param widthMils The width in mils (thousands of an inch).
582         * @param heightMils The height in mils (thousands of an inch).
583         *
584         * @throws IllegalArgumentException If the id is empty.
585         * @throws IllegalArgumentException If the label is empty.
586         * @throws IllegalArgumentException If the widthMils is less than or equal to zero.
587         * @throws IllegalArgumentException If the heightMils is less than or equal to zero.
588         */
589        public MediaSize(String id, String packageName, int labelResId,
590                int widthMils, int heightMils) {
591            if (TextUtils.isEmpty(id)) {
592                throw new IllegalArgumentException("id cannot be empty.");
593            }
594            if (TextUtils.isEmpty(packageName)) {
595                throw new IllegalArgumentException("packageName cannot be empty.");
596            }
597            if (labelResId <= 0) {
598                throw new IllegalArgumentException("labelResId must be greater than zero.");
599            }
600            if (widthMils <= 0) {
601                throw new IllegalArgumentException("widthMils "
602                        + "cannot be less than or equal to zero.");
603            }
604            if (heightMils <= 0) {
605                throw new IllegalArgumentException("heightMils "
606                       + "cannot be less than or euqual to zero.");
607            }
608            mPackageName = packageName;
609            mId = id;
610            mLabelResId = labelResId;
611            mWidthMils = widthMils;
612            mHeightMils = heightMils;
613        }
614
615        void writeToParcel(Parcel parcel) {
616            parcel.writeString(mId);
617            parcel.writeString(mPackageName);
618            parcel.writeInt(mLabelResId);
619            parcel.writeInt(mWidthMils);
620            parcel.writeInt(mHeightMils);
621        }
622
623        static MediaSize createFromParcel(Parcel parcel) {
624            return new MediaSize(
625                    parcel.readString(),
626                    parcel.readString(),
627                    parcel.readInt(),
628                    parcel.readInt(),
629                    parcel.readInt());
630        }
631
632        @Override
633        public String toString() {
634            StringBuilder builder = new StringBuilder();
635            builder.append("MediaSize{");
636            builder.append("id: ").append(mId);
637            builder.append(", packageName: ").append(mPackageName);
638            builder.append(", labelResId: ").append(mLabelResId);
639            builder.append(", heightMils: ").append(mHeightMils);
640            builder.append(", widthMils: ").append(mWidthMils);
641            builder.append("}");
642            return builder.toString();
643        }
644    }
645
646    /**
647     * This class specifies a supported resolution in dpi (dots per inch).
648     */
649    public static final class Resolution {
650        private static final String LOG_TAG = "Resolution";
651
652        private final String mId;
653        private final String mPackageName;
654        private final int mLabelResId;
655        private final int mHorizontalDpi;
656        private final int mVerticalDpi;
657
658        /**
659         * Gets the unique resolution id.
660         *
661         * @return The unique resolution id.
662         */
663        public String getId() {
664            return mId;
665        }
666
667        /**
668         * Gets the resolution human readable label.
669         *
670         * @return The human readable label.
671         */
672        public CharSequence getLabel(PackageManager packageManager) {
673            try {
674                return packageManager.getResourcesForApplication(
675                        mPackageName).getString(mLabelResId);
676            } catch (NotFoundException nfe) {
677                Log.w(LOG_TAG, "Could not load resouce" + mLabelResId
678                        + " from package " + mPackageName);
679            } catch (NameNotFoundException nnfee) {
680                Log.w(LOG_TAG, "Could not load resouce" + mLabelResId
681                        + " from package " + mPackageName);
682            }
683            return null;
684        }
685
686        /**
687         * Gets the horizontal resolution in dpi.
688         *
689         * @return The horizontal resolution.
690         */
691        public int getHorizontalDpi() {
692            return mHorizontalDpi;
693        }
694
695        /**
696         * Gets the vertical resolution in dpi.
697         *
698         * @return The vertical resolution.
699         */
700        public int getVerticalDpi() {
701            return mVerticalDpi;
702        }
703
704        /**
705         * Creates a new instance.
706         *
707         * @param id The unique resolution id.
708         * @param packageName The name of the creating package.
709         * @param labelResId The resource id of a human readable label.
710         * @param horizontalDpi The horizontal resolution in dpi.
711         * @param verticalDpi The vertical resolution in dpi.
712         *
713         * @throws IllegalArgumentException If the id is empty.
714         * @throws IllegalArgumentException If the label is empty.
715         * @throws IllegalArgumentException If the horizontalDpi is less than or equal to zero.
716         * @throws IllegalArgumentException If the verticalDpi is less than or equal to zero.
717         */
718        public Resolution(String id, String packageName, int labelResId,
719                int horizontalDpi, int verticalDpi) {
720            if (TextUtils.isEmpty(id)) {
721                throw new IllegalArgumentException("id cannot be empty.");
722            }
723            if (TextUtils.isEmpty(packageName)) {
724                throw new IllegalArgumentException("packageName cannot be empty.");
725            }
726            if (labelResId <= 0) {
727                throw new IllegalArgumentException("labelResId must be greater than zero.");
728            }
729            if (horizontalDpi <= 0) {
730                throw new IllegalArgumentException("horizontalDpi "
731                        + "cannot be less than or equal to zero.");
732            }
733            if (verticalDpi <= 0) {
734                throw new IllegalArgumentException("verticalDpi"
735                       + " cannot be less than or equal to zero.");
736            }
737            mId = id;
738            mPackageName = packageName;
739            mLabelResId = labelResId;
740            mHorizontalDpi = horizontalDpi;
741            mVerticalDpi = verticalDpi;
742        }
743
744        void writeToParcel(Parcel parcel) {
745            parcel.writeString(mId);
746            parcel.writeString(mPackageName);
747            parcel.writeInt(mLabelResId);
748            parcel.writeInt(mHorizontalDpi);
749            parcel.writeInt(mVerticalDpi);
750        }
751
752        static Resolution createFromParcel(Parcel parcel) {
753            return new Resolution(
754                    parcel.readString(),
755                    parcel.readString(),
756                    parcel.readInt(),
757                    parcel.readInt(),
758                    parcel.readInt());
759        }
760
761        @Override
762        public String toString() {
763            StringBuilder builder = new StringBuilder();
764            builder.append("Resolution{");
765            builder.append("id: ").append(mId);
766            builder.append(", packageName: ").append(mPackageName);
767            builder.append(", labelResId: ").append(mLabelResId);
768            builder.append(", horizontalDpi: ").append(mHorizontalDpi);
769            builder.append(", verticalDpi: ").append(mVerticalDpi);
770            builder.append("}");
771            return builder.toString();
772        }
773    }
774
775    /**
776     * This class specifies content margins.
777     */
778    public static final class Margins {
779        private final int mLeftMils;
780        private final int mTopMils;
781        private final int mRightMils;
782        private final int mBottomMils;
783
784        /**
785         * Gets the left margin in mils (thousands of an inch).
786         *
787         * @return The left margin.
788         */
789        public int getLeftMils() {
790            return mLeftMils;
791        }
792
793        /**
794         * Gets the top margin in mils (thousands of an inch).
795         *
796         * @return The top margin.
797         */
798        public int getTopMils() {
799            return mTopMils;
800        }
801
802        /**
803         * Gets the right margin in mils (thousands of an inch).
804         *
805         * @return The right margin.
806         */
807        public int getRightMils() {
808            return mRightMils;
809        }
810
811        /**
812         * Gets the bottom margin in mils (thousands of an inch).
813         *
814         * @return The bottom margin.
815         */
816        public int getBottomMils() {
817            return mBottomMils;
818        }
819
820        /**
821         * Creates a new instance.
822         *
823         * @param leftMils The left margin in mils (thousands of an inch).
824         * @param topMils The top margin in mils (thousands of an inch).
825         * @param rightMils The right margin in mils (thousands of an inch).
826         * @param bottomMils The bottom margin in mils (thousands of an inch).
827         *
828         * @throws IllegalArgumentException If the leftMils is less than zero.
829         * @throws IllegalArgumentException If the topMils is less than zero.
830         * @throws IllegalArgumentException If the rightMils is less than zero.
831         * @throws IllegalArgumentException If the bottomMils is less than zero.
832         */
833        public Margins(int leftMils, int topMils, int rightMils, int bottomMils) {
834            if (leftMils < 0) {
835                throw new IllegalArgumentException("leftMils cannot be less than zero.");
836            }
837            if (topMils < 0) {
838                throw new IllegalArgumentException("topMils cannot be less than zero.");
839            }
840            if (rightMils < 0) {
841                throw new IllegalArgumentException("rightMils cannot be less than zero.");
842            }
843            if (bottomMils < 0) {
844                throw new IllegalArgumentException("bottomMils cannot be less than zero.");
845            }
846            mTopMils = topMils;
847            mLeftMils = leftMils;
848            mRightMils = rightMils;
849            mBottomMils = bottomMils;
850        }
851
852        void writeToParcel(Parcel parcel) {
853            parcel.writeInt(mLeftMils);
854            parcel.writeInt(mTopMils);
855            parcel.writeInt(mRightMils);
856            parcel.writeInt(mBottomMils);
857        }
858
859        static Margins createFromParcel(Parcel parcel) {
860            return new Margins(
861                    parcel.readInt(),
862                    parcel.readInt(),
863                    parcel.readInt(),
864                    parcel.readInt());
865        }
866
867        @Override
868        public String toString() {
869            StringBuilder builder = new StringBuilder();
870            builder.append("Margins{");
871            builder.append("leftMils: ").append(mLeftMils);
872            builder.append(", topMils: ").append(mTopMils);
873            builder.append(", rightMils: ").append(mRightMils);
874            builder.append(", bottomMils: ").append(mBottomMils);
875            builder.append("}");
876            return builder.toString();
877        }
878    }
879
880    /**
881     * Represents a printer tray.
882     */
883    public static final class Tray {
884        private static final String LOG_TAG = "Tray";
885
886        private final String mId;
887        private final String mPackageName;
888        private final int mLabelResId;
889
890        /**
891         * Gets the unique tray id.
892         *
893         * @return The unique tray id.
894         */
895        public String getId() {
896            return mId;
897        }
898
899        /**
900         * Gets the tray human readable label.
901         *
902         * @return The human readable label.
903         */
904        public CharSequence getLabel(PackageManager packageManager) {
905            try {
906                return packageManager.getResourcesForApplication(
907                        mPackageName).getString(mLabelResId);
908            } catch (NotFoundException nfe) {
909                Log.w(LOG_TAG, "Could not load resouce" + mLabelResId
910                        + " from package " + mPackageName);
911            } catch (NameNotFoundException nnfee) {
912                Log.w(LOG_TAG, "Could not load resouce" + mLabelResId
913                        + " from package " + mPackageName);
914            }
915            return null;
916        }
917
918        /**
919         * Creates a new instance.
920         *
921         * @param id The unique tray id.
922         * @param packageName The name of the creating package.
923         * @param labelResId The resource id of a human readable label.
924         *
925         * @throws IllegalArgumentException If the id is empty.
926         * @throws IllegalArgumentException If the label is empty.
927         */
928        public Tray(String id, String packageName, int labelResId) {
929            if (TextUtils.isEmpty(id)) {
930                throw new IllegalArgumentException("id cannot be empty.");
931            }
932            if (TextUtils.isEmpty(packageName)) {
933                throw new IllegalArgumentException("packageName cannot be empty.");
934            }
935            if (labelResId <= 0) {
936                throw new IllegalArgumentException("label must be greater than zero.");
937            }
938            mId = id;
939            mPackageName = packageName;
940            mLabelResId = labelResId;
941        }
942
943        void writeToParcel(Parcel parcel) {
944            parcel.writeString(mId);
945            parcel.writeString(mPackageName);
946            parcel.writeInt(mLabelResId);
947        }
948
949        static Tray createFromParcel(Parcel parcel) {
950            return new Tray(
951                    parcel.readString(),
952                    parcel.readString(),
953                    parcel.readInt());
954        }
955
956        @Override
957        public String toString() {
958            StringBuilder builder = new StringBuilder();
959            builder.append("Tray{");
960            builder.append("id: ").append(mId);
961            builder.append("id: ").append(mId);
962            builder.append(", packageName: ").append(mPackageName);
963            builder.append(", labelResId: ").append(mLabelResId);
964            builder.append("}");
965            return builder.toString();
966        }
967    }
968
969    @Override
970    public String toString() {
971        StringBuilder builder = new StringBuilder();
972        builder.append("PrintAttributes{");
973        builder.append("mediaSize: ").append(mMediaSize);
974        builder.append(", resolution: ").append(mResolution);
975        builder.append(", margins: ").append(mMargins);
976        builder.append(", duplexMode: ").append(duplexModeToString(mDuplexMode));
977        builder.append(", colorMode: ").append(colorModeToString(mColorMode));
978        builder.append(", fittingMode: ").append(fittingModeToString(mFittingMode));
979        builder.append(", orientation: ").append(orientationToString(mOrientation));
980        builder.append(", copies: ").append(mCopies);
981        return builder.toString();
982    }
983
984    private static String duplexModeToString(int duplexMode) {
985        switch (duplexMode) {
986            case DUPLEX_MODE_NONE: {
987                return "DUPLEX_MODE_NONE";
988            }
989            case DUPLEX_MODE_LONG_EDGE: {
990                return "DUPLEX_MODE_LONG_EDGE";
991            }
992            case DUPLEX_MODE_SHORT_EDGE: {
993                return "DUPLEX_MODE_SHORT_EDGE";
994            }
995            default:
996                return "DUPLEX_MODE_UNKNOWN";
997        }
998    }
999
1000    private static String colorModeToString(int colorMode) {
1001        switch (colorMode) {
1002            case COLOR_MODE_MONOCHROME: {
1003                return "COLOR_MODE_MONOCHROME";
1004            }
1005            case COLOR_MODE_COLOR: {
1006                return "COLOR_MODE_COLOR";
1007            }
1008            default:
1009                return "COLOR_MODE_UNKNOWN";
1010        }
1011    }
1012
1013    private static String orientationToString(int orientation) {
1014        switch (orientation) {
1015            case ORIENTATION_PORTRAIT: {
1016                return "ORIENTATION_PORTRAIT";
1017            }
1018            case ORIENTATION_LANDSCAPE: {
1019                return "ORIENTATION_LANDSCAPE";
1020            }
1021            default:
1022                return "ORIENTATION_UNKNOWN";
1023        }
1024    }
1025
1026    private static String fittingModeToString(int fittingMode) {
1027        switch (fittingMode) {
1028            case FITTING_MODE_NONE: {
1029                return "FITTING_MODE_NONE";
1030            }
1031            case FITTING_MODE_FIT_TO_PAGE: {
1032                return "FITTING_MODE_FIT_TO_PAGE";
1033            }
1034            default:
1035                return "FITTING_MODE_UNKNOWN";
1036        }
1037    }
1038
1039    static void enforceValidDuplexMode(int duplexMode) {
1040        if ((duplexMode & VALID_DUPLEX_MODES) == 0) {
1041            throw new IllegalArgumentException("invalid duplex mode: " + duplexMode);
1042        }
1043    }
1044
1045    static void enforceValidColorMode(int colorMode) {
1046        if ((colorMode & VALID_COLOR_MODES) == 0) {
1047            throw new IllegalArgumentException("invalid color mode: " + colorMode);
1048        }
1049    }
1050
1051    static void enfoceValidFittingMode(int fittingMode) {
1052        if ((fittingMode & VALID_FITTING_MODES) == 0) {
1053            throw new IllegalArgumentException("invalid fitting mode: " + fittingMode);
1054        }
1055    }
1056
1057    static void enforceValidOrientation(int orientation) {
1058        if ((orientation & VALID_ORIENTATIONS) == 0) {
1059            throw new IllegalArgumentException("invalid orientation: " + orientation);
1060        }
1061    }
1062
1063    /**
1064     * Builder for creating {@link PrintAttributes}.
1065     */
1066    public static final class Builder {
1067        private final PrintAttributes mAttributes = new PrintAttributes();
1068
1069        /**
1070         * Sets the media size.
1071         *
1072         * @param mediaSize The media size.
1073         * @return This builder.
1074         */
1075        public Builder setMediaSize(MediaSize mediaSize) {
1076            mAttributes.setMediaSize(mediaSize);
1077            return this;
1078        }
1079
1080        /**
1081         * Sets the resolution.
1082         *
1083         * @param resolution The resolution.
1084         * @return This builder.
1085         */
1086        public Builder setResolution(Resolution resolution) {
1087            mAttributes.setResolution(resolution);
1088            return this;
1089        }
1090
1091        /**
1092         * Sets the margins.
1093         *
1094         * @param margins The margins.
1095         * @return This builder.
1096         */
1097        public Builder setMargins(Margins margins) {
1098            mAttributes.setMargins(margins);
1099            return this;
1100        }
1101
1102        /**
1103         * Sets the input tray.
1104         *
1105         * @param inputTray The tray.
1106         * @return This builder.
1107         */
1108        public Builder setInputTray(Tray inputTray) {
1109            mAttributes.setInputTray(inputTray);
1110            return this;
1111        }
1112
1113        /**
1114         * Sets the output tray.
1115         *
1116         * @param outputTray The tray.
1117         * @return This builder.
1118         */
1119        public Builder setOutputTray(Tray outputTray) {
1120            mAttributes.setOutputTray(outputTray);
1121            return this;
1122        }
1123
1124        /**
1125         * Sets the duplex mode.
1126         *
1127         * @param duplexMode A valid duplex mode or zero.
1128         * @return This builder.
1129         *
1130         * @see PrintAttributes#DUPLEX_MODE_NONE
1131         * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
1132         * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
1133         */
1134        public Builder setDuplexMode(int duplexMode) {
1135            if (Integer.bitCount(duplexMode) != 1) {
1136                throw new IllegalArgumentException("can specify at most one duplexMode bit.");
1137            }
1138            mAttributes.setDuplexMode(duplexMode);
1139            return this;
1140        }
1141
1142        /**
1143         * Sets the color mode.
1144         *
1145         * @param colorMode A valid color mode or zero.
1146         * @return This builder.
1147         *
1148         * @see PrintAttributes#COLOR_MODE_MONOCHROME
1149         * @see PrintAttributes#COLOR_MODE_COLOR
1150         */
1151        public Builder setColorMode(int colorMode) {
1152            if (Integer.bitCount(colorMode) > 1) {
1153                throw new IllegalArgumentException("can specify at most one colorMode bit.");
1154            }
1155            mAttributes.setColorMode(colorMode);
1156            return this;
1157        }
1158
1159        /**
1160         * Sets the fitting mode.
1161         *
1162         * @param fittingMode A valid fitting mode or zero.
1163         * @return This builder.
1164         *
1165         * @see PrintAttributes#FITTING_MODE_NONE
1166         * @see PrintAttributes#FITTING_MODE_FIT_TO_PAGE
1167         */
1168        public Builder setFittingMode(int fittingMode) {
1169            if (Integer.bitCount(fittingMode) > 1) {
1170                throw new IllegalArgumentException("can specify at most one fittingMode bit.");
1171            }
1172            mAttributes.setFittingMode(fittingMode);
1173            return this;
1174        }
1175
1176        /**
1177         * Sets the orientation.
1178         *
1179         * @param orientation A valid orientation or zero.
1180         * @return This builder.
1181         *
1182         * @see PrintAttributes#ORIENTATION_PORTRAIT
1183         * @see PrintAttributes#ORIENTATION_LANDSCAPE
1184         */
1185        public Builder setOrientation(int orientation) {
1186            if (Integer.bitCount(orientation) > 1) {
1187                throw new IllegalArgumentException("can specify at most one orientation bit.");
1188            }
1189            mAttributes.setOrientation(orientation);
1190            return this;
1191        }
1192
1193        /**
1194         * Sets the number of copies.
1195         *
1196         * @param copyCount A greater or equal to zero copy count.
1197         * @return This builder.
1198         */
1199        public Builder setCopyCount(int copyCount) {
1200            mAttributes.setCopies(copyCount);
1201            return this;
1202        }
1203
1204        /**
1205         * Creates a new {@link PrintAttributes} instance.
1206         *
1207         * @return The new instance.
1208         */
1209        public PrintAttributes create() {
1210            return mAttributes;
1211        }
1212    }
1213
1214    public static final Parcelable.Creator<PrintAttributes> CREATOR =
1215            new Creator<PrintAttributes>() {
1216        @Override
1217        public PrintAttributes createFromParcel(Parcel parcel) {
1218            return new PrintAttributes(parcel);
1219        }
1220
1221        @Override
1222        public PrintAttributes[] newArray(int size) {
1223            return new PrintAttributes[size];
1224        }
1225    };
1226}
1227