gt:         if (sides == PrintSides.DUPLEX) {
context: /*
   * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this
   * particular file as subject to the "Classpath" exception as provided
   * by Oracle in the LICENSE file that accompanied this code.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   * or visit www.oracle.com if you need additional information or have any
   * questions.
   */
  
  package com.sun.prism.j2d.print;
  
  import javafx.print.Collation;
  import javafx.print.JobSettings;
  import javafx.print.PageLayout;
  import javafx.print.PageOrientation;
  import javafx.print.PageRange;
  import javafx.print.Paper;
  import javafx.print.PaperSource;
  import javafx.print.PrintColor;
  import javafx.print.PrintResolution;
  import javafx.print.PrintSides;
  import javafx.print.Printer;
  import javafx.print.Printer.MarginType;
  import javafx.print.PrinterAttributes;
  import javafx.scene.Group;
  import javafx.scene.Node;
  import javafx.scene.Parent;
  import javafx.scene.Scene;
  import javafx.stage.Window;
  import javax.print.PrintService;
  import javax.print.attribute.HashPrintRequestAttributeSet;
  import javax.print.attribute.PrintRequestAttributeSet;
  import javax.print.attribute.ResolutionSyntax;
  import javax.print.attribute.Size2DSyntax;
  import javax.print.attribute.standard.Chromaticity;
  import javax.print.attribute.standard.Copies;
  import javax.print.attribute.standard.DialogTypeSelection;
  import javax.print.attribute.standard.Media;
  import javax.print.attribute.standard.MediaPrintableArea;
  import javax.print.attribute.standard.MediaSize;
  import javax.print.attribute.standard.MediaSizeName;
  import javax.print.attribute.standard.MediaTray;
  import javax.print.attribute.standard.OrientationRequested;
  import javax.print.attribute.standard.PageRanges;
  import javax.print.attribute.standard.PrintQuality;
  import javax.print.attribute.standard.PrinterResolution;
  import javax.print.attribute.standard.SheetCollate;
  import javax.print.attribute.standard.Sides;
  import java.awt.*;
  import java.awt.print.PageFormat;
  import java.awt.print.Pageable;
  import java.awt.print.Printable;
  import java.awt.print.PrinterException;
  import java.util.ArrayList;
  import java.util.Set;
  import com.sun.glass.ui.Application;
  import com.sun.javafx.print.PrintHelper;
  import com.sun.javafx.print.PrinterImpl;
  import com.sun.javafx.print.PrinterJobImpl;
  import com.sun.javafx.scene.NodeHelper;
  import com.sun.javafx.sg.prism.NGNode;
  import com.sun.javafx.tk.Toolkit;
  import com.sun.prism.j2d.PrismPrintGraphics;
  
  public class J2DPrinterJob implements PrinterJobImpl {
  
      javafx.print.PrinterJob fxPrinterJob;
      java.awt.print.PrinterJob pJob2D;
      javafx.print.Printer fxPrinter;
      J2DPrinter j2dPrinter;
      
      private JobSettings settings;
      private PrintRequestAttributeSet printReqAttrSet;
  
      public J2DPrinterJob(javafx.print.PrinterJob fxJob) {
  
          fxPrinterJob = fxJob;
          fxPrinter = fxPrinterJob.getPrinter();
          j2dPrinter = getJ2DPrinter(fxPrinter);
          settings = fxPrinterJob.getJobSettings();
          pJob2D = java.awt.print.PrinterJob.getPrinterJob();
          try {
              pJob2D.setPrintService(j2dPrinter.getService());
          } catch (PrinterException pe) {
          }
          printReqAttrSet = new HashPrintRequestAttributeSet();
          // dialog selection is a JDK 1.7 attribute.
          // We expect to run on 1.8 and above so this should be fine.
          printReqAttrSet.add(DialogTypeSelection.NATIVE);
      }
  
      public boolean showPrintDialog(Window owner) {
  
          if (jobRunning || jobDone) {
              return false;
          }
  
          if (GraphicsEnvironment.isHeadless()) {
              return true;
          }
  
          boolean rv = false;
          syncSettingsToAttributes();
          if (!Toolkit.getToolkit().isFxUserThread()) {
              rv = pJob2D.printDialog(printReqAttrSet);
          } else {
              rv = showPrintDialogWithNestedLoop(owner);
          }
          if (rv) {
              updateSettingsFromDialog();
          }
          return rv;
      }
  
      private class PrintDialogRunnable implements Runnable {
  
          public void run() {
              boolean rv = false;
              try {
                  rv = pJob2D.printDialog(printReqAttrSet);
              } catch (Exception e) {
              } finally {
                  Application.invokeLater(new ExitLoopRunnable(this, rv));
              }
          }
      }
  
      private boolean showPrintDialogWithNestedLoop(Window owner) {
          PrintDialogRunnable dr = new PrintDialogRunnable();
          Thread prtThread = new Thread(dr, "FX Print Dialog Thread");
          prtThread.start();
          // the nested event loop will return after the runnable exits.
          Object rv = Toolkit.getToolkit().enterNestedEventLoop(dr);
  
          boolean rvbool = false;
          try {
              rvbool = ((Boolean)rv).booleanValue();
          } catch (Exception e) {
          }
          return rvbool;
      }
  
      public boolean showPageDialog(Window owner) {
          if (jobRunning || jobDone) {
              return false;
          }
          if (GraphicsEnvironment.isHeadless()) {
              return true;
          }
          boolean rv = false;
          syncSettingsToAttributes();
          if (!Toolkit.getToolkit().isFxUserThread()) {
              PageFormat pf = pJob2D.pageDialog(printReqAttrSet);
              rv = pf != null;
          } else {
              rv = showPageDialogFromNestedLoop(owner);
          }
          if (rv) {
              updateSettingsFromDialog();
          }
          return rv;
      }
  
      private class PageDialogRunnable implements Runnable {
  
          public void run() {
              PageFormat pf = null;
              try {
                  pf = pJob2D.pageDialog(printReqAttrSet);
              } catch (Exception e) {
              } finally {
                  Boolean rv = Boolean.valueOf(pf != null);
                  Application.invokeLater(new ExitLoopRunnable(this, rv));
              }
          }
      }
  
      private boolean showPageDialogFromNestedLoop(Window owner) {
  
          PageDialogRunnable dr = new PageDialogRunnable();
          Thread prtThread = new Thread(dr, "FX Page Setup Dialog Thread");
          prtThread.start();
          // the nested event loop will return after the runnable exits.
          Object rv = Toolkit.getToolkit().enterNestedEventLoop(dr);
          boolean rvbool = false;
          try {
              rvbool = ((Boolean)rv).booleanValue();
          } catch (Exception e) {
          }
          return rvbool;
      }
  
      /*
       * The update-Foo methods here are only used to update the
       * FX JobSettings as a result of changes by user interaction
       * with a print dialog. The new values are stored in the
       * PrintRequestAttributeSet and pulled from there in to the
       * equivalent FX public API JobSettings.
       */
      private void updateJobName() {
          String name =  pJob2D.getJobName();
          if (!name.equals(settings.getJobName())) {
              settings.setJobName(name);
          }
      }
      private void updateCopies() {
          int nCopies = pJob2D.getCopies();
          if (settings.getCopies() != nCopies) {
              settings.setCopies(nCopies);
          }
      }
  
      private void updatePageRanges() {
          PageRanges ranges = (PageRanges)printReqAttrSet.get(PageRanges.class);
          // JDK sets default to 1,Integer.MAX_VALUE
          // So in this case I think we can just check for non-null and
          // only set if its non-null.
          if (ranges != null) {
              int[][] members = ranges.getMembers();
              if (members.length == 1) {
                  PageRange range = new PageRange(members[0][0], members[0][1]);
                  settings.setPageRanges(range);
              } else if (members.length > 0) {
                  try {
                      ArrayList<PageRange> prList = new ArrayList<PageRange>();
                      int last = 0;
                      for (int i=0; i<members.length;i++) {
                          int s = members[i][0];
                          int e = members[i][1];
                          if (s <= last || e < s) {
                              return;
                          }
                          last = e;
                          prList.add(new PageRange(s, e));
                      }
                      settings.setPageRanges(prList.toArray(new PageRange[0]));
                  } catch (Exception e) {
                  }
              }
          }
      }
  
      private void updateSides() {
          Sides sides = (Sides)printReqAttrSet.get(Sides.class);
          if (sides == null) {
              sides = (Sides)j2dPrinter.getService().
                  getDefaultAttributeValue(Sides.class);
          }
          if (sides == Sides.ONE_SIDED) {
              settings.setPrintSides(PrintSides.ONE_SIDED);
          } else if (sides == Sides.DUPLEX) {
              settings.setPrintSides(PrintSides.DUPLEX);
          } else if (sides == Sides.TUMBLE) {
              settings.setPrintSides(PrintSides.TUMBLE);
          }
      }
  
      /* If the attribute set has an explicit setting for
       * collation, then its been set by the user at some point,
       * even if the current value is the printer default.
       * If there is no value for collation in the attribute set,
       * it means that we are u  sing the printer default.
       */
      private void updateCollation() {
          SheetCollate collate =
              (SheetCollate)printReqAttrSet.get(SheetCollate.class);
          if (collate == null) {
              collate = j2dPrinter.getDefaultSheetCollate();
          }
          if (collate == SheetCollate.UNCOLLATED) {
              settings.setCollation(Collation.UNCOLLATED);
          } else {
              settings.setCollation(Collation.COLLATED);
          }
      }
  
      private void updateColor() {
          Chromaticity color =
              (Chromaticity)printReqAttrSet.get(Chromaticity.class);
          if (color == null) {
              color = j2dPrinter.getDefaultChromaticity();
          }
          if (color == Chromaticity.COLOR) {
              settings.setPrintColor(PrintColor.COLOR);
          } else {
              settings.setPrintColor(PrintColor.MONOCHROME);
          }
      }
  
      private void updatePrintQuality() {
          PrintQuality quality =
              (PrintQuality)printReqAttrSet.get(PrintQuality.class);
          if (quality == null) {
              quality = j2dPrinter.getDefaultPrintQuality();
          }
  
          if (quality == PrintQuality.DRAFT) {
              settings.
                  setPrintQuality(javafx.print.PrintQuality.DRAFT);
          } else if (quality == PrintQuality.HIGH) {
              settings.
                  setPrintQuality(javafx.print.PrintQuality.HIGH);
          } else {
              settings.
                  setPrintQuality(javafx.print.PrintQuality.NORMAL);
          }
      }
  
      private void updatePrintResolution() {
          PrinterResolution res =
              (PrinterResolution)printReqAttrSet.get(PrinterResolution.class);
          if (res == null) {
              res = j2dPrinter.getDefaultPrinterResolution();
          }
          int cfr = res.getCrossFeedResolution(ResolutionSyntax.DPI);
          int fr = res.getFeedResolution(ResolutionSyntax.DPI);
          settings.setPrintResolution(PrintHelper.createPrintResolution(cfr, fr));
      }
  
      private void updatePageLayout() {
          
          PageLayout oldLayout = null;
          Media media = (Media)printReqAttrSet.get(Media.class);
          Paper paper = j2dPrinter.getPaperForMedia(media);
          OrientationRequested o = (OrientationRequested)
              printReqAttrSet.get(OrientationRequested.class);
          PageOrientation orient = J2DPrinter.reverseMapOrientation(o);
          MediaPrintableArea mpa =
              (MediaPrintableArea)printReqAttrSet.get(MediaPrintableArea.class);
          PageLayout newLayout;
          if (mpa == null) {
              newLayout = fxPrinter.createPageLayout(paper, orient,
                                                     MarginType.DEFAULT);
          } else {            
              double pWid = paper.getWidth();
              double pHgt = paper.getHeight();
              int INCH = MediaPrintableArea.INCH;
              double mpaX = mpa.getX(INCH) * 72;
              double mpaY = mpa.getY(INCH) * 72;
              double mpaW = mpa.getWidth(INCH) * 72;
              double mpaH = mpa.getHeight(INCH) * 72;
              double lm=0, rm=0, tm=0, bm=0;
              switch (orient) {
              case PORTRAIT:
                  lm = mpaX;
                  rm = pWid - mpaX - mpaW;
                  tm = mpaY;
                  bm = pHgt - mpaY - mpaH;
                  break;
              case REVERSE_PORTRAIT:
                  lm = pWid - mpaX - mpaW;
                  rm = mpaX;
                  tm = pHgt - mpaY - mpaH;
                  bm = mpaY;
                  break;
              case LANDSCAPE:
                  lm = mpaY;
                  rm = pHgt - mpaY - mpaH;
                  tm = pWid - mpaX - mpaW;
                  bm = mpaX;
                  break;
              case REVERSE_LANDSCAPE:
                  lm = pHgt - mpaY - mpaH;
                  tm = mpaX;
                  rm = mpaY;
                  bm = pWid - mpaX - mpaW;
                  break;
              }
              newLayout = fxPrinter.createPageLayout(paper, orient,
                                                     lm, rm, tm, bm);
          }
          settings.setPageLayout(newLayout);
      }
  
      private void updatePaperSource() {
          Media m = (Media)printReqAttrSet.get(Media.class);
          if (m instanceof MediaTray) {
              PaperSource s = j2dPrinter.getPaperSource((MediaTray)m);
              if (s != null) {
                  settings.setPaperSource(s);
              }
          }
      }
  
      private Printer getFXPrinterForService(PrintService service) {
          Set<Printer> printerSet = Printer.getAllPrinters();
          for (Printer p : printerSet) {
              J2DPrinter p2d = (J2DPrinter)PrintHelper.getPrinterImpl(p);
              PrintService s = p2d.getService();
              if (s.equals(service)) {
                  return p;
              }
          }
          return fxPrinter; // current printer.
      }
  
      public void setPrinterImpl(PrinterImpl impl) {
          j2dPrinter = (J2DPrinter)impl;
          fxPrinter = j2dPrinter.getPrinter();
          try {
              pJob2D.setPrintService(j2dPrinter.getService());
          } catch (PrinterException pe) {
          }
      }
  
      public PrinterImpl getPrinterImpl() {
          return j2dPrinter;
      }
  
      private J2DPrinter getJ2DPrinter(Printer printer) {
          return (J2DPrinter)PrintHelper.getPrinterImpl(printer);
      }
  
      public Printer getPrinter() {
          return fxPrinter;
      }
  
      public void setPrinter(Printer printer) {
          fxPrinter = printer;
          j2dPrinter = getJ2DPrinter(printer);
          try {
              pJob2D.setPrintService(j2dPrinter.getService());
          } catch (PrinterException pe) {
          }
      }
  
      private void updatePrinter() {
          PrintService currService = j2dPrinter.getService();
          PrintService jobService = pJob2D.getPrintService();
          if (currService.equals(jobService)) {
              return; // no change
          }
          Printer newFXPrinter = getFXPrinterForService(jobService);
          // The public setPrinter call also updates the job to be valid for
          // the new printer. Any old values not supported will be updated
          // to supported values. If we do that, then apply the new user
          // settings, any listener will see both sets of changes.
          // Its best to just see the single transition.
          fxPrinterJob.setPrinter(newFXPrinter);
      }
  
      private void updateSettingsFromDialog() {
          updatePrinter();
          updateJobName();
          updateCopies();
          updatePageRanges();
          updateSides();
          updateCollation();
          updatePageLayout();
          updatePaperSource();
          updateColor();
          updatePrintQuality();
          updatePrintResolution();
      }
  
      private void syncSettingsToAttributes() {
          syncJobName();
          syncCopies();
          syncPageRanges();
          syncSides();
          syncCollation();
          syncPageLayout();
          syncPaperSource();
          syncColor();
          syncPrintQuality();
          syncPrintResolution();
      }
  
      private void syncJobName() {
          pJob2D.setJobName(settings.getJobName());
      }
  
      private void syncCopies() {
          pJob2D.setCopies(settings.getCopies());
          printReqAttrSet.add(new Copies(settings.getCopies()));
      }
  
      private void syncPageRanges() {
          printReqAttrSet.remove(PageRanges.class);
          PageRange[] prArr = settings.getPageRanges();
          if (prArr != null && prArr.length>0) {
              int len = prArr.length;
              int[][] ranges = new int[len][2];
              for (int i=0;i<len;i++) {
                  ranges[i][0] = prArr[i].getStartPage();
                  ranges[i][1] = prArr[i].getEndPage();
              }
              printReqAttrSet.add(new PageRanges(ranges));
          }
      }
  
      private void syncSides() {
          Sides j2dSides = Sides.ONE_SIDED;
          PrintSides sides = settings.getPrintSides();
  