Spec-Zone .ru
спецификации, руководства, описания, API
001/*
002 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.  Oracle designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Oracle in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
022 * or visit www.oracle.com if you need additional information or have any
023 * questions.
024 */
025
026package javafx.print;
027
028import java.util.Set;
029
030import javafx.beans.property.BooleanProperty;
031import javafx.beans.property.BooleanPropertyBase;
032import javafx.beans.property.IntegerProperty;
033import javafx.beans.property.ObjectProperty;
034import javafx.beans.property.Property;
035import javafx.beans.property.SimpleIntegerProperty;
036import javafx.beans.property.SimpleObjectProperty;
037import javafx.beans.property.SimpleStringProperty;
038import javafx.beans.property.StringProperty;
039import javafx.beans.value.ObservableValue;
040
041/**
042 * The JobSettings class encapsulates most of the configuration of a
043 * print job. Applications do not - and cannot - directly create or
044 * set a JobSettings instance. One is already installed on the print job
045 * when it is created.
046 * <p>
047 * As documented on PrinterJob, the JobSettings installed on that job will
048 * initially reflect the current default settings for the initially
049 * associated printer for that job.
050 * <p>
051 * The JobSettings delegate then remains the same for the life of the job,
052 * and will have it's member properties updated to be compatible with
053 * a change in Printer on the job. For example as a
054 * result of a user interaction via a platform's dialog.
055 * An incompatible setting will usually cause the setting to revert to
056 * the default for the new printer.
057 * <p>
058 * Any implicit or explicit updates to settings resulting from
059 * the user interaction with dialog will be propagated and visible to
060 * the application once the user approves the settings by
061 * dismissing the dialog using its "accept" option.
062 * <p>
063 * For most printing applications it is likely sufficient to let the user
064 * set the desired options and have these propagated to the job.
065 * For applications which need them,
066 * there are setter and getter methods for the individual options,
067 * which are also available as properties, and change in values of
068 * settings may be monitored and updated via these properties.
069 * <p>
070 * Not all values of settings are available on all printers. For example
071 * a printer may not support two-sided printing.
072 * See the {@link javafx.print.Printer Printer} class for how to
073 * to determine supported settings.
074 *
075 * @since JavaFX 8
076 *
077 *
078 */
079public final class JobSettings {
080
081    private PrinterJob job;
082    private Printer printer;
083    private PrinterAttributes printerCaps;
084
085    /*
086     * There's no need for client code to create a JobSettings
087     * as there is already one set on a PrinterJob and it must
088     * be updated, not replaced. So we do not expose the constructor.
089     *
090     */
091    JobSettings(Printer printer) {
092        this.printer = printer;
093        printerCaps = printer.getPrinterAttributes();
094    }
095
096    void setPrinterJob(PrinterJob job) {
097        this.job = job;
098    }
099
100    private boolean isJobNew() {
101        // If we haven't yet set the job its equivalent to a new job.
102        return job == null || job.isJobNew();
103    }
104
105
106    /*
107     * We need to be able to distinguish settings which are
108     * the printer defaults, versus explicitly set ones. so
109     * the settings object remembers for each setting if it
110     * was an explicit setting or a default.
111     * Settings such as JobName which are supportable across printers
112     * don't need this treatment.
113     */
114
115    private boolean defaultCopies = true;
116    private boolean hasOldCopies = false;
117    private int oldCopies;
118
119    private boolean defaultSides = true;
120    private boolean hasOldSides = false;
121    private PrintSides oldSides;
122
123    private boolean defaultCollation = true;
124    private boolean hasOldCollation = false;
125    private Collation oldCollation;
126
127    private boolean defaultPrintColor = true;
128    private boolean hasOldPrintColor = false;
129    private PrintColor oldPrintColor;
130
131    private boolean defaultPrintQuality = true;
132    private boolean hasOldPrintQuality = false;
133    private PrintQuality oldPrintQuality;
134
135    private boolean defaultPrintResolution = true;
136    private boolean hasOldPrintResolution = false;
137    private PrintResolution oldPrintResolution;
138
139    private boolean defaultPaperSource = true;
140    private boolean hasOldPaperSource = false;
141    private PaperSource oldPaperSource;
142
143    private boolean defaultPageLayout = true;
144    private boolean hasOldPageLayout = false;
145    private PageLayout oldPageLayout;
146
147    /**
148     * If any settings are incompatible with the specified printer,
149     * they are updated to be compatible.
150     * This method could be useful as a public one.
151     */
152    void updateForPrinter(Printer printer) {
153
154        this.printer = printer;
155        this.printerCaps = printer.getPrinterAttributes();
156
157        ////////////////////////////////////////////////
158
159        /*
160         * The algorithm for how we update is tricky in order to get
161         * the desired behaviour, which needs to be explained first.
162         * - If neither user nor code ever set a value for a property,
163         * we always update to the default for the new printer.
164         * - If user or code has ever explicitly set a value for a
165         * property then when we navigate to a different printer we
166         * remember that last set value.
167         * - If the new printer can support that value, it is used
168         * - If it can't, then we use the default value for that printer,
169         * or in a few cases some 'close' value. Such as substituting
170         * LANDSCAPE for REVERSE_LANDSCAPE.
171         * - We still remember the value and if we move to another printer
172         * that supports it, it gets resurrected.
173         */
174
175        //////////// COPIES ////////////
176
177        if (defaultCopies) {
178            if (getCopies() != printerCaps.getDefaultCopies()) {
179                setCopies(printerCaps.getDefaultCopies());
180                defaultCopies = true; // restore that this is default.
181            }
182        } else {
183            int copies = getCopies();
184            if (hasOldCopies && oldCopies > copies) {
185                copies = oldCopies;
186            }
187            int maxCopies = printerCaps.getMaxCopies();
188            if (!hasOldCopies && getCopies() > maxCopies) {
189                hasOldCopies = true;
190                oldCopies = getCopies();
191            }
192            if (copies > maxCopies) copies = maxCopies;
193            setCopies(copies);
194        }
195
196
197        ////////////////////////////////////////////////
198
199        PrintSides currSides = getPrintSides();
200        PrintSides defSides = printerCaps.getDefaultPrintSides();
201        Set<PrintSides> suppSides = printerCaps.getSupportedPrintSides();
202
203        if (defaultSides) {
204            if (currSides != defSides) {
205                setPrintSides(defSides);
206                defaultSides = true;  // restore that this is default.
207            }
208        } else {
209            // The "current" sides may not be the one we really wanted,
210            // but one that was forced by virtue of the current printer not
211            // supporting the one specified for a previous printer.
212            // Check to see if the old supported value can now
213            // be restored on this new printer.
214            if (hasOldSides) {
215                if (suppSides.contains(oldSides)) {
216                    setPrintSides(oldSides);
217                    hasOldSides = false; // is current again.
218                } else {
219                    setPrintSides(defSides);
220                }
221            } else if (!suppSides.contains(currSides)) {
222                    hasOldSides = true;
223                    oldSides = currSides;
224                    setPrintSides(defSides);
225            }
226        }
227
228        ////////////////////////////////////////////////
229
230        Collation currColl = getCollation();
231        Collation defColl = printerCaps.getDefaultCollation();
232        Set<Collation> suppColl = printerCaps.getSupportedCollations();
233
234        if (defaultCollation) {
235            if (currColl != defColl) {
236                setCollation(defColl);
237                defaultCollation = true;  // restore that this is default.
238            }
239        } else {
240            if (hasOldCollation) {
241                if (suppColl.contains(oldCollation)) {
242                    setCollation(oldCollation);
243                    hasOldCollation = false; // is current again.
244                } else {
245                    setCollation(defColl);
246                }
247            } else if (!suppColl.contains(currColl)) {
248                    hasOldCollation = true;
249                    oldCollation = currColl;
250                    setCollation(defColl);
251            }
252        }
253
254
255        ////////////////////////////////////////////////
256
257        PrintColor currColor = getPrintColor();
258        PrintColor defColor = printerCaps.getDefaultPrintColor();
259        Set<PrintColor> suppColors = printerCaps.getSupportedPrintColors();
260
261        if (defaultPrintColor) {
262            if (currColor != defColor) {
263                setPrintColor(defColor);
264                defaultPrintColor = true; // restore that this is default.
265            }
266        } else {
267            if (hasOldPrintColor) {
268                if (suppColors.contains(oldPrintColor)) {
269                    setPrintColor(oldPrintColor);
270                    hasOldPrintColor = false; // is current again.
271                } else {
272                    setPrintColor(defColor);
273                }
274            } else if (!suppColors.contains(currColor)) {
275                hasOldPrintColor = true;
276                oldPrintColor = currColor;
277                setPrintColor(defColor);
278            }
279        }
280
281        ////////////////////////////////////////////////
282
283        PrintQuality currQuality = getPrintQuality();
284        PrintQuality defQuality = printerCaps.getDefaultPrintQuality();
285        Set<PrintQuality> suppQuality = printerCaps.getSupportedPrintQuality();
286
287        if (defaultPrintQuality) {
288            if (currQuality != defQuality) {
289                setPrintQuality(defQuality);
290                defaultPrintQuality = true; // restore that this is default.
291            }
292        } else {
293            if (hasOldPrintQuality) {
294                if (suppQuality.contains(oldPrintQuality)) {
295                    setPrintQuality(oldPrintQuality);
296                    hasOldPrintQuality = false; // is current again.
297                } else {
298                    setPrintQuality(defQuality);
299                }
300            } else if (!suppQuality.contains(currQuality)) {
301                hasOldPrintQuality = true;
302                oldPrintQuality = currQuality;
303                setPrintQuality(defQuality);
304            }
305        }
306
307        ////////////////////////////////////////////////
308
309       PrintResolution currRes = getPrintResolution();
310       PrintResolution defResolution = printerCaps.getDefaultPrintResolution();
311       Set<PrintResolution> suppRes =
312           printerCaps.getSupportedPrintResolutions();
313
314       if (defaultPrintResolution) {
315           if (currRes != defResolution) {
316               setPrintResolution(defResolution);
317               defaultPrintResolution = true; // restore that this is default.
318            }
319        } else {
320            if (hasOldPrintResolution) {
321                if (suppRes.contains(oldPrintResolution)) {
322                    setPrintResolution(oldPrintResolution);
323                    hasOldPrintResolution = false; // is current again.
324                } else {
325                    setPrintResolution(defResolution);
326                }
327            } else if (!suppRes.contains(currRes)) {
328                hasOldPrintResolution = true;
329                oldPrintResolution = currRes;
330                setPrintResolution(defResolution);
331            }
332        }
333
334       ////////////////////////////////////////////////
335
336
337       PaperSource currSource = getPaperSource();
338       PaperSource defSource = printerCaps.getDefaultPaperSource();
339       Set<PaperSource> suppSources = printerCaps.getSupportedPaperSources();
340
341       if (defaultPaperSource) {
342           if (currSource != defSource) {
343               setPaperSource(defSource);
344               defaultPaperSource = true; // restore that this is default.
345            }
346        } else {
347            if (hasOldPaperSource) {
348                if (suppSources.contains(oldPaperSource)) {
349                    setPaperSource(oldPaperSource);
350                    hasOldPaperSource = false; // is current again.
351                } else {
352                    setPaperSource(defSource);
353                }
354            } else if (!suppSources.contains(currSource)) {
355                hasOldPaperSource = true;
356                oldPaperSource = currSource;
357                setPaperSource(defSource);
358            }
359        }
360
361       ///////////////////////////////////////////////////
362
363       // Paper size is an important component of PageLayout
364       // and the selected paper input tray may affect the paper sizes
365       // that are supported. For example non-standard sizes may
366       // require a manual or secondary input tray to be used.
367       // The implementation below is not accounting for that and
368       // it likely should, which means that when updating to a new
369       // printer we need to consider tray and layout together, not
370       // consecutively.
371
372       PageLayout currPageLayout = getPageLayout();
373       PageLayout defPageLayout = printer.getDefaultPageLayout();
374
375       if (defaultPageLayout) {
376           // It might appear cleaner to always set the default page layout
377           // instance for this printer, but it if they are equal, then
378           // either set(..) will skip it anyway, or it won't and a
379           // listener will see a somewhat spurious change in the property.
380           if (!currPageLayout.equals(defPageLayout)) {
381               setPageLayout(defPageLayout);
382               defaultPageLayout = true; // restore that this is default.
383            }
384        } else {
385            if (hasOldPageLayout) {
386                PageLayout valPageLayout =
387                    job.validatePageLayout(oldPageLayout);
388                if (valPageLayout.equals(oldPageLayout)) {
389                    setPageLayout(oldPageLayout);
390                    hasOldPageLayout = false; // is current again.
391                } else {
392                    setPageLayout(defPageLayout);
393                }
394            } else {
395                PageLayout valPageLayout =
396                    job.validatePageLayout(currPageLayout);
397                if (!valPageLayout.equals(currPageLayout)) {
398                    hasOldPageLayout = true;
399                    oldPageLayout = currPageLayout;
400                    // Should I use the validated layout instead ?
401                    setPageLayout(defPageLayout);
402                }
403            }
404        }
405    }
406
407    ///////////////////////  START JOBNAME /////////////////////
408
409    private static final String DEFAULT_JOBNAME = "JavaFX Print Job";
410    private SimpleStringProperty jobName;
411
412    /**
413     * <code>StringProperty</code> representing the name of a job.
414     */
415    public final StringProperty jobNameProperty() {
416        if (jobName == null) {
417            jobName = new SimpleStringProperty(JobSettings.this, "jobName",
418                                               DEFAULT_JOBNAME) {
419
420                @Override
421                public void set(String value) {
422                    if (!isJobNew()) {
423                        return;
424                    }
425                    if (value == null) {
426                        value = DEFAULT_JOBNAME;
427                    }
428                    super.set(value);
429                }
430
431                @Override
432                public void bind(ObservableValue<? extends String>
433                                 rawObservable) {
434                    throw new 
435                        RuntimeException("Jobname property cannot be bound");
436                }
437
438                @Override
439                public void bindBidirectional(Property<String> other) {
440                    throw new
441                        RuntimeException("Jobname property cannot be bound");
442                }
443            };
444        }
445        return jobName;
446    }
447
448    /**
449     * @return a string representing the name of a job.
450     */
451    public String getJobName() {
452        return jobNameProperty().get();
453    }
454
455
456    /**
457     * @param name string representing the name of a job.
458     */
459    public void setJobName(String name) {
460        jobNameProperty().set(name);
461    }
462    ///////////////////////  END JOBNAME /////////////////////
463
464    //////////////////////// START COPIES ////////////////////////
465
466    private IntegerProperty copies;
467
468    /**
469     * <code>IntegerProperty</code> representing the number of
470     * copies of the job to print.
471     */
472    public final IntegerProperty copiesProperty() {
473        if (copies == null) {
474            copies =
475                new SimpleIntegerProperty(JobSettings.this, "copies",
476                                          printerCaps.getDefaultCopies()) {
477
478                @Override
479                public void set(int value) {
480                    if (!isJobNew()) {
481                        return;
482                    }
483                    if (value <= 0) {
484                        if (defaultCopies) {
485                            return;
486                        } else {
487                            super.set(printerCaps.getDefaultCopies());
488                            defaultCopies = true;
489                            return;
490                        }
491                    }
492                    super.set(value);
493                    defaultCopies = false;
494                }
495
496                @Override
497                public void bind(ObservableValue<? extends Number>
498                                 rawObservable) {
499                    throw new 
500                        RuntimeException("Copies property cannot be bound");
501                }
502
503                @Override
504                public void bindBidirectional(Property<Number> other) {
505                    throw new
506                        RuntimeException("Copies property cannot be bound");
507                }
508            };
509        }
510        return copies;
511    }
512
513    /**
514     * @return number of copies to print.
515     */
516    public int getCopies() {
517         return copiesProperty().get();
518    }
519
520    /**
521     * @param nCopies number of copies to print.
522     */
523    public final void setCopies(int nCopies) {
524        copiesProperty().set(nCopies);
525    }
526
527    //////////////////////// END COPIES ////////////////////////
528
529
530    ///////////////////////  START PAGE RANGES /////////////////////
531    private ObjectProperty<PageRange[]> pageRanges = null;
532
533    /**
534     * An <code>ObjectProperty</code> whose value represents the job pages
535     * to print as an array of PageRange.
536     * A null values mean print all pages.
537     * Otherwise it must be a non-overlapping array of PageRange
538     * instances ordered in increasing page number.
539     * Page numbers start from 1 (one).
540     * An empty array is considered equivalent to a null array.
541     * <p>
542     * An illegal or unsupported (by the printer) set of page ranges
543     * will be ignored.
544     * <p>
545     * Ranges which exceed beyond the number of pages imaged by the job
546     * during printing do not cause any error.
547     */
548    public final ObjectProperty pageRangesProperty() {
549         if (pageRanges == null) {
550            pageRanges = new SimpleObjectProperty(JobSettings.this,
551                                                  "pageRanges", null) {
552
553                @Override
554                public void set(Object o) {
555                    try {
556                        set((PageRange[])o);
557                    } catch (ClassCastException e) {
558                        return;
559                    }
560                }
561
562                public void set(PageRange[] value) {
563                    if (!isJobNew()) {
564                        return;
565                    }
566                    if (value == null || value.length == 0 ||
567                        value[0] == null) {
568                        value = null;
569                    } else { // validate
570                        int len = value.length;
571                        PageRange[] arr = new PageRange[len];
572                        int curr = 0;
573                        for (int i=0; i<len; i++) {
574                            PageRange r = value[i];
575                            if (r == null || curr >= r.getStartPage()) {
576                                return; // bad range
577                            }
578                            curr = r.getEndPage();
579                            arr[i] = r;
580                        }
581                        value = arr;
582                    }
583                    // passed validation so its either null,
584                    // or an array of ranges in increasing order.
585                    super.set(value);
586                }
587
588                @Override
589                public void bind(ObservableValue rawObservable) {
590                    throw new RuntimeException
591                        ("PageRanges property cannot be bound");
592                }
593
594                @Override
595                public void bindBidirectional(Property other) {
596                    throw new RuntimeException
597                        ("PageRanges property cannot be bound");
598                }
599            };
600        }
601        return pageRanges;
602    }
603
604    /**
605     * The range of pages to print. null always means all pages.
606     * See {@link pageRangesProperty} for more details.
607     * @return null or an array as specified above
608     */
609    public PageRange[] getPageRanges() {
610        return (PageRange[])(pageRangesProperty().get());
611    }
612
613    /**
614     * The range of pages to print as an array of PageRange.
615     * The use of varargs means the common case of a single range
616     * can be auto-boxed.
617     * <code>((PageRange[])null)</code> always means all pages however
618     * since this is the default it is less likely to be used.
619     * See {@link pageRangesProperty} for more details.
620     * @param pages null or a varargs array as specified above
621     */
622    public void setPageRanges(PageRange... pages) {
623        pageRangesProperty().set((PageRange[])pages);
624    }
625
626    ///////////////////////  END PAGE RANGES /////////////////////
627
628
629    ///////////////////////  START SIDES  /////////////////////
630
631    private ObjectProperty<PrintSides> sides = null;
632
633    /**
634     * Property representing an instance of <code>PrintSides</code>.
635     */
636    public final ObjectProperty<PrintSides> printSidesProperty() {
637         if (sides == null) {
638             sides = new SimpleObjectProperty<PrintSides>
639                 (JobSettings.this, "printSides",
640                  printerCaps.getDefaultPrintSides()) {
641
642                @Override
643                public void set(PrintSides value) {
644                    if (!isJobNew()) {
645                        return;
646                    }
647                    if (value == null) {
648                        if (defaultSides) {
649                            return;
650                        } else {
651                            super.set(printerCaps.getDefaultPrintSides());
652                            defaultSides = true;
653                        }
654                    }
655                    if (printerCaps.getSupportedPrintSides().contains(value)) {
656                        super.set(value);
657                        defaultSides = false;
658                    }
659                }
660
661                @Override
662                public void bind(ObservableValue<? extends PrintSides>
663                                 rawObservable) {
664                    throw new RuntimeException
665                        ("PrintSides property cannot be bound");
666                }
667
668                @Override
669                public void bindBidirectional(Property<PrintSides> other) {
670                    throw new RuntimeException
671                        ("PrintSides property cannot be bound");
672                }
673            };
674        }
675        return sides;
676    }
677
678    /**
679     * If a printer supports it, then a job may be printed on
680     * both sides of the media (paper), ie duplex printing.
681     * This method returns the selected setting.
682     * @return the duplex (side) setting.
683     */
684    public PrintSides getPrintSides() {
685        return printSidesProperty().get();
686    }
687
688    /**
689     * Set the <code>PrintSides</code> property which controls
690     * duplex printing.
691     * A null value is ignored.
692     * @param sides new setting for number of sides.
693     */
694    public void setPrintSides(PrintSides sides) {
695        if (sides == getPrintSides()) {
696            return;
697        }
698        printSidesProperty().set(sides);
699    }
700    ///////////////////////  END SIDES  /////////////////////
701
702
703    ///////////////////////  START COLLATION /////////////////////
704
705    private ObjectProperty<Collation> collation = null;
706
707    /**
708     * Property representing an instance of <code>Collation</code>.
709     */
710    public final ObjectProperty<Collation> collationProperty() {
711         if (collation == null) {
712             Collation coll = printerCaps.getDefaultCollation();
713             collation = new SimpleObjectProperty<Collation>
714                (JobSettings.this, "collation", coll) {
715
716                @Override
717                public void set(Collation value) {
718                    if (!isJobNew()) {
719                        return;
720                    }
721                    if (value == null) {
722                        if (defaultCollation) {
723                            return;
724                        } else {
725                            super.set(printerCaps.getDefaultCollation());
726                            defaultCollation = true;
727                            return;
728                        }
729                    }
730                    if (printerCaps.getSupportedCollations().contains(value)) {
731                        super.set(value);
732                        defaultCollation = false;
733                    }
734                }
735
736                @Override
737                public void bind(ObservableValue<? extends Collation>
738                                 rawObservable) {
739                    throw new RuntimeException
740                        ("Collation property cannot be bound");
741                }
742
743                @Override
744                public void bindBidirectional(Property<Collation> other) {
745                    throw new RuntimeException
746                        ("Collation property cannot be bound");
747                }
748            };
749        }
750        return collation;
751    }
752
753    /**
754     * Collation determines how sheets are sorted when
755     * multiple copies of a document are printed.
756     * As such it is only relevant if 2 or more copies of
757     * a document with 2 more sheets are printed.
758     * A sheet is the physical media, so documents with 2 pages
759     * that are printed N-up, or double-sided may still have only
760     * one sheet.
761     * A collated print job produces documents with sheets
762     * of a document sorted in sequence.
763     * An uncollated job collects together the multiple copies
764     * of the same sheet.
765     * Uncollated (<code>false</false>) is the typical default value.
766     */
767    public Collation getCollation() {
768        return collationProperty().get();
769    }
770
771    /**
772     * Set the <code>Collation</code> property.
773     * A null value is ignored.
774     * @param collation new setting for collation
775     */
776    public void setCollation(Collation collation) {
777        if (collation == getCollation()) {
778            return;
779        }
780        collationProperty().set(collation);
781    }
782
783    ///////////////////////  END COLLATION /////////////////////
784
785    ///////////////////////  START COLOUR /////////////////////
786
787    private ObjectProperty<PrintColor> color = null;
788
789    /**
790     * Property representing an instance of <code>PrintColor</code>.
791     */
792    public final ObjectProperty<PrintColor> printColorProperty() {
793         if (color == null) {
794            color = new SimpleObjectProperty<PrintColor>
795                (JobSettings.this, "printColor",
796                 printerCaps.getDefaultPrintColor()) {
797
798                @Override
799                public void set(PrintColor value) {
800                    if (!isJobNew()) {
801                        return;
802                    }
803                    if (value == null) {
804                        if (defaultPrintColor) {
805                            return;
806                        } else {
807                            super.set(printerCaps.getDefaultPrintColor());
808                            defaultPrintColor = true;
809                        }
810                    }
811                    if (printerCaps.
812                        getSupportedPrintColors().contains(value)) {
813                        super.set(value);
814                        defaultPrintColor = false;
815                    }
816                }
817
818                @Override
819                public void bind(ObservableValue<? extends PrintColor>
820                                 rawObservable) {
821                    throw new RuntimeException
822                        ("PrintColor property cannot be bound");
823                }
824
825                @Override
826                public void bindBidirectional(Property<PrintColor> other) {
827                    throw new RuntimeException
828                        ("PrintColor property cannot be bound");
829                }
830            };
831        }
832        return color;
833    }
834
835    public PrintColor getPrintColor() {
836        return printColorProperty().get();
837    }
838
839    /**
840     * Set the <code>PrintColor</code> property.
841     * A null value is ignored.
842     * <p>
843     * @param color new setting for print color.
844     */
845    public void setPrintColor(PrintColor color) {
846        if (color == getPrintColor()) {
847            return;
848        }
849        printColorProperty().set(color);
850    }
851
852    ///////////////////////  END COLOUR /////////////////////
853
854    ///////////////////////  START QUALITY /////////////////////
855
856    private ObjectProperty<PrintQuality> quality = null;
857
858    /**
859     * Property representing an instance of <code>PrintQuality</code>.
860     */
861    public final ObjectProperty<PrintQuality> printQualityProperty() {
862         if (quality == null) {
863            quality = new SimpleObjectProperty<PrintQuality>
864                (JobSettings.this, "printQuality",
865                 printerCaps.getDefaultPrintQuality()) {
866
867                @Override
868                public void set(PrintQuality value) {
869                    if (!isJobNew()) {
870                        return;
871                    }
872                    if (value == null) {
873                        if (defaultPrintQuality) {
874                            return;
875                        } else {
876                            super.set(printerCaps.getDefaultPrintQuality());
877                            defaultPrintQuality = true;
878                        }
879                    }
880                    if (printerCaps.
881                        getSupportedPrintQuality().contains(value)) {
882                        super.set(value);
883                        defaultPrintQuality = false;
884                    }
885                }
886
887                @Override
888                public void bind(ObservableValue<? extends PrintQuality>
889                                 rawObservable) {
890                    throw new RuntimeException
891                        ("PrintQuality property cannot be bound");
892                }
893
894                @Override
895                public void bindBidirectional(Property<PrintQuality> other) {
896                    throw new RuntimeException
897                        ("PrintQuality property cannot be bound");
898                }
899            };
900        }
901        return quality;
902    }
903
904    public PrintQuality getPrintQuality() {
905        return  printQualityProperty().get();
906    }
907
908    /**
909     * Set the <code>PrintQuality</code> property.
910     * A null value is ignored.
911     * <p>
912     * Note that quality and resolution overlapping concepts.
913     * Therefore a printer may support setting one, or the other but
914     * not both. Applications setting these programmatically should
915     * query both properties and select appropriately from the supported
916     * values. If a printer supports non-standard values, code likely
917     * cannot distinguish the printer's interpretation of these values
918     * and is safest to stick to selecting from the standard value that
919     * matches the requirement.
920     * @param quality new setting for print quality.
921     */
922    public void setPrintQuality(PrintQuality quality) {
923        if (quality == getPrintQuality()) {
924            return;
925        }
926        printQualityProperty().set(quality);
927    }
928
929    ///////////////////////  END QUALITY /////////////////////
930
931    ///////////////////////  START RESOLUTION /////////////////////
932
933
934    private ObjectProperty<PrintResolution> resolution = null;
935
936    /**
937     * Property representing an instance of <code>PrintResolution</code>.
938     */
939    public final ObjectProperty<PrintResolution> printResolutionProperty() {
940         if (resolution == null) {
941            resolution = new SimpleObjectProperty<PrintResolution>
942                (JobSettings.this, "printResolution",
943                 printerCaps.getDefaultPrintResolution()) {
944
945                @Override
946                public void set(PrintResolution value) {
947                    if (!isJobNew()) {
948                        return;
949                    }
950                    if (value == null) {
951                        if (defaultPrintResolution) {
952                            return;
953                        } else {
954                            super.set(printerCaps.getDefaultPrintResolution());
955                            defaultPrintResolution = true;
956                        }
957                    }
958                    if (printerCaps.getSupportedPrintResolutions().
959                        contains(value))
960                    {
961                        super.set(value);
962                        defaultPrintResolution = false;
963                    }
964                }
965
966                @Override
967                public void bind(ObservableValue<? extends PrintResolution>
968                                 rawObservable) {
969                    throw new RuntimeException
970                        ("PrintResolution property cannot be bound");
971                }
972
973                @Override
974                public void bindBidirectional(Property<PrintResolution> other)
975                {
976                    throw new RuntimeException
977                        ("PrintResolution property cannot be bound");
978                }
979            };
980        }
981        return resolution;
982    }
983
984    /**
985     *
986     */
987    public PrintResolution getPrintResolution() {
988        return printResolutionProperty().get();
989    }
990
991    /**
992     * Set the <code>PrintResolution</code> property.
993     * A null value is ignored.
994     * <p>
995     * Note that quality and resolution overlapping concepts.
996     * Therefore a printer may support setting one, or the other but
997     * not both. Applications setting these programmatically should
998     * query both properties and select appropriately from the supported
999     * values. If a printer supports non-standard values, code likely
1000     * cannot distinguish the printer's interpretation of these values
1001     * and is safest to stick to selecting from the standard value that
1002     * matches the requirement.
1003     * @param resolution new setting for print resolution.
1004     */
1005    public void setPrintResolution(PrintResolution resolution) {
1006        if (resolution == null || resolution == getPrintResolution()) {
1007            return;
1008        }
1009        printResolutionProperty().set(resolution);
1010    }
1011
1012    ///////////////////////  END RESOLUTION /////////////////////
1013
1014    //////////////// START PAPERSOURCE /////////////////
1015
1016    private ObjectProperty<PaperSource> paperSource = null;
1017
1018
1019    /**
1020     * Property representing an instance of <code>PaperSource</code>.
1021     */
1022    public final ObjectProperty<PaperSource> paperSourceProperty() {
1023         if (paperSource == null) {
1024            paperSource = new SimpleObjectProperty<PaperSource>
1025                (JobSettings.this, "paperSource",
1026                 printerCaps.getDefaultPaperSource()) {
1027
1028                @Override
1029                public void set(PaperSource value) {
1030                    if (!isJobNew()) {
1031                        return;
1032                    }
1033                    if (value == null) {
1034                        if (defaultPaperSource) {
1035                            return;
1036                        } else {
1037                            super.set(printerCaps.getDefaultPaperSource());
1038                            defaultPaperSource = true;
1039                        }
1040                    }
1041                    if (printerCaps.
1042                        getSupportedPaperSources().contains(value)) {
1043                        super.set(value);
1044                        defaultPaperSource = false;
1045                    }
1046                }
1047
1048                @Override
1049                public void bind(ObservableValue<? extends PaperSource>
1050                                 rawObservable) {
1051                    throw new RuntimeException
1052                        ("PaperSource property cannot be bound");
1053                }
1054
1055                @Override
1056                public void bindBidirectional(Property<PaperSource> other) {
1057                    throw new RuntimeException
1058                        ("PaperSource property cannot be bound");
1059                }
1060            };
1061        }
1062        return paperSource;
1063    }
1064
1065
1066    public PaperSource getPaperSource() {
1067        return paperSourceProperty().get();
1068    }
1069
1070    public void setPaperSource(PaperSource value) {
1071        paperSourceProperty().set(value);
1072    }
1073
1074    //////////////// END PAPERSOURCE /////////////////
1075
1076    //////////////// START PAGELAYOUT /////////////////
1077
1078    /*
1079     * Default page needs to originate from the printer, be the
1080     * default for the initial settings on the job.
1081
1082     * having "page" be a property might make sense and perhaps
1083     * for the elts of a paper like orientation.
1084     * But what is the point in listening in on the paper of a Page
1085     * or orientation if a whole new Page is added instead ..
1086     */
1087
1088    private ObjectProperty<PageLayout> layout = null;
1089
1090    /**
1091     * Property representing an instance of <code>PageLayout</code>.
1092     */
1093    public final ObjectProperty<PageLayout> pageLayoutProperty() {
1094         if (layout == null) {
1095             layout = new SimpleObjectProperty<PageLayout>
1096                 (JobSettings.this, "pageLayout",
1097                  printer.getDefaultPageLayout()) {
1098
1099                @Override
1100                public void set(PageLayout value) {
1101                    if (!isJobNew()) {
1102                        return;
1103                    }
1104                    if (value == null) {
1105                        return;
1106                    }
1107                    defaultPageLayout = false;
1108                    super.set(value);
1109                }
1110
1111                @Override
1112                public void bind(ObservableValue<? extends PageLayout>
1113                                 rawObservable) {
1114                    throw new RuntimeException
1115                        ("PageLayout property cannot be bound");
1116                }
1117
1118                @Override
1119                public void bindBidirectional(Property<PageLayout> other) {
1120                    throw new RuntimeException
1121                        ("PageLayout property cannot be bound");
1122                }
1123            };
1124        }
1125        return layout;
1126    }
1127
1128    /**
1129     * Get the current page layout for this job.
1130     * @return page layout to use for the job.
1131     */
1132    public PageLayout getPageLayout() {
1133        return pageLayoutProperty().get();
1134    }
1135
1136    /**
1137     * Set the PageLayout to use.
1138     * @param pageLayout The page layout to use.
1139     */
1140    public void setPageLayout(PageLayout pageLayout) {
1141        pageLayoutProperty().set(pageLayout);
1142    }
1143
1144    //////////////// END PAGELAYOUT /////////////////
1145
1146    public String toString() {
1147        String nl = System.lineSeparator();
1148        return
1149            " Collation = " + getCollation() + nl +
1150            " Copies = " + getCopies() + nl +
1151            " Sides = " + getPrintSides() + nl +
1152            " JobName = " + getJobName() + nl +
1153            " Page ranges = " + getPageRanges() + nl +
1154            " Print color = " + getPrintColor() + nl +
1155            " Print quality = " + getPrintQuality() + nl +
1156            " Print resolution = " + getPrintResolution() + nl +
1157            " Paper source = " + getPaperSource() + nl +
1158            " Page layout = " + getPageLayout();
1159    }
1160}