diff --git a/jdk/src/share/classes/sun/print/DocumentPropertiesUI.java b/jdk/src/share/classes/sun/print/DocumentPropertiesUI.java new file mode 100644 index 00000000000..9938e8b3951 --- /dev/null +++ b/jdk/src/share/classes/sun/print/DocumentPropertiesUI.java @@ -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); + +} diff --git a/jdk/src/share/classes/sun/print/PrinterJobWrapper.java b/jdk/src/share/classes/sun/print/PrinterJobWrapper.java new file mode 100644 index 00000000000..343da0baa77 --- /dev/null +++ b/jdk/src/share/classes/sun/print/PrinterJobWrapper.java @@ -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(); + } +} diff --git a/jdk/src/share/classes/sun/print/RasterPrinterJob.java b/jdk/src/share/classes/sun/print/RasterPrinterJob.java index 1752016288e..37865e3246c 100644 --- a/jdk/src/share/classes/sun/print/RasterPrinterJob.java +++ b/jdk/src/share/classes/sun/print/RasterPrinterJob.java @@ -903,6 +903,9 @@ public abstract class RasterPrinterJob extends PrinterJob { 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 @@ public abstract class RasterPrinterJob extends PrinterJob { DocFlavor.SERVICE_FORMATTED.PAGEABLE, attributes); } + attributes.remove(PrinterJobWrapper.class); if (newService == null) { return false; diff --git a/jdk/src/share/classes/sun/print/ServiceDialog.java b/jdk/src/share/classes/sun/print/ServiceDialog.java index 82703406aa9..bdfd5ba1242 100644 --- a/jdk/src/share/classes/sun/print/ServiceDialog.java +++ b/jdk/src/share/classes/sun/print/ServiceDialog.java @@ -46,6 +46,7 @@ import java.awt.event.ItemEvent; 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 @@ public class ServiceDialog extends JDialog implements ActionListener { private AppearancePanel pnlAppearance; private boolean isAWT = false; - - static { initResource(); } @@ -801,9 +800,32 @@ public class ServiceDialog extends JDialog implements ActionListener { 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(); + } + } } } } diff --git a/jdk/src/windows/classes/sun/awt/windows/WPrinterJob.java b/jdk/src/windows/classes/sun/awt/windows/WPrinterJob.java index 897e8f1baf1..519a0be422e 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WPrinterJob.java +++ b/jdk/src/windows/classes/sun/awt/windows/WPrinterJob.java @@ -179,6 +179,7 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget { 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 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget { 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 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget { } 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 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget { myService = PrintServiceLookup.lookupDefaultPrintService(); if (myService != null) { try { - setNativePrintService(myService.getName()); + setNativePrintServiceIfNeeded(myService.getName()); } catch (Exception e) { myService = null; } @@ -1754,8 +1788,13 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget { 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 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget { } 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 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget { // 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 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget { } } + 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 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget { } //** END Functions called by native code for querying/updating attributes - } + } class PrintToFileErrorDialog extends Dialog implements ActionListener{ public PrintToFileErrorDialog(Frame parent, String title, String message, diff --git a/jdk/src/windows/classes/sun/print/Win32MediaTray.java b/jdk/src/windows/classes/sun/print/Win32MediaTray.java index ecafcef5668..2f2cafce035 100644 --- a/jdk/src/windows/classes/sun/print/Win32MediaTray.java +++ b/jdk/src/windows/classes/sun/print/Win32MediaTray.java @@ -70,6 +70,10 @@ public class Win32MediaTray extends MediaTray { winEnumTable.add(this); } + public int getDMBinID() { + return winID; + } + private static final String[] myStringTable ={ "Manual-Envelope", "Automatic-Feeder", diff --git a/jdk/src/windows/classes/sun/print/Win32PrintService.java b/jdk/src/windows/classes/sun/print/Win32PrintService.java index c42de1ae7df..73e89269285 100644 --- a/jdk/src/windows/classes/sun/print/Win32PrintService.java +++ b/jdk/src/windows/classes/sun/print/Win32PrintService.java @@ -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.AttributeSet; 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.PrintQuality; 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 @@ public class Win32PrintService implements PrintService, AttributeUpdater, 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= 1 && dmBin <= dmPaperBinToPrintService.length) { return dmPaperBinToPrintService[dmBin-1]; @@ -673,7 +693,6 @@ public class Win32PrintService implements PrintService, AttributeUpdater, return arr2; } - private PrinterIsAcceptingJobs getPrinterIsAcceptingJobs() { if (getJobStatus(printer, 2) != 1) { return PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS; @@ -1596,8 +1615,76 @@ public class Win32PrintService implements PrintService, AttributeUpdater, } } - 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() { diff --git a/jdk/src/windows/native/sun/windows/awt_PrintControl.cpp b/jdk/src/windows/native/sun/windows/awt_PrintControl.cpp index 71a08d3df33..07dd90fcf2c 100644 --- a/jdk/src/windows/native/sun/windows/awt_PrintControl.cpp +++ b/jdk/src/windows/native/sun/windows/awt_PrintControl.cpp @@ -81,6 +81,7 @@ jmethodID AwtPrintControl::setToPageID; jmethodID AwtPrintControl::setNativeAttID; jmethodID AwtPrintControl::setRangeCopiesID; jmethodID AwtPrintControl::setResID; +jmethodID AwtPrintControl::setJobAttributesID; BOOL AwtPrintControl::IsSupportedLevel(HANDLE hPrinter, DWORD dwLevel) { @@ -297,6 +298,10 @@ void AwtPrintControl::initIDs(JNIEnv *env, jclass cls) 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 @@ void AwtPrintControl::initIDs(JNIEnv *env, jclass cls) DASSERT(AwtPrintControl::getSidesID != NULL); DASSERT(AwtPrintControl::getSelectID != NULL); DASSERT(AwtPrintControl::getPrintToFileEnabledID != NULL); + DASSERT(AwtPrintControl::setJobAttributesID != NULL); CATCH_BAD_ALLOC; diff --git a/jdk/src/windows/native/sun/windows/awt_PrintControl.h b/jdk/src/windows/native/sun/windows/awt_PrintControl.h index 2e3fbaf2e60..e8b7415f305 100644 --- a/jdk/src/windows/native/sun/windows/awt_PrintControl.h +++ b/jdk/src/windows/native/sun/windows/awt_PrintControl.h @@ -47,7 +47,6 @@ public: static jmethodID setDevmodeID; static jmethodID getDevnamesID; static jmethodID setDevnamesID; - static jmethodID getWin32MediaID; static jmethodID setWin32MediaID; static jmethodID getWin32MediaTrayID; @@ -73,6 +72,7 @@ public: 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, diff --git a/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp b/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp index a2deb14b58c..c19e4306114 100644 --- a/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp +++ b/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp @@ -329,6 +329,156 @@ static int CALLBACK fontEnumProcA(ENUMLOGFONTEXA *logfont, 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 @@ Java_sun_awt_windows_WPrinterJob_validatePaper(JNIEnv *env, jobject self, 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 @@ Java_sun_awt_windows_WPrinterJob_validatePaper(JNIEnv *env, jobject self, 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 @@ Java_sun_awt_windows_WPrinterJob_initPrinter(JNIEnv *env, jobject self) { setBooleanField(env, self, DRIVER_COLLATE_STR, JNI_FALSE); } + if (dmFields & DM_COPIES) { + setBooleanField(env, self, DRIVER_COPIES_STR, JNI_TRUE); + } } CATCH_BAD_ALLOC;