4673406: RFE: Java Printing: Provide a way to display win32 printer driver's dialog
Reviewed-by: jgodinez, bae
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/print/DocumentPropertiesUI.java Fri Aug 30 10:25:55 2013 -0700
@@ -0,0 +1,62 @@
+/*
+ * 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 sun.print;
+
+import java.awt.Window;
+import java.awt.print.PrinterJob;
+import javax.print.PrintService;
+import javax.print.ServiceUIFactory;
+import javax.print.attribute.PrintRequestAttributeSet;
+
+public abstract class DocumentPropertiesUI {
+
+ /**
+ * For Win32 doc properties sheet.
+ */
+ public static final int
+ DOCUMENTPROPERTIES_ROLE = ServiceUIFactory.RESERVED_UIROLE +100;
+
+ /**
+ * Name of (this) abstract class for Document Properties.
+ */
+ public static final String
+ DOCPROPERTIESCLASSNAME = DocumentPropertiesUI.class.getName();
+
+ /**
+ * Invokes whatever code is needed to display a native dialog
+ * with the specified owner. The owner should be the cross-platform
+ * dialog. If the user cancels the dialog the return value is null.
+ * A non-null return value is always a new attribute set (or is it?)
+ * The cross-platform dialog may need to be updated to reflect the
+ * updated properties.
+ */
+ public abstract PrintRequestAttributeSet
+ showDocumentProperties(PrinterJob job,
+ Window owner,
+ PrintService service,
+ PrintRequestAttributeSet aset);
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/print/PrinterJobWrapper.java Fri Aug 30 10:25:55 2013 -0700
@@ -0,0 +1,60 @@
+/*
+ * 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 sun.print;
+
+import java.awt.print.PrinterJob;
+import javax.print.attribute.PrintRequestAttribute;
+
+public class PrinterJobWrapper implements PrintRequestAttribute {
+
+ private static final long serialVersionUID = -8792124426995707237L;
+
+ private PrinterJob job;
+
+ public PrinterJobWrapper(PrinterJob job) {
+ this.job = job;
+ }
+
+ public PrinterJob getPrinterJob() {
+ return job;
+ }
+
+ public final Class getCategory() {
+ return PrinterJobWrapper.class;
+ }
+
+ public final String getName() {
+ return "printerjob-wrapper";
+ }
+
+ public String toString() {
+ return "printerjob-wrapper: " + job.toString();
+ }
+
+ public int hashCode() {
+ return job.hashCode();
+ }
+}
--- a/jdk/src/share/classes/sun/print/RasterPrinterJob.java Fri Aug 30 09:10:30 2013 -0700
+++ b/jdk/src/share/classes/sun/print/RasterPrinterJob.java Fri Aug 30 10:25:55 2013 -0700
@@ -903,6 +903,9 @@
int x = bounds.x+bounds.width/3;
int y = bounds.y+bounds.height/3;
PrintService newService;
+ // temporarily add an attribute pointing back to this job.
+ PrinterJobWrapper jobWrapper = new PrinterJobWrapper(this);
+ attributes.add(jobWrapper);
try {
newService =
ServiceUI.printDialog(gc, x, y,
@@ -915,6 +918,7 @@
DocFlavor.SERVICE_FORMATTED.PAGEABLE,
attributes);
}
+ attributes.remove(PrinterJobWrapper.class);
if (newService == null) {
return false;
--- a/jdk/src/share/classes/sun/print/ServiceDialog.java Fri Aug 30 09:10:30 2013 -0700
+++ b/jdk/src/share/classes/sun/print/ServiceDialog.java Fri Aug 30 10:25:55 2013 -0700
@@ -46,6 +46,7 @@
import java.awt.event.ItemListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowAdapter;
+import java.awt.print.PrinterJob;
import java.io.File;
import java.io.FilePermission;
import java.io.IOException;
@@ -119,8 +120,6 @@
private AppearancePanel pnlAppearance;
private boolean isAWT = false;
-
-
static {
initResource();
}
@@ -801,9 +800,32 @@
if (dialog != null) {
dialog.show();
} else {
- // REMIND: may want to notify the user why we're
- // disabling the button
- btnProperties.setEnabled(false);
+ DocumentPropertiesUI docPropertiesUI = null;
+ try {
+ docPropertiesUI =
+ (DocumentPropertiesUI)uiFactory.getUI
+ (DocumentPropertiesUI.DOCUMENTPROPERTIES_ROLE,
+ DocumentPropertiesUI.DOCPROPERTIESCLASSNAME);
+ } catch (Exception ex) {
+ }
+ if (docPropertiesUI != null) {
+ PrinterJobWrapper wrapper = (PrinterJobWrapper)
+ asCurrent.get(PrinterJobWrapper.class);
+ if (wrapper == null) {
+ return; // should not happen, defensive only.
+ }
+ PrinterJob job = wrapper.getPrinterJob();
+ if (job == null) {
+ return; // should not happen, defensive only.
+ }
+ PrintRequestAttributeSet newAttrs =
+ docPropertiesUI.showDocumentProperties
+ (job, ServiceDialog.this, psCurrent, asCurrent);
+ if (newAttrs != null) {
+ asCurrent.addAll(newAttrs);
+ updatePanels();
+ }
+ }
}
}
}
--- a/jdk/src/windows/classes/sun/awt/windows/WPrinterJob.java Fri Aug 30 09:10:30 2013 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WPrinterJob.java Fri Aug 30 10:25:55 2013 -0700
@@ -179,6 +179,7 @@
private static final int SET_RES_LOW = 0x00000080;
private static final int SET_COLOR = 0x00000200;
private static final int SET_ORIENTATION = 0x00004000;
+ private static final int SET_COLLATED = 0x00008000;
/**
* Values must match those defined in wingdi.h & commdlg.h
@@ -189,10 +190,33 @@
private static final int PD_NOSELECTION = 0x00000004;
private static final int PD_COLLATE = 0x00000010;
private static final int PD_PRINTTOFILE = 0x00000020;
- private static final int DM_ORIENTATION = 0x00000001;
- private static final int DM_PRINTQUALITY = 0x00000400;
- private static final int DM_COLOR = 0x00000800;
- private static final int DM_DUPLEX = 0x00001000;
+ private static final int DM_ORIENTATION = 0x00000001;
+ private static final int DM_PAPERSIZE = 0x00000002;
+ private static final int DM_COPIES = 0x00000100;
+ private static final int DM_DEFAULTSOURCE = 0x00000200;
+ private static final int DM_PRINTQUALITY = 0x00000400;
+ private static final int DM_COLOR = 0x00000800;
+ private static final int DM_DUPLEX = 0x00001000;
+ private static final int DM_YRESOLUTION = 0x00002000;
+ private static final int DM_COLLATE = 0x00008000;
+
+ private static final short DMCOLLATE_FALSE = 0;
+ private static final short DMCOLLATE_TRUE = 1;
+
+ private static final short DMORIENT_PORTRAIT = 1;
+ private static final short DMORIENT_LANDSCAPE = 2;
+
+ private static final short DMCOLOR_MONOCHROME = 1;
+ private static final short DMCOLOR_COLOR = 2;
+
+ private static final short DMRES_DRAFT = -1;
+ private static final short DMRES_LOW = -2;
+ private static final short DMRES_MEDIUM = -3;
+ private static final short DMRES_HIGH = -4;
+
+ private static final short DMDUP_SIMPLEX = 1;
+ private static final short DMDUP_VERTICAL = 2;
+ private static final short DMDUP_HORIZONTAL = 3;
/**
* Pageable MAX pages
@@ -592,13 +616,23 @@
}
driverDoesMultipleCopies = false;
driverDoesCollation = false;
- setNativePrintService(service.getName());
+ setNativePrintServiceIfNeeded(service.getName());
}
/* associates this job with the specified native service */
private native void setNativePrintService(String name)
throws PrinterException;
+ private String lastNativeService = null;
+ private void setNativePrintServiceIfNeeded(String name)
+ throws PrinterException {
+
+ if (name != null && !(name.equals(lastNativeService))) {
+ setNativePrintService(name);
+ lastNativeService = name;
+ }
+ }
+
public PrintService getPrintService() {
if (myService == null) {
String printerName = getNativePrintService();
@@ -616,7 +650,7 @@
myService = PrintServiceLookup.lookupDefaultPrintService();
if (myService != null) {
try {
- setNativePrintService(myService.getName());
+ setNativePrintServiceIfNeeded(myService.getName());
} catch (Exception e) {
myService = null;
}
@@ -1754,8 +1788,13 @@
mAttMediaSizeName = ((Win32PrintService)myService).findPaperID(msn);
}
- private void setWin32MediaAttrib(int dmIndex, int width, int length) {
- MediaSizeName msn =
+ private void addPaperSize(PrintRequestAttributeSet aset,
+ int dmIndex, int width, int length) {
+
+ if (aset == null) {
+ return;
+ }
+ MediaSizeName msn =
((Win32PrintService)myService).findWin32Media(dmIndex);
if (msn == null) {
msn = ((Win32PrintService)myService).
@@ -1763,10 +1802,12 @@
}
if (msn != null) {
- if (attributes != null) {
- attributes.add(msn);
- }
+ aset.add(msn);
}
+ }
+
+ private void setWin32MediaAttrib(int dmIndex, int width, int length) {
+ addPaperSize(attributes, dmIndex, width, length);
mAttMediaSizeName = dmIndex;
}
@@ -1788,7 +1829,7 @@
// no equivalent predefined value
mAttMediaTray = 7; // DMBIN_AUTO
} else if (attr == MediaTray.TOP) {
- mAttMediaTray =1; // DMBIN_UPPER
+ mAttMediaTray = 1; // DMBIN_UPPER
} else {
if (attr instanceof Win32MediaTray) {
mAttMediaTray = ((Win32MediaTray)attr).winID;
@@ -1914,6 +1955,254 @@
}
}
+ private static final class DevModeValues {
+ int dmFields;
+ short copies;
+ short collate;
+ short color;
+ short duplex;
+ short orient;
+ short paper;
+ short bin;
+ short xres_quality;
+ short yres;
+ }
+
+ private void getDevModeValues(PrintRequestAttributeSet aset,
+ DevModeValues info) {
+
+ Copies c = (Copies)aset.get(Copies.class);
+ if (c != null) {
+ info.dmFields |= DM_COPIES;
+ info.copies = (short)c.getValue();
+ }
+
+ SheetCollate sc = (SheetCollate)aset.get(SheetCollate.class);
+ if (sc != null) {
+ info.dmFields |= DM_COLLATE;
+ info.collate = (sc == SheetCollate.COLLATED) ?
+ DMCOLLATE_TRUE : DMCOLLATE_FALSE;
+ }
+
+ Chromaticity ch = (Chromaticity)aset.get(Chromaticity.class);
+ if (ch != null) {
+ info.dmFields |= DM_COLOR;
+ if (ch == Chromaticity.COLOR) {
+ info.color = DMCOLOR_COLOR;
+ } else {
+ info.color = DMCOLOR_MONOCHROME;
+ }
+ }
+
+ Sides s = (Sides)aset.get(Sides.class);
+ if (s != null) {
+ info.dmFields |= DM_DUPLEX;
+ if (s == Sides.TWO_SIDED_LONG_EDGE) {
+ info.duplex = DMDUP_VERTICAL;
+ } else if (s == Sides.TWO_SIDED_SHORT_EDGE) {
+ info.duplex = DMDUP_HORIZONTAL;
+ } else { // Sides.ONE_SIDED
+ info.duplex = DMDUP_SIMPLEX;
+ }
+ }
+
+ OrientationRequested or =
+ (OrientationRequested)aset.get(OrientationRequested.class);
+ if (or != null) {
+ info.dmFields |= DM_ORIENTATION;
+ info.orient = (or == OrientationRequested.LANDSCAPE)
+ ? DMORIENT_LANDSCAPE : DMORIENT_PORTRAIT;
+ }
+
+ Media m = (Media)aset.get(Media.class);
+ if (m instanceof MediaSizeName) {
+ info.dmFields |= DM_PAPERSIZE;
+ MediaSizeName msn = (MediaSizeName)m;
+ info.paper =
+ (short)((Win32PrintService)myService).findPaperID(msn);
+ }
+
+ MediaTray mt = null;
+ if (m instanceof MediaTray) {
+ mt = (MediaTray)m;
+ }
+ if (mt == null) {
+ SunAlternateMedia sam =
+ (SunAlternateMedia)aset.get(SunAlternateMedia.class);
+ if (sam != null && (sam.getMedia() instanceof MediaTray)) {
+ mt = (MediaTray)sam.getMedia();
+ }
+ }
+
+ if (mt != null) {
+ info.dmFields |= DM_DEFAULTSOURCE;
+ info.bin = (short)(((Win32PrintService)myService).findTrayID(mt));
+ }
+
+ PrintQuality q = (PrintQuality)aset.get(PrintQuality.class);
+ if (q != null) {
+ info.dmFields |= DM_PRINTQUALITY;
+ if (q == PrintQuality.DRAFT) {
+ info.xres_quality = DMRES_DRAFT;
+ } else if (q == PrintQuality.HIGH) {
+ info.xres_quality = DMRES_HIGH;
+ } else {
+ info.xres_quality = DMRES_MEDIUM;
+ }
+ }
+
+ PrinterResolution r =
+ (PrinterResolution)aset.get(PrinterResolution.class);
+ if (r != null) {
+ info.dmFields |= DM_PRINTQUALITY | DM_YRESOLUTION;
+ info.xres_quality =
+ (short)r.getCrossFeedResolution(PrinterResolution.DPI);
+ info.yres = (short)r.getFeedResolution(PrinterResolution.DPI);
+ }
+ }
+
+ /* This method is called from native to update the values in the
+ * attribute set which originates from the cross-platform dialog,
+ * but updated by the native DocumentPropertiesUI which updates the
+ * devmode. This syncs the devmode back in to the attributes so that
+ * we can update the cross-platform dialog.
+ * The attribute set here is a temporary one installed whilst this
+ * happens,
+ */
+ private final void setJobAttributes(PrintRequestAttributeSet attributes,
+ int fields, int values,
+ short copies,
+ short dmPaperSize,
+ short dmPaperWidth,
+ short dmPaperLength,
+ short dmDefaultSource,
+ short xRes,
+ short yRes) {
+
+ if (attributes == null) {
+ return;
+ }
+
+ if ((fields & DM_COPIES) != 0) {
+ attributes.add(new Copies(copies));
+ }
+
+ if ((fields & DM_COLLATE) != 0) {
+ if ((values & SET_COLLATED) != 0) {
+ attributes.add(SheetCollate.COLLATED);
+ } else {
+ attributes.add(SheetCollate.UNCOLLATED);
+ }
+ }
+
+ if ((fields & DM_ORIENTATION) != 0) {
+ if ((values & SET_ORIENTATION) != 0) {
+ attributes.add(OrientationRequested.LANDSCAPE);
+ } else {
+ attributes.add(OrientationRequested.PORTRAIT);
+ }
+ }
+
+ if ((fields & DM_COLOR) != 0) {
+ if ((values & SET_COLOR) != 0) {
+ attributes.add(Chromaticity.COLOR);
+ } else {
+ attributes.add(Chromaticity.MONOCHROME);
+ }
+ }
+
+ if ((fields & DM_PRINTQUALITY) != 0) {
+ /* value < 0 indicates quality setting.
+ * value > 0 indicates X resolution. In that case
+ * hopefully we will also find y-resolution specified.
+ * If its not, assume its the same as x-res.
+ * Maybe Java code should try to reconcile this against
+ * the printers claimed set of supported resolutions.
+ */
+ if (xRes < 0) {
+ PrintQuality quality;
+ if ((values & SET_RES_LOW) != 0) {
+ quality = PrintQuality.DRAFT;
+ } else if ((fields & SET_RES_HIGH) != 0) {
+ quality = PrintQuality.HIGH;
+ } else {
+ quality = PrintQuality.NORMAL;
+ }
+ attributes.add(quality);
+ } else if (xRes > 0 && yRes > 0) {
+ attributes.add(
+ new PrinterResolution(xRes, yRes, PrinterResolution.DPI));
+ }
+ }
+
+ if ((fields & DM_DUPLEX) != 0) {
+ Sides sides;
+ if ((values & SET_DUP_VERTICAL) != 0) {
+ sides = Sides.TWO_SIDED_LONG_EDGE;
+ } else if ((values & SET_DUP_HORIZONTAL) != 0) {
+ sides = Sides.TWO_SIDED_SHORT_EDGE;
+ } else {
+ sides = Sides.ONE_SIDED;
+ }
+ attributes.add(sides);
+ }
+
+ if ((fields & DM_PAPERSIZE) != 0) {
+ addPaperSize(attributes, dmPaperSize, dmPaperWidth, dmPaperLength);
+ }
+
+ if ((fields & DM_DEFAULTSOURCE) != 0) {
+ MediaTray tray =
+ ((Win32PrintService)myService).findMediaTray(dmDefaultSource);
+ attributes.add(new SunAlternateMedia(tray));
+ }
+ }
+
+ private native boolean showDocProperties(long hWnd,
+ PrintRequestAttributeSet aset,
+ int dmFields,
+ short copies,
+ short collate,
+ short color,
+ short duplex,
+ short orient,
+ short paper,
+ short bin,
+ short xres_quality,
+ short yres);
+
+ @SuppressWarnings("deprecation")
+ public PrintRequestAttributeSet
+ showDocumentProperties(Window owner,
+ PrintService service,
+ PrintRequestAttributeSet aset)
+ {
+ try {
+ setNativePrintServiceIfNeeded(service.getName());
+ } catch (PrinterException e) {
+ }
+ long hWnd = ((WWindowPeer)(owner.getPeer())).getHWnd();
+ DevModeValues info = new DevModeValues();
+ getDevModeValues(aset, info);
+ boolean ok =
+ showDocProperties(hWnd, aset,
+ info.dmFields,
+ info.copies,
+ info.collate,
+ info.color,
+ info.duplex,
+ info.orient,
+ info.paper,
+ info.bin,
+ info.xres_quality,
+ info.yres);
+
+ if (ok) {
+ return aset;
+ } else {
+ return null;
+ }
+ }
/* Printer Resolution. See also getXRes() and getYRes() */
private final void setResolutionDPI(int xres, int yres) {
@@ -1956,7 +2245,7 @@
}
//** END Functions called by native code for querying/updating attributes
- }
+ }
class PrintToFileErrorDialog extends Dialog implements ActionListener{
public PrintToFileErrorDialog(Frame parent, String title, String message,
--- a/jdk/src/windows/classes/sun/print/Win32MediaTray.java Fri Aug 30 09:10:30 2013 -0700
+++ b/jdk/src/windows/classes/sun/print/Win32MediaTray.java Fri Aug 30 10:25:55 2013 -0700
@@ -70,6 +70,10 @@
winEnumTable.add(this);
}
+ public int getDMBinID() {
+ return winID;
+ }
+
private static final String[] myStringTable ={
"Manual-Envelope",
"Automatic-Feeder",
--- a/jdk/src/windows/classes/sun/print/Win32PrintService.java Fri Aug 30 09:10:30 2013 -0700
+++ b/jdk/src/windows/classes/sun/print/Win32PrintService.java Fri Aug 30 10:25:55 2013 -0700
@@ -25,6 +25,8 @@
package sun.print;
+import java.awt.Window;
+import java.awt.print.PrinterJob;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
@@ -39,6 +41,7 @@
import javax.print.attribute.AttributeSetUtilities;
import javax.print.attribute.EnumSyntax;
import javax.print.attribute.HashAttributeSet;
+import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.PrintServiceAttribute;
import javax.print.attribute.PrintServiceAttributeSet;
import javax.print.attribute.HashPrintServiceAttributeSet;
@@ -69,6 +72,7 @@
import javax.print.attribute.standard.PrinterResolution;
import javax.print.attribute.standard.SheetCollate;
import javax.print.event.PrintServiceAttributeListener;
+import sun.awt.windows.WPrinterJob;
public class Win32PrintService implements PrintService, AttributeUpdater,
SunPrinterJobService {
@@ -282,6 +286,22 @@
return 0;
}
+ public int findTrayID(MediaTray tray) {
+
+ getMediaTrays(); // make sure they are initialised.
+
+ if (tray instanceof Win32MediaTray) {
+ Win32MediaTray winTray = (Win32MediaTray)tray;
+ return winTray.getDMBinID();
+ }
+ for (int id=0; id<dmPaperBinToPrintService.length; id++) {
+ if (tray.equals(dmPaperBinToPrintService[id])) {
+ return id+1; // DMBIN_FIRST = 1;
+ }
+ }
+ return 0; // didn't find the tray
+ }
+
public MediaTray findMediaTray(int dmBin) {
if (dmBin >= 1 && dmBin <= dmPaperBinToPrintService.length) {
return dmPaperBinToPrintService[dmBin-1];
@@ -673,7 +693,6 @@
return arr2;
}
-
private PrinterIsAcceptingJobs getPrinterIsAcceptingJobs() {
if (getJobStatus(printer, 2) != 1) {
return PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS;
@@ -1596,8 +1615,76 @@
}
}
- public ServiceUIFactory getServiceUIFactory() {
- return null;
+ private Win32DocumentPropertiesUI docPropertiesUI = null;
+
+ private static class Win32DocumentPropertiesUI
+ extends DocumentPropertiesUI {
+
+ Win32PrintService service;
+
+ private Win32DocumentPropertiesUI(Win32PrintService s) {
+ service = s;
+ }
+
+ public PrintRequestAttributeSet
+ showDocumentProperties(PrinterJob job,
+ Window owner,
+ PrintService service,
+ PrintRequestAttributeSet aset) {
+
+ if (!(job instanceof WPrinterJob)) {
+ return null;
+ }
+ WPrinterJob wJob = (WPrinterJob)job;
+ return wJob.showDocumentProperties(owner, service, aset);
+ }
+ }
+
+ private synchronized DocumentPropertiesUI getDocumentPropertiesUI() {
+ return new Win32DocumentPropertiesUI(this);
+ }
+
+ private static class Win32ServiceUIFactory extends ServiceUIFactory {
+
+ Win32PrintService service;
+
+ Win32ServiceUIFactory(Win32PrintService s) {
+ service = s;
+ }
+
+ public Object getUI(int role, String ui) {
+ if (role <= ServiceUIFactory.MAIN_UIROLE) {
+ return null;
+ }
+ if (role == DocumentPropertiesUI.DOCUMENTPROPERTIES_ROLE &&
+ DocumentPropertiesUI.DOCPROPERTIESCLASSNAME.equals(ui))
+ {
+ return service.getDocumentPropertiesUI();
+ }
+ throw new IllegalArgumentException("Unsupported role");
+ }
+
+ public String[] getUIClassNamesForRole(int role) {
+
+ if (role <= ServiceUIFactory.MAIN_UIROLE) {
+ return null;
+ }
+ if (role == DocumentPropertiesUI.DOCUMENTPROPERTIES_ROLE) {
+ String[] names = new String[0];
+ names[0] = DocumentPropertiesUI.DOCPROPERTIESCLASSNAME;
+ return names;
+ }
+ throw new IllegalArgumentException("Unsupported role");
+ }
+ }
+
+ private Win32ServiceUIFactory uiFactory = null;
+
+ public synchronized ServiceUIFactory getServiceUIFactory() {
+ if (uiFactory == null) {
+ uiFactory = new Win32ServiceUIFactory(this);
+ }
+ return uiFactory;
}
public String toString() {
--- a/jdk/src/windows/native/sun/windows/awt_PrintControl.cpp Fri Aug 30 09:10:30 2013 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_PrintControl.cpp Fri Aug 30 10:25:55 2013 -0700
@@ -81,6 +81,7 @@
jmethodID AwtPrintControl::setNativeAttID;
jmethodID AwtPrintControl::setRangeCopiesID;
jmethodID AwtPrintControl::setResID;
+jmethodID AwtPrintControl::setJobAttributesID;
BOOL AwtPrintControl::IsSupportedLevel(HANDLE hPrinter, DWORD dwLevel) {
@@ -297,6 +298,10 @@
AwtPrintControl::setPrinterID =
env->GetMethodID(cls, "setPrinterNameAttrib", "(Ljava/lang/String;)V");
+ AwtPrintControl::setJobAttributesID =
+ env->GetMethodID(cls, "setJobAttributes",
+ "(Ljavax/print/attribute/PrintRequestAttributeSet;IISSSSSSS)V");
+
DASSERT(AwtPrintControl::driverDoesMultipleCopiesID != NULL);
DASSERT(AwtPrintControl::getPrintDCID != NULL);
DASSERT(AwtPrintControl::setPrintDCID != NULL);
@@ -327,6 +332,7 @@
DASSERT(AwtPrintControl::getSidesID != NULL);
DASSERT(AwtPrintControl::getSelectID != NULL);
DASSERT(AwtPrintControl::getPrintToFileEnabledID != NULL);
+ DASSERT(AwtPrintControl::setJobAttributesID != NULL);
CATCH_BAD_ALLOC;
--- a/jdk/src/windows/native/sun/windows/awt_PrintControl.h Fri Aug 30 09:10:30 2013 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_PrintControl.h Fri Aug 30 10:25:55 2013 -0700
@@ -47,7 +47,6 @@
static jmethodID setDevmodeID;
static jmethodID getDevnamesID;
static jmethodID setDevnamesID;
-
static jmethodID getWin32MediaID;
static jmethodID setWin32MediaID;
static jmethodID getWin32MediaTrayID;
@@ -73,6 +72,7 @@
static jmethodID setNativeAttID;
static jmethodID setRangeCopiesID;
static jmethodID setResID;
+ static jmethodID setJobAttributesID;
static void initIDs(JNIEnv *env, jclass cls);
static BOOL FindPrinter(jstring printerName, LPBYTE pPrinterEnum,
--- a/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp Fri Aug 30 09:10:30 2013 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp Fri Aug 30 10:25:55 2013 -0700
@@ -329,6 +329,156 @@
static int embolden(int currentWeight);
static BOOL getPrintableArea(HDC pdc, HANDLE hDevMode, RectDouble *margin);
+
+
+/************************************************************************
+ * DocumentProperties native support
+ */
+
+/* Values must match those defined in WPrinterJob.java */
+static const DWORD SET_COLOR = 0x00000200;
+static const DWORD SET_ORIENTATION = 0x00004000;
+static const DWORD SET_COLLATED = 0x00008000;
+static const DWORD SET_DUP_VERTICAL = 0x00000010;
+static const DWORD SET_DUP_HORIZONTAL = 0x00000020;
+static const DWORD SET_RES_HIGH = 0x00000040;
+static const DWORD SET_RES_LOW = 0x00000080;
+
+/*
+ * Copy DEVMODE state back into JobAttributes.
+ */
+
+static void UpdateJobAttributes(JNIEnv *env,
+ jobject wJob,
+ jobject attrSet,
+ DEVMODE *devmode) {
+
+ DWORD dmValues = 0;
+ int xRes = 0, yRes = 0;
+
+ if (devmode->dmFields & DM_COLOR) {
+ if (devmode->dmColor == DMCOLOR_COLOR) {
+ dmValues |= SET_COLOR;
+ }
+ }
+
+ if (devmode->dmFields & DM_ORIENTATION) {
+ if (devmode->dmOrientation == DMORIENT_LANDSCAPE) {
+ dmValues |= SET_ORIENTATION;
+ }
+ }
+
+ if (devmode->dmFields & DM_COLLATE &&
+ devmode->dmCollate == DMCOLLATE_TRUE) {
+ dmValues |= SET_COLLATED;
+ }
+
+ if (devmode->dmFields & DM_PRINTQUALITY) {
+ /* value < 0 indicates quality setting.
+ * value > 0 indicates X resolution. In that case
+ * hopefully we will also find y-resolution specified.
+ * If its not, assume its the same as x-res.
+ * Maybe Java code should try to reconcile this against
+ * the printers claimed set of supported resolutions.
+ */
+ if (devmode->dmPrintQuality < 0) {
+ if (devmode->dmPrintQuality == DMRES_HIGH) {
+ dmValues |= SET_RES_HIGH;
+ } else if ((devmode->dmPrintQuality == DMRES_LOW) ||
+ (devmode->dmPrintQuality == DMRES_DRAFT)) {
+ dmValues |= SET_RES_LOW;
+ }
+ /* else if (devmode->dmPrintQuality == DMRES_MEDIUM)
+ * will set to NORMAL.
+ */
+ } else {
+ xRes = devmode->dmPrintQuality;
+ yRes = (devmode->dmFields & DM_YRESOLUTION) ?
+ devmode->dmYResolution : devmode->dmPrintQuality;
+ }
+ }
+
+ if (devmode->dmFields & DM_DUPLEX) {
+ if (devmode->dmDuplex == DMDUP_HORIZONTAL) {
+ dmValues |= SET_DUP_HORIZONTAL;
+ } else if (devmode->dmDuplex == DMDUP_VERTICAL) {
+ dmValues |= SET_DUP_VERTICAL;
+ }
+ }
+
+ env->CallVoidMethod(wJob, AwtPrintControl::setJobAttributesID, attrSet,
+ devmode->dmFields, dmValues, devmode->dmCopies,
+ devmode->dmPaperSize, devmode->dmPaperWidth,
+ devmode->dmPaperLength, devmode->dmDefaultSource,
+ xRes, yRes);
+
+}
+
+JNIEXPORT jboolean JNICALL
+Java_sun_awt_windows_WPrinterJob_showDocProperties(JNIEnv *env,
+ jobject wJob,
+ jlong hWndParent,
+ jobject attrSet,
+ jint dmFields,
+ jshort copies,
+ jshort collate,
+ jshort color,
+ jshort duplex,
+ jshort orient,
+ jshort paper,
+ jshort bin,
+ jshort xres_quality,
+ jshort yres)
+{
+ TRY;
+
+ HGLOBAL hDevMode = AwtPrintControl::getPrintHDMode(env, wJob);
+ HGLOBAL hDevNames = AwtPrintControl::getPrintHDName(env, wJob);
+ DEVMODE *devmode = NULL;
+ DEVNAMES *devnames = NULL;
+ LONG rval = IDCANCEL;
+ jboolean ret = JNI_FALSE;
+
+ if (hDevMode != NULL && hDevNames != NULL) {
+ devmode = (DEVMODE *)::GlobalLock(hDevMode);
+ devnames = (DEVNAMES *)::GlobalLock(hDevNames);
+
+ LPTSTR lpdevnames = (LPTSTR)devnames;
+ // No need to call _tcsdup as we won't unlock until we are done.
+ LPTSTR printerName = lpdevnames+devnames->wDeviceOffset;
+ LPTSTR portName = lpdevnames+devnames->wOutputOffset;
+
+ HANDLE hPrinter;
+ if (::OpenPrinter(printerName, &hPrinter, NULL) == TRUE) {
+ devmode->dmFields |= dmFields;
+ devmode->dmCopies = copies;
+ devmode->dmCollate = collate;
+ devmode->dmColor = color;
+ devmode->dmDuplex = duplex;
+ devmode->dmOrientation = orient;
+ devmode->dmPrintQuality = xres_quality;
+ devmode->dmYResolution = yres;
+ devmode->dmPaperSize = paper;
+ devmode->dmDefaultSource = bin;
+
+ rval = ::DocumentProperties((HWND)hWndParent,
+ hPrinter, printerName, devmode, devmode,
+ DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
+ if (rval == IDOK) {
+ UpdateJobAttributes(env, wJob, attrSet, devmode);
+ ret = JNI_TRUE;
+ }
+ VERIFY(::ClosePrinter(hPrinter));
+ }
+ ::GlobalUnlock(hDevNames);
+ ::GlobalUnlock(hDevMode);
+ }
+
+ return ret;
+
+ CATCH_BAD_ALLOC_RET(0);
+}
+
/************************************************************************
* WPageDialog native methods
*/
@@ -732,7 +882,6 @@
memset(&pd, 0, sizeof(PRINTDLG));
pd.lStructSize = sizeof(PRINTDLG);
pd.Flags = PD_RETURNDEFAULT | PD_RETURNDC;
-
if (::PrintDlg(&pd)) {
printDC = pd.hDC;
hDevMode = pd.hDevMode;
@@ -792,8 +941,19 @@
jint imgPixelWid = GetDeviceCaps(printDC, HORZRES);
jint imgPixelHgt = GetDeviceCaps(printDC, VERTRES);
+ // The DC may be obtained when we first selected the printer as a
+ // result of a call to setNativePrintService.
+ // If the Devmode was obtained later on from the DocumentProperties dialog
+ // the DC won't have been updated and its settings may be for PORTRAIT.
+ // This may happen in other cases too, but was observed for the above.
+ // To get a DC compatible with this devmode we should really call
+ // CreateDC() again to get a DC for the devmode we are using.
+ // The changes for that are a lot more risk, so to minimise that
+ // risk, assume its not LANDSCAPE unless width > height, even if the
+ // devmode says its LANDSCAPE.
// if the values were obtained from a rotated device, swap.
- if (getOrientationFromDevMode2(hDevMode) == DMORIENT_LANDSCAPE) {
+ if ((getOrientationFromDevMode2(hDevMode) == DMORIENT_LANDSCAPE) &&
+ (imgPixelWid > imgPixelHgt)) {
jint tmp;
tmp = xPixelRes;
xPixelRes = yPixelRes;
@@ -941,6 +1101,9 @@
setBooleanField(env, self, DRIVER_COLLATE_STR, JNI_FALSE);
}
+ if (dmFields & DM_COPIES) {
+ setBooleanField(env, self, DRIVER_COPIES_STR, JNI_TRUE);
+ }
}
CATCH_BAD_ALLOC;