8314070: javax.print: Support IPP output-bin attribute extension
Reviewed-by: psadhukhan, prr
This commit is contained in:
parent
d230b30353
commit
c7d2a5c1c4
@ -44,6 +44,7 @@ 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.OutputBin;
|
||||
import javax.print.attribute.standard.PageRanges;
|
||||
import javax.print.attribute.standard.Sides;
|
||||
import javax.print.attribute.Attribute;
|
||||
@ -70,6 +71,8 @@ public final class CPrinterJob extends RasterPrinterJob {
|
||||
|
||||
private String tray = null;
|
||||
|
||||
private String outputBin = null;
|
||||
|
||||
// This is the NSPrintInfo for this PrinterJob. Protect multi thread
|
||||
// access to it. It is used by the pageDialog, jobDialog, and printLoop.
|
||||
// This way the state of these items is shared across these calls.
|
||||
@ -191,6 +194,8 @@ public final class CPrinterJob extends RasterPrinterJob {
|
||||
tray = customTray.getChoiceName();
|
||||
}
|
||||
|
||||
outputBin = getOutputBinValue(attributes.get(OutputBin.class));
|
||||
|
||||
PageRanges pageRangesAttr = (PageRanges)attributes.get(PageRanges.class);
|
||||
if (isSupportedValue(pageRangesAttr, attributes)) {
|
||||
SunPageSelection rangeSelect = (SunPageSelection)attributes.get(SunPageSelection.class);
|
||||
@ -658,6 +663,41 @@ public final class CPrinterJob extends RasterPrinterJob {
|
||||
return tray;
|
||||
}
|
||||
|
||||
private String getOutputBin() {
|
||||
return outputBin;
|
||||
}
|
||||
|
||||
private void setOutputBin(String outputBinName) {
|
||||
|
||||
OutputBin outputBin = toOutputBin(outputBinName);
|
||||
if (outputBin != null) {
|
||||
attributes.add(outputBin);
|
||||
}
|
||||
}
|
||||
|
||||
private OutputBin toOutputBin(String outputBinName) {
|
||||
|
||||
PrintService ps = getPrintService();
|
||||
if (ps == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
OutputBin[] supportedBins = (OutputBin[]) ps.getSupportedAttributeValues(OutputBin.class, null, null);
|
||||
if (supportedBins == null || supportedBins.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (OutputBin bin : supportedBins) {
|
||||
if (bin instanceof CustomOutputBin customBin){
|
||||
if (customBin.getChoiceName().equals(outputBinName)) {
|
||||
return customBin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void setPrinterServiceFromNative(String printerName) {
|
||||
// This is called from the native side.
|
||||
PrintService[] services = PrintServiceLookup.lookupPrintServices(DocFlavor.SERVICE_FORMATTED.PAGEABLE, null);
|
||||
|
@ -383,6 +383,7 @@ static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject d
|
||||
DECLARE_METHOD(jm_setPrintToFile, sjc_CPrinterJob, "setPrintToFile", "(Z)V");
|
||||
DECLARE_METHOD(jm_setDestinationFile, sjc_CPrinterJob, "setDestinationFile", "(Ljava/lang/String;)V");
|
||||
DECLARE_METHOD(jm_setSides, sjc_CPrinterJob, "setSides", "(I)V");
|
||||
DECLARE_METHOD(jm_setOutputBin, sjc_CPrinterJob, "setOutputBin", "(Ljava/lang/String;)V");
|
||||
|
||||
// get the selected printer's name, and set the appropriate PrintService on the Java side
|
||||
NSString *name = [[src printer] name];
|
||||
@ -449,6 +450,13 @@ static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject d
|
||||
(*env)->CallVoidMethod(env, dstPrinterJob, jm_setSides, sides); // AWT_THREADING Safe (known object)
|
||||
CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
NSString* outputBin = [[src printSettings] objectForKey:@"OutputBin"];
|
||||
if (outputBin != nil) {
|
||||
jstring outputBinName = NSStringToJavaString(env, outputBin);
|
||||
(*env)->CallVoidMethod(env, dstPrinterJob, jm_setOutputBin, outputBinName);
|
||||
CHECK_EXCEPTION();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -468,6 +476,7 @@ static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobj
|
||||
DECLARE_METHOD(jm_getPageFormat, sjc_CPrinterJob, "getPageFormatFromAttributes", "()Ljava/awt/print/PageFormat;");
|
||||
DECLARE_METHOD(jm_getDestinationFile, sjc_CPrinterJob, "getDestinationFile", "()Ljava/lang/String;");
|
||||
DECLARE_METHOD(jm_getSides, sjc_CPrinterJob, "getSides", "()I");
|
||||
DECLARE_METHOD(jm_getOutputBin, sjc_CPrinterJob, "getOutputBin", "()Ljava/lang/String;");
|
||||
|
||||
|
||||
NSMutableDictionary* printingDictionary = [dst dictionary];
|
||||
@ -538,6 +547,15 @@ static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobj
|
||||
[dst updateFromPMPrintSettings];
|
||||
}
|
||||
}
|
||||
|
||||
jobject outputBin = (*env)->CallObjectMethod(env, srcPrinterJob, jm_getOutputBin);
|
||||
CHECK_EXCEPTION();
|
||||
if (outputBin != NULL) {
|
||||
NSString *nsOutputBinStr = JavaStringToNSString(env, outputBin);
|
||||
if (nsOutputBinStr != nil) {
|
||||
[[dst printSettings] setObject:nsOutputBinStr forKey:@"OutputBin"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, BELLSOFT. 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 javax.print.attribute.standard;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
import javax.print.attribute.Attribute;
|
||||
import javax.print.attribute.DocAttribute;
|
||||
import javax.print.attribute.EnumSyntax;
|
||||
import javax.print.attribute.PrintJobAttribute;
|
||||
import javax.print.attribute.PrintRequestAttribute;
|
||||
|
||||
import sun.print.CustomOutputBin;
|
||||
|
||||
/**
|
||||
* Class {@code OutputBin} is a printing attribute class, an enumeration, that
|
||||
* specifies the output bin for the job.
|
||||
* <p>
|
||||
* Class {@code OutputBin} declares keywords for standard output bin kind values.
|
||||
* <p>
|
||||
* <b>IPP Compatibility:</b> This attribute is not an IPP 1.1 attribute; it is
|
||||
* an attribute in the "output-bin" attribute extension
|
||||
* (<a href="https://ftp.pwg.org/pub/pwg/candidates/cs-ippoutputbin10-20010207-5100.2.pdf">
|
||||
* PDF</a>) of IPP 1.1. The category name returned by {@code getName()} is the
|
||||
* IPP attribute name. The enumeration's integer value is the IPP enum value.
|
||||
* The {@code toString()} method returns the IPP string representation of the
|
||||
* attribute value.
|
||||
*/
|
||||
public sealed class OutputBin extends EnumSyntax implements PrintRequestAttribute, PrintJobAttribute permits CustomOutputBin {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = -3718893309873137109L;
|
||||
|
||||
/**
|
||||
* The top output bin in the printer.
|
||||
*/
|
||||
public static final OutputBin TOP = new OutputBin(0);
|
||||
|
||||
/**
|
||||
* The middle output bin in the printer.
|
||||
*/
|
||||
public static final OutputBin MIDDLE = new OutputBin(1);
|
||||
|
||||
/**
|
||||
* The bottom output bin in the printer.
|
||||
*/
|
||||
public static final OutputBin BOTTOM = new OutputBin(2);
|
||||
|
||||
/**
|
||||
* The side output bin in the printer.
|
||||
*/
|
||||
public static final OutputBin SIDE = new OutputBin(3);
|
||||
|
||||
/**
|
||||
* The left output bin in the printer.
|
||||
*/
|
||||
public static final OutputBin LEFT = new OutputBin(4);
|
||||
|
||||
/**
|
||||
* The right output bin in the printer.
|
||||
*/
|
||||
public static final OutputBin RIGHT = new OutputBin(5);
|
||||
|
||||
/**
|
||||
* The center output bin in the printer.
|
||||
*/
|
||||
public static final OutputBin CENTER = new OutputBin(6);
|
||||
|
||||
/**
|
||||
* The rear output bin in the printer.
|
||||
*/
|
||||
public static final OutputBin REAR = new OutputBin(7);
|
||||
|
||||
/**
|
||||
* The face up output bin in the printer.
|
||||
*/
|
||||
public static final OutputBin FACE_UP = new OutputBin(8);
|
||||
|
||||
/**
|
||||
* The face down output bin in the printer.
|
||||
*/
|
||||
public static final OutputBin FACE_DOWN = new OutputBin(9);
|
||||
|
||||
/**
|
||||
* The large-capacity output bin in the printer.
|
||||
*/
|
||||
public static final OutputBin LARGE_CAPACITY = new OutputBin(10);
|
||||
|
||||
/**
|
||||
* Construct a new output bin enumeration value with the given integer
|
||||
* value.
|
||||
*
|
||||
* @param value Integer value
|
||||
*/
|
||||
protected OutputBin(int value) {
|
||||
super(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* The string table for class {@code OutputBin}.
|
||||
*/
|
||||
private static final String[] myStringTable = {
|
||||
"top",
|
||||
"middle",
|
||||
"bottom",
|
||||
"side",
|
||||
"left",
|
||||
"right",
|
||||
"center",
|
||||
"rear",
|
||||
"face-up",
|
||||
"face-down",
|
||||
"large-capacity",
|
||||
};
|
||||
|
||||
/**
|
||||
* The enumeration value table for class {@code OutputBin}.
|
||||
*/
|
||||
private static final OutputBin[] myEnumValueTable = {
|
||||
TOP,
|
||||
MIDDLE,
|
||||
BOTTOM,
|
||||
SIDE,
|
||||
LEFT,
|
||||
RIGHT,
|
||||
CENTER,
|
||||
REAR,
|
||||
FACE_UP,
|
||||
FACE_DOWN,
|
||||
LARGE_CAPACITY,
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the string table for class {@code OutputBin}.
|
||||
*/
|
||||
@Override
|
||||
protected String[] getStringTable() {
|
||||
return myStringTable.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the enumeration value table for class {@code OutputBin}.
|
||||
*/
|
||||
@Override
|
||||
protected EnumSyntax[] getEnumValueTable() {
|
||||
return (EnumSyntax[]) myEnumValueTable.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the printing attribute class which is to be used as the "category"
|
||||
* for this printing attribute value.
|
||||
* <p>
|
||||
* For class {@code OutputBin} and any vendor-defined subclasses, the category
|
||||
* is class {@code OutputBin} itself.
|
||||
*
|
||||
* @return printing attribute class (category), an instance of class
|
||||
* {@link Class java.lang.Class}
|
||||
*/
|
||||
@Override
|
||||
public final Class<? extends Attribute> getCategory() {
|
||||
return OutputBin.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the category of which this attribute value is an
|
||||
* instance.
|
||||
* <p>
|
||||
* For class {@code OutputBin} and any vendor-defined subclasses, the category
|
||||
* name is {@code "output-bin"}.
|
||||
*
|
||||
* @return attribute category name
|
||||
*/
|
||||
@Override
|
||||
public final String getName() {
|
||||
return "output-bin";
|
||||
}
|
||||
}
|
@ -335,6 +335,13 @@
|
||||
* <td>
|
||||
* <td>
|
||||
* <tr>
|
||||
* <th scope="row"><a href="OutputBin.html">OutputBin</a>
|
||||
* <td>
|
||||
* <td>X
|
||||
* <td>X
|
||||
* <td>
|
||||
* <td>
|
||||
* <tr>
|
||||
* <th scope="row"><a href="DateTimeAtCompleted.html">
|
||||
* DateTimeAtCompleted</a>
|
||||
* <td>
|
||||
|
108
src/java.desktop/share/classes/sun/print/CustomOutputBin.java
Normal file
108
src/java.desktop/share/classes/sun/print/CustomOutputBin.java
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, BELLSOFT. 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.io.Serial;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.print.attribute.EnumSyntax;
|
||||
import javax.print.attribute.standard.Media;
|
||||
import javax.print.attribute.standard.OutputBin;
|
||||
|
||||
public final class CustomOutputBin extends OutputBin {
|
||||
private static ArrayList<String> customStringTable = new ArrayList<>();
|
||||
private static ArrayList<CustomOutputBin> customEnumTable = new ArrayList<>();
|
||||
private String choiceName;
|
||||
|
||||
private CustomOutputBin(int x) {
|
||||
super(x);
|
||||
}
|
||||
|
||||
private static synchronized int nextValue(String name) {
|
||||
customStringTable.add(name);
|
||||
return (customStringTable.size()-1);
|
||||
}
|
||||
|
||||
private CustomOutputBin(String name, String choice) {
|
||||
super(nextValue(name));
|
||||
choiceName = choice;
|
||||
customEnumTable.add(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a custom output bin
|
||||
*/
|
||||
public static synchronized CustomOutputBin createOutputBin(String name, String choice) {
|
||||
for (CustomOutputBin bin : customEnumTable) {
|
||||
if (bin.getChoiceName().equals(choice) && bin.getCustomName().equals(name)) {
|
||||
return bin;
|
||||
}
|
||||
}
|
||||
return new CustomOutputBin(name, choice);
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 3018751086294120717L;
|
||||
|
||||
/**
|
||||
* Returns the command string for this media tray.
|
||||
*/
|
||||
public String getChoiceName() {
|
||||
return choiceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string table for super class MediaTray.
|
||||
*/
|
||||
public OutputBin[] getSuperEnumTable() {
|
||||
return (OutputBin[])super.getEnumValueTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string table for class CustomOutputBin.
|
||||
*/
|
||||
@Override
|
||||
protected String[] getStringTable() {
|
||||
String[] nameTable = new String[customStringTable.size()];
|
||||
return customStringTable.toArray(nameTable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a custom bin name
|
||||
*/
|
||||
public String getCustomName() {
|
||||
return customStringTable.get(getValue() - getOffset());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the enumeration value table for class CustomOutputBin.
|
||||
*/
|
||||
@Override
|
||||
protected CustomOutputBin[] getEnumValueTable() {
|
||||
CustomOutputBin[] enumTable = new CustomOutputBin[customEnumTable.size()];
|
||||
return customEnumTable.toArray(enumTable);
|
||||
}
|
||||
}
|
@ -61,6 +61,7 @@ import javax.print.attribute.standard.Copies;
|
||||
import javax.print.attribute.standard.Destination;
|
||||
import javax.print.attribute.standard.DialogTypeSelection;
|
||||
import javax.print.attribute.standard.JobName;
|
||||
import javax.print.attribute.standard.OutputBin;
|
||||
import javax.print.attribute.standard.Sides;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
@ -491,14 +492,19 @@ public class PSPrinterJob extends RasterPrinterJob {
|
||||
if (attributes == null) {
|
||||
return; // now always use attributes, so this shouldn't happen.
|
||||
}
|
||||
mOptions = "";
|
||||
Attribute attr = attributes.get(Media.class);
|
||||
if (attr instanceof CustomMediaTray) {
|
||||
CustomMediaTray customTray = (CustomMediaTray)attr;
|
||||
String choice = customTray.getChoiceName();
|
||||
if (choice != null) {
|
||||
mOptions = " InputSlot="+ choice;
|
||||
mOptions += " InputSlot="+ choice;
|
||||
}
|
||||
}
|
||||
String outputBin = getOutputBinValue(outputBinAttr);
|
||||
if (outputBin != null) {
|
||||
mOptions += " output-bin=" + outputBin;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1643,7 +1649,9 @@ public class PSPrinterJob extends RasterPrinterJob {
|
||||
execCmd[n++] = "-o job-sheets=standard";
|
||||
}
|
||||
if ((pFlags & OPTIONS) != 0) {
|
||||
execCmd[n++] = "-o" + options;
|
||||
for (String option : options.trim().split(" ")) {
|
||||
execCmd[n++] = "-o " + option;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ncomps+=1; //add 1 arg for lp
|
||||
@ -1666,7 +1674,9 @@ public class PSPrinterJob extends RasterPrinterJob {
|
||||
execCmd[n++] = "-o job-sheets=standard";
|
||||
}
|
||||
if ((pFlags & OPTIONS) != 0) {
|
||||
execCmd[n++] = "-o" + options;
|
||||
for (String option : options.trim().split(" ")) {
|
||||
execCmd[n++] = "-o " + option;
|
||||
}
|
||||
}
|
||||
}
|
||||
execCmd[n++] = spoolFile;
|
||||
|
@ -81,6 +81,7 @@ import javax.print.attribute.standard.MediaPrintableArea;
|
||||
import javax.print.attribute.standard.MediaSize;
|
||||
import javax.print.attribute.standard.MediaSizeName;
|
||||
import javax.print.attribute.standard.OrientationRequested;
|
||||
import javax.print.attribute.standard.OutputBin;
|
||||
import javax.print.attribute.standard.PageRanges;
|
||||
import javax.print.attribute.standard.PrinterResolution;
|
||||
import javax.print.attribute.standard.PrinterState;
|
||||
@ -279,6 +280,7 @@ public abstract class RasterPrinterJob extends PrinterJob {
|
||||
private PageRanges pageRangesAttr;
|
||||
protected PrinterResolution printerResAttr;
|
||||
protected Sides sidesAttr;
|
||||
protected OutputBin outputBinAttr;
|
||||
protected String destinationAttr;
|
||||
protected boolean noJobSheet = false;
|
||||
protected int mDestType = RasterPrinterJob.FILE;
|
||||
@ -1228,6 +1230,7 @@ public abstract class RasterPrinterJob extends PrinterJob {
|
||||
/* reset all values to defaults */
|
||||
setCollated(false);
|
||||
sidesAttr = null;
|
||||
outputBinAttr = null;
|
||||
printerResAttr = null;
|
||||
pageRangesAttr = null;
|
||||
copiesAttr = 0;
|
||||
@ -1274,6 +1277,11 @@ public abstract class RasterPrinterJob extends PrinterJob {
|
||||
sidesAttr = Sides.ONE_SIDED;
|
||||
}
|
||||
|
||||
outputBinAttr = (OutputBin)attributes.get(OutputBin.class);
|
||||
if (!isSupportedValue(outputBinAttr, attributes)) {
|
||||
outputBinAttr = null;
|
||||
}
|
||||
|
||||
printerResAttr = (PrinterResolution)attributes.get(PrinterResolution.class);
|
||||
if (service.isAttributeCategorySupported(PrinterResolution.class)) {
|
||||
if (!isSupportedValue(printerResAttr, attributes)) {
|
||||
@ -2617,4 +2625,26 @@ public abstract class RasterPrinterJob extends PrinterJob {
|
||||
parentWindowID = DialogOwnerAccessor.getID(onTop);
|
||||
}
|
||||
}
|
||||
|
||||
protected String getOutputBinValue(Attribute attr) {
|
||||
if (attr instanceof CustomOutputBin customOutputBin) {
|
||||
return customOutputBin.getChoiceName();
|
||||
} else if (attr instanceof OutputBin) {
|
||||
PrintService ps = getPrintService();
|
||||
if (ps == null) {
|
||||
return null;
|
||||
}
|
||||
String name = attr.toString();
|
||||
OutputBin[] outputBins = (OutputBin[]) ps
|
||||
.getSupportedAttributeValues(OutputBin.class, null, null);
|
||||
for (OutputBin outputBin : outputBins) {
|
||||
String choice = ((CustomOutputBin) outputBin).getChoiceName();
|
||||
if (name.equalsIgnoreCase(choice) || name.replaceAll("-", "").equalsIgnoreCase(choice)) {
|
||||
return choice;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,7 @@ import java.awt.event.KeyEvent;
|
||||
import java.net.URISyntaxException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.MalformedURLException;
|
||||
import sun.awt.OSInfo;
|
||||
|
||||
/**
|
||||
* A class which implements a cross-platform print dialog.
|
||||
@ -2300,6 +2301,7 @@ public class ServiceDialog extends JDialog implements ActionListener {
|
||||
private QualityPanel pnlQuality;
|
||||
private JobAttributesPanel pnlJobAttributes;
|
||||
private SidesPanel pnlSides;
|
||||
private OutputPanel pnlOutput;
|
||||
|
||||
public AppearancePanel() {
|
||||
super();
|
||||
@ -2330,6 +2332,11 @@ public class ServiceDialog extends JDialog implements ActionListener {
|
||||
pnlJobAttributes = new JobAttributesPanel();
|
||||
addToGB(pnlJobAttributes, this, gridbag, c);
|
||||
|
||||
if (OSInfo.getOSType() != OSInfo.OSType.WINDOWS) {
|
||||
c.gridwidth = GridBagConstraints.REMAINDER;
|
||||
pnlOutput = new OutputPanel();
|
||||
addToGB(pnlOutput, this, gridbag, c);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateInfo() {
|
||||
@ -2337,6 +2344,9 @@ public class ServiceDialog extends JDialog implements ActionListener {
|
||||
pnlQuality.updateInfo();
|
||||
pnlSides.updateInfo();
|
||||
pnlJobAttributes.updateInfo();
|
||||
if (pnlOutput != null) {
|
||||
pnlOutput.updateInfo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2818,8 +2828,106 @@ public class ServiceDialog extends JDialog implements ActionListener {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial") // Superclass is not serializable across versions
|
||||
private class OutputPanel extends JPanel implements ItemListener {
|
||||
|
||||
private final String strTitle = getMsg("border.output");
|
||||
private JLabel lblOutput;
|
||||
private JComboBox<Object> cbOutput;
|
||||
private Vector<OutputBin> outputs = new Vector<>();
|
||||
|
||||
public OutputPanel() {
|
||||
super();
|
||||
|
||||
GridBagLayout gridbag = new GridBagLayout();
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
|
||||
setLayout(gridbag);
|
||||
setBorder(BorderFactory.createTitledBorder(strTitle));
|
||||
|
||||
cbOutput = new JComboBox<>();
|
||||
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
c.insets = compInsets;
|
||||
c.weighty = 1.0;
|
||||
|
||||
c.weightx = 0.0;
|
||||
lblOutput = new JLabel(getMsg("label.outputbins"), JLabel.TRAILING);
|
||||
lblOutput.setDisplayedMnemonic(getMnemonic("label.outputbins"));
|
||||
lblOutput.setLabelFor(cbOutput);
|
||||
addToGB(lblOutput, this, gridbag, c);
|
||||
c.weightx = 1.0;
|
||||
c.gridwidth = GridBagConstraints.REMAINDER;
|
||||
addToGB(cbOutput, this, gridbag, c);
|
||||
}
|
||||
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
|
||||
Object source = e.getSource();
|
||||
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||
if (source == cbOutput) {
|
||||
int index = cbOutput.getSelectedIndex();
|
||||
if ((index >= 0) && (index < outputs.size())) {
|
||||
asCurrent.add(outputs.get(index));
|
||||
} else if (index == cbOutput.getItemCount() - 1) {
|
||||
asCurrent.remove(OutputBin.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateInfo() {
|
||||
|
||||
Class<OutputBin> obCategory = OutputBin.class;
|
||||
|
||||
cbOutput.removeItemListener(this);
|
||||
cbOutput.removeAllItems();
|
||||
|
||||
outputs.clear();
|
||||
|
||||
boolean outputEnabled = false;
|
||||
|
||||
if (psCurrent.isAttributeCategorySupported(obCategory)) {
|
||||
|
||||
Object values =
|
||||
psCurrent.getSupportedAttributeValues(obCategory,
|
||||
docFlavor,
|
||||
asCurrent);
|
||||
|
||||
if (values instanceof OutputBin[]) {
|
||||
OutputBin[] outputBins = (OutputBin[])values;
|
||||
|
||||
for (OutputBin outputBin: outputBins) {
|
||||
outputs.add(outputBin);
|
||||
cbOutput.addItem(outputBin.toString());
|
||||
}
|
||||
|
||||
cbOutput.addItem("");
|
||||
cbOutput.setSelectedIndex(cbOutput.getItemCount() - 1);
|
||||
|
||||
OutputBin current = (OutputBin) asCurrent.get(obCategory);
|
||||
if (current != null) {
|
||||
for (int i = 0; i < outputs.size(); i++) {
|
||||
if (current.equals(outputs.get(i))) {
|
||||
cbOutput.setSelectedIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (outputBins.length == 1) {
|
||||
cbOutput.setSelectedIndex(0);
|
||||
}
|
||||
|
||||
outputEnabled = outputBins.length > 1;
|
||||
}
|
||||
}
|
||||
|
||||
cbOutput.setEnabled(outputEnabled);
|
||||
lblOutput.setEnabled(outputEnabled);
|
||||
if (outputEnabled) {
|
||||
cbOutput.addItemListener(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A special widget that groups a JRadioButton with an associated icon,
|
||||
|
@ -29,6 +29,7 @@ border.chromaticity=Color Appearance
|
||||
border.copies=Copies
|
||||
border.jobattributes=Job Attributes
|
||||
border.media=Media
|
||||
border.output=Output
|
||||
border.orientation=Orientation
|
||||
border.printrange=Print Range
|
||||
border.printservice=Print Service
|
||||
@ -62,6 +63,7 @@ label.pstype=Type:
|
||||
label.rangeto=To
|
||||
label.size=Si&ze:
|
||||
label.source=Sour&ce:
|
||||
label.outputbins=Out&put trays:
|
||||
label.status=Status:
|
||||
label.username=&User Name:
|
||||
label.millimetres=(mm)
|
||||
|
@ -29,6 +29,7 @@ border.chromaticity=Farbdarstellung
|
||||
border.copies=Kopien
|
||||
border.jobattributes=Jobattribute
|
||||
border.media=Medien
|
||||
border.output=Ausgabe
|
||||
border.orientation=Ausrichtung
|
||||
border.printrange=Druckbereich
|
||||
border.printservice=Druckservice
|
||||
@ -62,6 +63,7 @@ label.pstype=Typ:
|
||||
label.rangeto=Bis
|
||||
label.size=G&röße:
|
||||
label.source=&Quelle:
|
||||
label.outputbins=A&usgabefächer:
|
||||
label.status=Status:
|
||||
label.username=&Benutzername:
|
||||
label.millimetres=(mm)
|
||||
|
@ -29,6 +29,7 @@ border.chromaticity=Apariencia del Color
|
||||
border.copies=Copias
|
||||
border.jobattributes=Atributos del Trabajo
|
||||
border.media=Soporte
|
||||
border.output=Salida
|
||||
border.orientation=Orientación
|
||||
border.printrange=Rango de Impresión
|
||||
border.printservice=Servicio de Impresión
|
||||
@ -62,6 +63,7 @@ label.pstype=Tipo:
|
||||
label.rangeto=A
|
||||
label.size=Tama&ño:
|
||||
label.source=Orig&en:
|
||||
label.outputbins=Band&ejas de salida:
|
||||
label.status=Estado:
|
||||
label.username=&Usuario:
|
||||
label.millimetres=(mm)
|
||||
|
@ -29,6 +29,7 @@ border.chromaticity=Couleur
|
||||
border.copies=Copies
|
||||
border.jobattributes=Attributs de tâche
|
||||
border.media=Support
|
||||
border.output=Sortir
|
||||
border.orientation=Orientation
|
||||
border.printrange=Plage d'impression
|
||||
border.printservice=Service d'impression
|
||||
@ -62,6 +63,7 @@ label.pstype=Type :
|
||||
label.rangeto=A
|
||||
label.size=Tai&lle :
|
||||
label.source=Sour&ce :
|
||||
label.outputbins=Bacs de s&ortie :
|
||||
label.status=Statut :
|
||||
label.username=Nom ut&ilisateur :
|
||||
label.millimetres=(mm)
|
||||
|
@ -29,6 +29,7 @@ border.chromaticity=Aspetto colore
|
||||
border.copies=Copie
|
||||
border.jobattributes=Attributi job
|
||||
border.media=Supporti
|
||||
border.output=Output
|
||||
border.orientation=Orientamento
|
||||
border.printrange=Intervallo di stampa
|
||||
border.printservice=Servizio di stampa
|
||||
@ -62,6 +63,7 @@ label.pstype=Tipo:
|
||||
label.rangeto=A
|
||||
label.size=Di&mensioni:
|
||||
label.source=O&rigine:
|
||||
label.outputbins=&Vassoi di uscita:
|
||||
label.status=Stato:
|
||||
label.username=Nome &utente:
|
||||
label.millimetres=(mm)
|
||||
|
@ -29,6 +29,7 @@ border.chromaticity=色の表現
|
||||
border.copies=印刷部数
|
||||
border.jobattributes=ジョブの属性
|
||||
border.media=メディア
|
||||
border.output=出力
|
||||
border.orientation=用紙の向き
|
||||
border.printrange=印刷範囲
|
||||
border.printservice=印刷サービス
|
||||
@ -62,6 +63,7 @@ label.pstype=タイプ:
|
||||
label.rangeto=印刷範囲
|
||||
label.size=サイズ(&Z):
|
||||
label.source=ソース(&C):
|
||||
label.outputbins=出力トレイ(&P):
|
||||
label.status=状態:
|
||||
label.username=ユーザー名(&U):
|
||||
label.millimetres=(mm)
|
||||
|
@ -29,6 +29,7 @@ border.chromaticity=색상 모양
|
||||
border.copies=복사
|
||||
border.jobattributes=작업 속성
|
||||
border.media=매체
|
||||
border.output=출력물
|
||||
border.orientation=방향
|
||||
border.printrange=인쇄 범위
|
||||
border.printservice=인쇄 서비스
|
||||
@ -62,6 +63,7 @@ label.pstype=유형:
|
||||
label.rangeto=종료
|
||||
label.size=크기(&Z):
|
||||
label.source=소스(&C):
|
||||
label.outputbins=출력 트레이(&P):
|
||||
label.status=상태:
|
||||
label.username=사용자 이름(&U):
|
||||
label.millimetres=(mm)
|
||||
|
@ -29,6 +29,7 @@ border.chromaticity=Aparência da Cor
|
||||
border.copies=Cópias
|
||||
border.jobattributes=Atributos do Job
|
||||
border.media=Mídia
|
||||
border.output=Saída
|
||||
border.orientation=Orientação
|
||||
border.printrange=Faixa de Impressão
|
||||
border.printservice=Serviço de Impressão
|
||||
@ -62,6 +63,7 @@ label.pstype=Tipo:
|
||||
label.rangeto=Até
|
||||
label.size=Ta&manho:
|
||||
label.source=&Origem:
|
||||
label.outputbins=Bande&jas de saída:
|
||||
label.status=Status:
|
||||
label.username=Nome do &Usuário:
|
||||
label.millimetres=(mm)
|
||||
|
@ -29,6 +29,7 @@ border.chromaticity=Färg
|
||||
border.copies=Antal exemplar
|
||||
border.jobattributes=Utskriftsattribut
|
||||
border.media=Media
|
||||
border.output=Utmatning
|
||||
border.orientation=Orientering
|
||||
border.printrange=Utskriftsintervall
|
||||
border.printservice=Utskriftstjänst
|
||||
@ -62,6 +63,7 @@ label.pstype=Typ:
|
||||
label.rangeto=Till
|
||||
label.size=Stor&lek:
|
||||
label.source=&Källa:
|
||||
label.outputbins=Utma&tningsfack:
|
||||
label.status=Status:
|
||||
label.username=A&nvändarnamn:
|
||||
label.millimetres=(mm)
|
||||
|
@ -29,6 +29,7 @@ border.chromaticity=颜色外观
|
||||
border.copies=份数
|
||||
border.jobattributes=作业属性
|
||||
border.media=介质
|
||||
border.output=出纸
|
||||
border.orientation=方向
|
||||
border.printrange=打印区域
|
||||
border.printservice=打印服务
|
||||
@ -62,6 +63,7 @@ label.pstype=类型:
|
||||
label.rangeto=至
|
||||
label.size=大小(&Z):
|
||||
label.source=来源(&C):
|
||||
label.outputbins=出纸托盘(&P):
|
||||
label.status=状态:
|
||||
label.username=用户名(&U):
|
||||
label.millimetres=(毫米)
|
||||
|
@ -29,6 +29,7 @@ border.chromaticity=色彩外觀
|
||||
border.copies=份數
|
||||
border.jobattributes=工作屬性
|
||||
border.media=媒體
|
||||
border.output=出紙
|
||||
border.orientation=方向
|
||||
border.printrange=列印範圍
|
||||
border.printservice=列印服務
|
||||
@ -62,6 +63,7 @@ label.pstype=類型:
|
||||
label.rangeto=至
|
||||
label.size=大小(&Z):
|
||||
label.source=來源(&C):
|
||||
label.outputbins=输出纸盒(&P):
|
||||
label.status=狀態:
|
||||
label.username=使用者名稱(&U):
|
||||
label.millimetres=(mm)
|
||||
|
@ -34,11 +34,13 @@ import java.util.HashMap;
|
||||
import sun.print.IPPPrintService;
|
||||
import sun.print.CustomMediaSizeName;
|
||||
import sun.print.CustomMediaTray;
|
||||
import sun.print.CustomOutputBin;
|
||||
import javax.print.attribute.standard.Media;
|
||||
import javax.print.attribute.standard.MediaSizeName;
|
||||
import javax.print.attribute.standard.MediaSize;
|
||||
import javax.print.attribute.standard.MediaTray;
|
||||
import javax.print.attribute.standard.MediaPrintableArea;
|
||||
import javax.print.attribute.standard.OutputBin;
|
||||
import javax.print.attribute.standard.PrinterResolution;
|
||||
import javax.print.attribute.Size2DSyntax;
|
||||
import javax.print.attribute.Attribute;
|
||||
@ -60,6 +62,7 @@ public class CUPSPrinter {
|
||||
// CUPS does not support multi-threading.
|
||||
private static synchronized native String[] getMedia(String printer);
|
||||
private static synchronized native float[] getPageSizes(String printer);
|
||||
private static synchronized native String[] getOutputBins(String printer);
|
||||
private static synchronized native void
|
||||
getResolutions(String printer, ArrayList<Integer> resolutionList);
|
||||
//public static boolean useIPPMedia = false; will be used later
|
||||
@ -68,10 +71,12 @@ public class CUPSPrinter {
|
||||
private MediaSizeName[] cupsMediaSNames;
|
||||
private CustomMediaSizeName[] cupsCustomMediaSNames;
|
||||
private MediaTray[] cupsMediaTrays;
|
||||
private OutputBin[] cupsOutputBins;
|
||||
|
||||
public int nPageSizes = 0;
|
||||
public int nTrays = 0;
|
||||
private String[] media;
|
||||
private String[] outputBins;
|
||||
private float[] pageSizes;
|
||||
int[] resolutionsArray;
|
||||
private String printer;
|
||||
@ -144,6 +149,8 @@ public class CUPSPrinter {
|
||||
for (int i=0; i < resolutionList.size(); i++) {
|
||||
resolutionsArray[i] = resolutionList.get(i);
|
||||
}
|
||||
|
||||
outputBins = getOutputBins(printer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -185,6 +192,14 @@ public class CUPSPrinter {
|
||||
return cupsMediaTrays;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array of OutputBins derived from PPD.
|
||||
*/
|
||||
OutputBin[] getOutputBins() {
|
||||
initMedia();
|
||||
return cupsOutputBins;
|
||||
}
|
||||
|
||||
/**
|
||||
* return the raw packed array of supported printer resolutions.
|
||||
*/
|
||||
@ -261,6 +276,15 @@ public class CUPSPrinter {
|
||||
cupsMediaTrays[i] = mt;
|
||||
}
|
||||
|
||||
if (outputBins == null) {
|
||||
cupsOutputBins = new OutputBin[0];
|
||||
} else {
|
||||
int nBins = outputBins.length / 2;
|
||||
cupsOutputBins = new OutputBin[nBins];
|
||||
for (int i = 0; i < nBins; i++) {
|
||||
cupsOutputBins[i] = CustomOutputBin.createOutputBin(outputBins[i*2], outputBins[i*2+1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -80,6 +80,7 @@ import javax.print.attribute.standard.MediaSizeName;
|
||||
import javax.print.attribute.standard.MediaTray;
|
||||
import javax.print.attribute.standard.NumberUp;
|
||||
import javax.print.attribute.standard.OrientationRequested;
|
||||
import javax.print.attribute.standard.OutputBin;
|
||||
import javax.print.attribute.standard.PDLOverrideSupported;
|
||||
import javax.print.attribute.standard.PageRanges;
|
||||
import javax.print.attribute.standard.PagesPerMinute;
|
||||
@ -138,6 +139,7 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
|
||||
private DocFlavor[] supportedDocFlavors;
|
||||
private Class<?>[] supportedCats;
|
||||
private MediaTray[] mediaTrays;
|
||||
private OutputBin[] outputBins;
|
||||
private MediaSizeName[] mediaSizeNames;
|
||||
private CustomMediaSizeName[] customMediaSizeNames;
|
||||
private int defaultMediaIndex;
|
||||
@ -211,6 +213,7 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
|
||||
new RequestingUserName("", Locale.getDefault()),
|
||||
//SheetCollate.UNCOLLATED, //CUPS has no sheet collate?
|
||||
Sides.ONE_SIDED,
|
||||
OutputBin.TOP,
|
||||
};
|
||||
|
||||
|
||||
@ -440,6 +443,7 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
|
||||
if ((urlConnection = getIPPConnection(myURL)) == null) {
|
||||
mediaSizeNames = new MediaSizeName[0];
|
||||
mediaTrays = new MediaTray[0];
|
||||
outputBins = new OutputBin[0];
|
||||
debug_println(debugPrefix+"initAttributes, NULL urlConnection ");
|
||||
init = true;
|
||||
return;
|
||||
@ -460,6 +464,9 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
|
||||
cps = new CUPSPrinter(printer);
|
||||
mediaSizeNames = cps.getMediaSizeNames();
|
||||
mediaTrays = cps.getMediaTrays();
|
||||
outputBins = PrintServiceLookupProvider.isMac()
|
||||
? cps.getOutputBins()
|
||||
: getSupportedOutputBins();
|
||||
customMediaSizeNames = cps.getCustomMediaSizeNames();
|
||||
defaultMediaIndex = cps.getDefaultMediaIndex();
|
||||
rawResolutions = cps.getRawResolutions();
|
||||
@ -493,6 +500,11 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
|
||||
mediaTrays = new MediaTray[trayList.size()];
|
||||
mediaTrays = trayList.toArray(mediaTrays);
|
||||
}
|
||||
|
||||
if (outputBins == null) {
|
||||
outputBins = getSupportedOutputBins();
|
||||
}
|
||||
|
||||
urlConnection.disconnect();
|
||||
|
||||
init = true;
|
||||
@ -827,6 +839,8 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
|
||||
new PrinterResolution[supportedRes.length];
|
||||
System.arraycopy(supportedRes, 0, arr, 0, supportedRes.length);
|
||||
return arr;
|
||||
} else if (category == OutputBin.class) {
|
||||
return Arrays.copyOf(outputBins, outputBins.length);
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -1053,6 +1067,25 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
|
||||
return new Media[0];
|
||||
}
|
||||
|
||||
private OutputBin[] getSupportedOutputBins() {
|
||||
if ((getAttMap != null) && getAttMap.containsKey("output-bin-supported")) {
|
||||
|
||||
AttributeClass attribClass = getAttMap.get("output-bin-supported");
|
||||
|
||||
if (attribClass != null) {
|
||||
String[] values = attribClass.getArrayOfStringValues();
|
||||
if (values == null || values.length == 0) {
|
||||
return null;
|
||||
}
|
||||
OutputBin[] outputBinNames = new OutputBin[values.length];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
outputBinNames[i] = CustomOutputBin.createOutputBin(values[i], values[i]);
|
||||
}
|
||||
return outputBinNames;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public synchronized Class<?>[] getSupportedAttributeCategories() {
|
||||
if (supportedCats != null) {
|
||||
@ -1070,6 +1103,11 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
|
||||
(PrintRequestAttribute)printReqAttribDefault[i];
|
||||
if (getAttMap != null &&
|
||||
getAttMap.containsKey(pra.getName()+"-supported")) {
|
||||
|
||||
if (pra == OutputBin.TOP && (outputBins == null || outputBins.length == 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
catList.add(pra.getCategory());
|
||||
}
|
||||
}
|
||||
@ -1148,6 +1186,11 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (category == OutputBin.class
|
||||
&& (outputBins == null || outputBins.length == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i=0;i<supportedCats.length;i++) {
|
||||
if (category == supportedCats[i]) {
|
||||
return true;
|
||||
@ -1478,6 +1521,18 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
|
||||
DialogTypeSelection dst = (DialogTypeSelection)attr;
|
||||
return attr == DialogTypeSelection.COMMON;
|
||||
}
|
||||
} else if (attr.getCategory() == OutputBin.class) {
|
||||
if (attr instanceof CustomOutputBin) {
|
||||
return true;
|
||||
}
|
||||
String name = attr.toString();
|
||||
for (OutputBin outputBin : outputBins) {
|
||||
String choice = ((CustomOutputBin) outputBin).getChoiceName();
|
||||
if (name.equalsIgnoreCase(choice) || name.replaceAll("-", "").equalsIgnoreCase(choice)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1646,6 +1701,10 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
|
||||
} else {
|
||||
return new PrinterResolution(300, 300, PrinterResolution.DPI);
|
||||
}
|
||||
} else if (category == OutputBin.class) {
|
||||
if (attribClass != null) {
|
||||
return CustomOutputBin.createOutputBin(attribClass.getStringValue(), attribClass.getStringValue());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -415,6 +415,96 @@ Java_sun_print_CUPSPrinter_getMedia(JNIEnv *env,
|
||||
return nameArray;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns list of output bins
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
Java_sun_print_CUPSPrinter_getOutputBins(JNIEnv *env,
|
||||
jobject printObj,
|
||||
jstring printer)
|
||||
{
|
||||
ppd_file_t *ppd;
|
||||
ppd_choice_t *choice;
|
||||
ppd_option_t *outputBin;
|
||||
const char *name;
|
||||
const char *filename;
|
||||
int i, nBins=0;
|
||||
jstring utf_str;
|
||||
jclass cls;
|
||||
jobjectArray nameArray = NULL;
|
||||
|
||||
name = (*env)->GetStringUTFChars(env, printer, NULL);
|
||||
if (name == NULL) {
|
||||
(*env)->ExceptionClear(env);
|
||||
JNU_ThrowOutOfMemoryError(env, "Could not create printer name");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// NOTE: cupsGetPPD returns a pointer to a filename of a temporary file.
|
||||
// unlink() must be caled to remove the file when finished using it.
|
||||
filename = j2d_cupsGetPPD(name);
|
||||
(*env)->ReleaseStringUTFChars(env, printer, name);
|
||||
CHECK_NULL_RETURN(filename, NULL);
|
||||
|
||||
cls = (*env)->FindClass(env, "java/lang/String");
|
||||
CHECK_NULL_RETURN(cls, NULL);
|
||||
|
||||
if ((ppd = j2d_ppdOpenFile(filename)) == NULL) {
|
||||
unlink(filename);
|
||||
DPRINTF("CUPSfuncs::unable to open PPD %s\n", filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
outputBin = j2d_ppdFindOption(ppd, "OutputBin");
|
||||
if (outputBin != NULL) {
|
||||
nBins = outputBin->num_choices;
|
||||
}
|
||||
|
||||
if (nBins > 0) {
|
||||
nameArray = (*env)->NewObjectArray(env, nBins * 2, cls, NULL);
|
||||
if (nameArray == NULL) {
|
||||
unlink(filename);
|
||||
j2d_ppdClose(ppd);
|
||||
DPRINTF("CUPSfuncs::bad alloc new array\n", "")
|
||||
if (!(*env)->ExceptionCheck(env)) {
|
||||
JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; outputBin!=NULL && i<nBins; i++) {
|
||||
choice = (outputBin->choices)+i;
|
||||
utf_str = JNU_NewStringPlatform(env, choice->text);
|
||||
if (utf_str == NULL) {
|
||||
unlink(filename);
|
||||
j2d_ppdClose(ppd);
|
||||
DPRINTF("CUPSfuncs::bad alloc new string text\n", "")
|
||||
if (!(*env)->ExceptionCheck(env)) {
|
||||
JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
(*env)->SetObjectArrayElement(env, nameArray, i*2, utf_str);
|
||||
(*env)->DeleteLocalRef(env, utf_str);
|
||||
utf_str = JNU_NewStringPlatform(env, choice->choice);
|
||||
if (utf_str == NULL) {
|
||||
unlink(filename);
|
||||
j2d_ppdClose(ppd);
|
||||
DPRINTF("CUPSfuncs::bad alloc new string choice\n", "")
|
||||
if (!(*env)->ExceptionCheck(env)) {
|
||||
JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
(*env)->SetObjectArrayElement(env, nameArray, i*2+1, utf_str);
|
||||
(*env)->DeleteLocalRef(env, utf_str);
|
||||
}
|
||||
}
|
||||
|
||||
j2d_ppdClose(ppd);
|
||||
unlink(filename);
|
||||
return nameArray;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns list of page sizes and imageable area.
|
||||
|
116
test/jdk/javax/print/attribute/CheckSupportedOutputBinsTest.java
Normal file
116
test/jdk/javax/print/attribute/CheckSupportedOutputBinsTest.java
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, BELLSOFT. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.print.PrintService;
|
||||
import javax.print.PrintServiceLookup;
|
||||
import javax.print.attribute.Attribute;
|
||||
import javax.print.attribute.standard.OutputBin;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8314070
|
||||
* @key printer
|
||||
* @summary javax.print: Support IPP output-bin attribute extension
|
||||
*/
|
||||
|
||||
public class CheckSupportedOutputBinsTest {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null);
|
||||
|
||||
if (services == null) {
|
||||
System.out.printf("Skip the test as there are no available PrintServices.%n");
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.printf("Print services: %d%n", services.length);
|
||||
|
||||
for (PrintService service : services) {
|
||||
checkSupportedOutputBins(service);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkSupportedOutputBins(PrintService service) throws Exception {
|
||||
|
||||
System.out.printf("Check printService: %s%n", service);
|
||||
|
||||
boolean isOutputBinCategorySupported = service.isAttributeCategorySupported(OutputBin.class);
|
||||
OutputBin defaultOutputBin = (OutputBin) service.getDefaultAttributeValue(OutputBin.class);
|
||||
Set<Class<?>> supportedAttributeCategories = Set.of(service.getSupportedAttributeCategories());
|
||||
OutputBin[] supportedOutputBins = (OutputBin[]) service
|
||||
.getSupportedAttributeValues(OutputBin.class, null, null);
|
||||
|
||||
if (!isOutputBinCategorySupported) {
|
||||
|
||||
if (supportedAttributeCategories.contains(OutputBin.class)) {
|
||||
throw new Exception("OutputBin category is not supported" +
|
||||
" and supported attribute categories contain OutputBin.class.");
|
||||
}
|
||||
|
||||
if (defaultOutputBin != null) {
|
||||
throw new Exception("OutputBin category is not supported" +
|
||||
" and the default output bin is not null.");
|
||||
}
|
||||
|
||||
if (supportedOutputBins != null && supportedOutputBins.length > 0) {
|
||||
throw new Exception("OutputBin category is not supported" +
|
||||
" and array of supported output bins is not null or its size is not zero.");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!supportedAttributeCategories.contains(OutputBin.class)) {
|
||||
throw new Exception("OutputBin category is supported" +
|
||||
" and supported attribute categories do not contain OutputBin.class.");
|
||||
}
|
||||
|
||||
if (defaultOutputBin == null) {
|
||||
throw new Exception("OutputBin category is supported" +
|
||||
" and the default output bin is null.");
|
||||
}
|
||||
|
||||
if (supportedOutputBins == null || supportedOutputBins.length == 0) {
|
||||
throw new Exception("OutputBin category is supported" +
|
||||
" and PrintService.getSupportedAttributeValues() returns null or an array with zero elements.");
|
||||
}
|
||||
|
||||
if (!service.isAttributeValueSupported(defaultOutputBin, null, null)) {
|
||||
throw new Exception("OutputBin category is supported" +
|
||||
" and the default output bin " + defaultOutputBin + " is not supported");
|
||||
}
|
||||
|
||||
for (OutputBin outputBin : supportedOutputBins) {
|
||||
if (!service.isAttributeValueSupported(outputBin, null, null)) {
|
||||
throw new Exception("OutputBin category is supported" +
|
||||
" and the output bin " + outputBin + " from supported attribute values" +
|
||||
" is not supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,368 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, BELLSOFT. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.print.PrintService;
|
||||
import javax.print.attribute.Attribute;
|
||||
import javax.print.attribute.HashPrintRequestAttributeSet;
|
||||
import javax.print.attribute.PrintRequestAttributeSet;
|
||||
import javax.print.attribute.standard.DialogTypeSelection;
|
||||
import javax.print.attribute.standard.MediaSizeName;
|
||||
import javax.print.attribute.standard.OutputBin;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dialog;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.print.PageFormat;
|
||||
import java.awt.print.Printable;
|
||||
import java.awt.print.PrinterException;
|
||||
import java.awt.print.PrinterJob;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8314070
|
||||
* @key printer
|
||||
* @requires (os.family == "linux" | os.family == "mac")
|
||||
* @summary javax.print: Support IPP output-bin attribute extension
|
||||
* @run main/manual OutputBinAttributePrintDialogTest COMMON
|
||||
* @run main/manual OutputBinAttributePrintDialogTest NATIVE
|
||||
*/
|
||||
|
||||
public class OutputBinAttributePrintDialogTest {
|
||||
|
||||
private static final long TIMEOUT = 10 * 60_000;
|
||||
private static volatile boolean testPassed = true;
|
||||
private static volatile boolean testSkipped = false;
|
||||
private static volatile boolean testFinished = false;
|
||||
private static volatile boolean printJobCanceled = false;
|
||||
private static volatile boolean timeout = false;
|
||||
|
||||
private static volatile boolean isNativeDialog;
|
||||
|
||||
private static volatile int testCount;
|
||||
private static volatile int testTotalCount;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
if (args.length < 1) {
|
||||
throw new RuntimeException("COMMON or NATIVE print dialog type argument is not provided!");
|
||||
}
|
||||
|
||||
final DialogTypeSelection dialogTypeSelection = getDialogTypeSelection(args[0]);
|
||||
isNativeDialog = (dialogTypeSelection == DialogTypeSelection.NATIVE);
|
||||
|
||||
if (dialogTypeSelection == DialogTypeSelection.NATIVE) {
|
||||
String os = System.getProperty("os.name").toLowerCase();
|
||||
if (os.startsWith("linux")) {
|
||||
System.out.println("Skip the native print dialog type test on Linux as it is the same as the common.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
final OutputBin[] supportedOutputBins = getSupportedOutputBinttributes();
|
||||
if (supportedOutputBins == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (supportedOutputBins.length < 2) {
|
||||
System.out.println("Skip the test as the number of supported output bins is less than 2.");
|
||||
return;
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
testTotalCount = supportedOutputBins.length;
|
||||
for (OutputBin outputBin : supportedOutputBins) {
|
||||
if (testSkipped) {
|
||||
break;
|
||||
}
|
||||
testPrint(dialogTypeSelection, outputBin, supportedOutputBins);
|
||||
}
|
||||
testFinished = true;
|
||||
});
|
||||
|
||||
long time = System.currentTimeMillis() + TIMEOUT;
|
||||
|
||||
while (System.currentTimeMillis() < time) {
|
||||
if (!testPassed || testFinished) {
|
||||
break;
|
||||
}
|
||||
Thread.sleep(500);
|
||||
}
|
||||
|
||||
timeout = true;
|
||||
|
||||
closeDialogs();
|
||||
|
||||
if (testSkipped) {
|
||||
System.out.printf("Test is skipped!%n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!testPassed) {
|
||||
throw new Exception("Test failed!");
|
||||
}
|
||||
|
||||
if (testCount != testTotalCount) {
|
||||
throw new Exception(
|
||||
"Timeout: " + testCount + " tests passed out from " + testTotalCount);
|
||||
}
|
||||
}
|
||||
|
||||
private static void print(DialogTypeSelection dialogTypeSelection, OutputBin outputBin) throws PrinterException {
|
||||
PrintRequestAttributeSet attr = new HashPrintRequestAttributeSet();
|
||||
attr.add(MediaSizeName.ISO_A4);
|
||||
attr.add(dialogTypeSelection);
|
||||
|
||||
for (Attribute attribute : attr.toArray()) {
|
||||
System.out.printf("Used print request attribute: %s%n", attribute);
|
||||
}
|
||||
|
||||
PrinterJob job = PrinterJob.getPrinterJob();
|
||||
job.setJobName("Print to " + outputBin + " output bin through " + dialogTypeSelection + " print dialog");
|
||||
job.setPrintable(new OutputBinAttributePrintable(outputBin));
|
||||
|
||||
if (job.printDialog(attr)) {
|
||||
job.print();
|
||||
} else if (isNativeDialog) {
|
||||
printJobCanceled = true;
|
||||
} else {
|
||||
throw new RuntimeException(dialogTypeSelection + " print dialog for " + outputBin + " is canceled!");
|
||||
}
|
||||
}
|
||||
|
||||
private static class OutputBinAttributePrintable implements Printable {
|
||||
|
||||
private final OutputBin outputBinAttr;
|
||||
|
||||
public OutputBinAttributePrintable(OutputBin outputBinAttr) {
|
||||
this.outputBinAttr = outputBinAttr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
|
||||
|
||||
if (pageIndex != 0) {
|
||||
return NO_SUCH_PAGE;
|
||||
}
|
||||
|
||||
int x = (int) (pageFormat.getImageableX() + pageFormat.getImageableWidth() / 10);
|
||||
int y = (int) (pageFormat.getImageableY() + pageFormat.getImageableHeight() / 5);
|
||||
|
||||
Graphics2D g = (Graphics2D) graphics;
|
||||
g.setColor(Color.BLACK);
|
||||
g.drawString(getPageText(outputBinAttr), x, y);
|
||||
return PAGE_EXISTS;
|
||||
}
|
||||
}
|
||||
|
||||
private static String getPageText(OutputBin outputBin) {
|
||||
return String.format("Output bin: %s", outputBin);
|
||||
}
|
||||
|
||||
private static OutputBin[] getSupportedOutputBinttributes() {
|
||||
|
||||
PrinterJob printerJob = PrinterJob.getPrinterJob();
|
||||
PrintService service = printerJob.getPrintService();
|
||||
if (service == null) {
|
||||
System.out.printf("No print service found.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!service.isAttributeCategorySupported(OutputBin.class)) {
|
||||
System.out.printf("Skipping the test as OutputBin category is not supported for this printer.");
|
||||
return null;
|
||||
}
|
||||
|
||||
Object obj = service.getSupportedAttributeValues(OutputBin.class, null, null);
|
||||
|
||||
if (obj instanceof OutputBin[]) {
|
||||
return (OutputBin[]) obj;
|
||||
}
|
||||
|
||||
throw new RuntimeException("OutputBin category is supported but no supported attribute values are returned.");
|
||||
}
|
||||
|
||||
private static void pass() {
|
||||
testCount++;
|
||||
}
|
||||
|
||||
private static void skip() {
|
||||
testSkipped = true;
|
||||
}
|
||||
|
||||
private static void fail(OutputBin outputBin) {
|
||||
System.out.printf("Failed test: %s%n", getPageText(outputBin));
|
||||
testPassed = false;
|
||||
}
|
||||
|
||||
private static void runPrint(DialogTypeSelection dialogTypeSelection, OutputBin outputBin) {
|
||||
try {
|
||||
print(dialogTypeSelection, outputBin);
|
||||
} catch (PrinterException e) {
|
||||
e.printStackTrace();
|
||||
fail(outputBin);
|
||||
closeDialogs();
|
||||
}
|
||||
}
|
||||
|
||||
private static void testPrint(DialogTypeSelection dialogTypeSelection, OutputBin outputBin, OutputBin[] supportedOutputBins) {
|
||||
|
||||
System.out.printf("Test dialog: %s%n", dialogTypeSelection);
|
||||
|
||||
String[] instructions = {
|
||||
"Up to " + testTotalCount + " tests will run and it will test all output bins:",
|
||||
Arrays.toString(supportedOutputBins),
|
||||
"supported by the printer.",
|
||||
"",
|
||||
"The test is " + (testCount + 1) + " from " + testTotalCount + ".",
|
||||
"",
|
||||
"On-screen inspection is not possible for this printing-specific",
|
||||
"test therefore its only output is a page printed to the printer",
|
||||
outputBin + " output bin.",
|
||||
"",
|
||||
"To be able to run this test it is required to have a default",
|
||||
"printer configured in your user environment.",
|
||||
"",
|
||||
" - Press 'Start Test' button.",
|
||||
" The " + dialogTypeSelection + " print dialog should appear.",
|
||||
String.join("\n", getPrintDialogInstructions(dialogTypeSelection, outputBin)),
|
||||
"",
|
||||
"Visual inspection of the printed pages is needed.",
|
||||
"",
|
||||
"A passing test will print the page with the text: '" + getPageText(outputBin) + "'",
|
||||
"to the corresponding printer " + outputBin + " ouput bin.",
|
||||
"",
|
||||
"The test fails if the page is not printed in to the corresponding output bin.",
|
||||
};
|
||||
|
||||
String title = String.format("Print %s dialog with %s output bin test: %d from %d",
|
||||
dialogTypeSelection, outputBin, testCount + 1, testTotalCount);
|
||||
final JDialog dialog = new JDialog((Frame) null, title, Dialog.ModalityType.DOCUMENT_MODAL);
|
||||
JTextArea textArea = new JTextArea(String.join("\n", instructions));
|
||||
textArea.setEditable(false);
|
||||
final JButton testButton = new JButton("Start Test");
|
||||
final JButton skipButton = new JButton("Skip Test");
|
||||
final JButton passButton = new JButton("PASS");
|
||||
skipButton.setEnabled(false);
|
||||
passButton.setEnabled(false);
|
||||
passButton.addActionListener((e) -> {
|
||||
pass();
|
||||
dialog.dispose();
|
||||
});
|
||||
skipButton.addActionListener((e) -> {
|
||||
skip();
|
||||
dialog.dispose();
|
||||
});
|
||||
final JButton failButton = new JButton("FAIL");
|
||||
failButton.setEnabled(false);
|
||||
failButton.addActionListener((e) -> {
|
||||
fail(outputBin);
|
||||
dialog.dispose();
|
||||
});
|
||||
testButton.addActionListener((e) -> {
|
||||
testButton.setEnabled(false);
|
||||
runPrint(dialogTypeSelection, outputBin);
|
||||
skipButton.setEnabled(true);
|
||||
passButton.setEnabled(true);
|
||||
failButton.setEnabled(true);
|
||||
});
|
||||
|
||||
JPanel mainPanel = new JPanel(new BorderLayout());
|
||||
mainPanel.add(textArea, BorderLayout.CENTER);
|
||||
JPanel buttonPanel = new JPanel(new FlowLayout());
|
||||
buttonPanel.add(testButton);
|
||||
if (isNativeDialog) {
|
||||
buttonPanel.add(skipButton);
|
||||
}
|
||||
buttonPanel.add(passButton);
|
||||
buttonPanel.add(failButton);
|
||||
mainPanel.add(buttonPanel, BorderLayout.SOUTH);
|
||||
dialog.add(mainPanel);
|
||||
dialog.pack();
|
||||
dialog.setVisible(true);
|
||||
dialog.addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
System.out.println("Dialog closing");
|
||||
fail(outputBin);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void closeDialogs() {
|
||||
for (Window w : Dialog.getWindows()) {
|
||||
w.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private static DialogTypeSelection getDialogTypeSelection(String dialogTypeSelection) {
|
||||
switch (dialogTypeSelection) {
|
||||
case "COMMON":
|
||||
return DialogTypeSelection.COMMON;
|
||||
case "NATIVE":
|
||||
return DialogTypeSelection.NATIVE;
|
||||
default:
|
||||
throw new RuntimeException("Unknown dialog type selection: " + dialogTypeSelection);
|
||||
}
|
||||
}
|
||||
|
||||
private static String[] getPrintDialogInstructions(DialogTypeSelection dialogTypeSelection, OutputBin outputBin) {
|
||||
if (dialogTypeSelection == DialogTypeSelection.COMMON) {
|
||||
return new String[]{
|
||||
" - Select 'Appearance' tab.",
|
||||
" - Select '" + outputBin + "' output tray from 'Output trays' combo box.",
|
||||
" - Press 'Print' button."
|
||||
};
|
||||
} else if (dialogTypeSelection == DialogTypeSelection.NATIVE) {
|
||||
return new String[]{
|
||||
" - Press 'Show Details' buttons if the details are hidded.",
|
||||
" - Check that the native print dialog contains 'Finishing Options' in the drop-down list.",
|
||||
" - If there is no 'Finishing Options' in the drop-down list then",
|
||||
" - Press 'Cancel' button on the print dialog.",
|
||||
" - Press 'Skip Test' button on the test dialog.",
|
||||
" otherwise",
|
||||
" - Select 'Finishing Options' from the drop-down list.",
|
||||
" - Select '" + outputBin + "' Output Bin.",
|
||||
" - Press 'Print' button."
|
||||
};
|
||||
}
|
||||
throw new RuntimeException("Unknown dialog type selection: " + dialogTypeSelection);
|
||||
}
|
||||
}
|
275
test/jdk/javax/print/attribute/OutputBinAttributeTest.java
Normal file
275
test/jdk/javax/print/attribute/OutputBinAttributeTest.java
Normal file
@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, BELLSOFT. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.print.PrintService;
|
||||
import javax.print.attribute.Attribute;
|
||||
import javax.print.attribute.HashPrintRequestAttributeSet;
|
||||
import javax.print.attribute.PrintRequestAttributeSet;
|
||||
import javax.print.attribute.standard.MediaSizeName;
|
||||
import javax.print.attribute.standard.OutputBin;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dialog;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.print.PageFormat;
|
||||
import java.awt.print.Printable;
|
||||
import java.awt.print.PrinterException;
|
||||
import java.awt.print.PrinterJob;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8314070
|
||||
* @key printer
|
||||
* @requires (os.family == "linux" | os.family == "mac")
|
||||
* @summary javax.print: Support IPP output-bin attribute extension
|
||||
* @run main/manual OutputBinAttributeTest
|
||||
*/
|
||||
|
||||
public class OutputBinAttributeTest {
|
||||
|
||||
private static final long TIMEOUT = 10 * 60_000;
|
||||
private static volatile boolean testPassed = true;
|
||||
private static volatile boolean testFinished = false;
|
||||
private static volatile boolean timeout = false;
|
||||
|
||||
private static volatile int testCount;
|
||||
private static volatile int testTotalCount;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
Set<OutputBin> supportedOutputBins = getSupportedOutputBinttributes();
|
||||
if (supportedOutputBins != null) {
|
||||
if (supportedOutputBins.size() > 1) {
|
||||
testTotalCount = supportedOutputBins.size();
|
||||
for (OutputBin outputBin : supportedOutputBins) {
|
||||
testPrint(outputBin, supportedOutputBins);
|
||||
}
|
||||
} else {
|
||||
System.out.println("Skip the test as the number of supported output bins is less than 2.");
|
||||
}
|
||||
}
|
||||
testFinished = true;
|
||||
});
|
||||
|
||||
long time = System.currentTimeMillis() + TIMEOUT;
|
||||
|
||||
while (System.currentTimeMillis() < time) {
|
||||
if (!testPassed || testFinished) {
|
||||
break;
|
||||
}
|
||||
Thread.sleep(500);
|
||||
}
|
||||
|
||||
timeout = true;
|
||||
|
||||
closeDialogs();
|
||||
|
||||
if (!testPassed) {
|
||||
throw new Exception("Test failed!");
|
||||
}
|
||||
|
||||
if (testCount != testTotalCount) {
|
||||
throw new Exception(
|
||||
"Timeout: " + testCount + " tests passed out from " + testTotalCount);
|
||||
}
|
||||
}
|
||||
|
||||
private static void print(OutputBin outputBin) throws PrinterException {
|
||||
PrintRequestAttributeSet attr = new HashPrintRequestAttributeSet();
|
||||
attr.add(MediaSizeName.ISO_A4);
|
||||
attr.add(outputBin);
|
||||
|
||||
for (Attribute attribute : attr.toArray()) {
|
||||
System.out.printf("Used print request attribute: %s%n", attribute);
|
||||
}
|
||||
|
||||
PrinterJob job = PrinterJob.getPrinterJob();
|
||||
job.setJobName("Print to " + outputBin + " output bin");
|
||||
job.setPrintable(new OutputBinAttributePrintable(outputBin));
|
||||
|
||||
job.print(attr);
|
||||
}
|
||||
|
||||
private static class OutputBinAttributePrintable implements Printable {
|
||||
|
||||
private final OutputBin outputBinAttr;
|
||||
|
||||
public OutputBinAttributePrintable(OutputBin outputBinAttr) {
|
||||
this.outputBinAttr = outputBinAttr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
|
||||
|
||||
if (pageIndex != 0) {
|
||||
return NO_SUCH_PAGE;
|
||||
}
|
||||
|
||||
int x = (int) (pageFormat.getImageableX() + pageFormat.getImageableWidth() / 10);
|
||||
int y = (int) (pageFormat.getImageableY() + pageFormat.getImageableHeight() / 5);
|
||||
|
||||
Graphics2D g = (Graphics2D) graphics;
|
||||
g.setColor(Color.BLACK);
|
||||
g.drawString(getPageText(outputBinAttr), x, y);
|
||||
return PAGE_EXISTS;
|
||||
}
|
||||
}
|
||||
|
||||
private static String getPageText(OutputBin outputBin) {
|
||||
return String.format("Output bin: %s", outputBin);
|
||||
}
|
||||
|
||||
private static Set<OutputBin> getSupportedOutputBinttributes() {
|
||||
Set<OutputBin> supportedOutputBins = new HashSet<>();
|
||||
|
||||
PrinterJob printerJob = PrinterJob.getPrinterJob();
|
||||
PrintService service = printerJob.getPrintService();
|
||||
if (service == null) {
|
||||
System.out.printf("No print service found.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!service.isAttributeCategorySupported(OutputBin.class)) {
|
||||
System.out.printf("Skipping the test as OutputBin category is not supported for this printer.");
|
||||
return null;
|
||||
}
|
||||
|
||||
Object obj = service.getSupportedAttributeValues(OutputBin.class, null, null);
|
||||
|
||||
if (obj instanceof OutputBin[]) {
|
||||
Collections.addAll(supportedOutputBins, (OutputBin[]) obj);
|
||||
return supportedOutputBins;
|
||||
}
|
||||
|
||||
throw new RuntimeException("OutputBin category is supported but no supported attribute values are returned.");
|
||||
}
|
||||
|
||||
private static void pass() {
|
||||
testCount++;
|
||||
}
|
||||
|
||||
private static void fail(OutputBin outputBin) {
|
||||
System.out.printf("Failed test: %s%n", getPageText(outputBin));
|
||||
testPassed = false;
|
||||
}
|
||||
|
||||
private static void runPrint(OutputBin outputBin) {
|
||||
try {
|
||||
print(outputBin);
|
||||
} catch (PrinterException e) {
|
||||
e.printStackTrace();
|
||||
fail(outputBin);
|
||||
}
|
||||
}
|
||||
|
||||
private static void testPrint(OutputBin outputBin, Set<OutputBin> supportedOutputBins) {
|
||||
|
||||
String[] instructions = {
|
||||
"Up to " + testTotalCount + " tests will run and it will test all output bins:",
|
||||
supportedOutputBins.toString(),
|
||||
"supported by the printer.",
|
||||
"",
|
||||
"The test is " + (testCount + 1) + " from " + testTotalCount + ".",
|
||||
"",
|
||||
"On-screen inspection is not possible for this printing-specific",
|
||||
"test therefore its only output is a page printed to the printer",
|
||||
outputBin + " output bin.",
|
||||
"To be able to run this test it is required to have a default",
|
||||
"printer configured in your user environment.",
|
||||
"",
|
||||
"Visual inspection of the printed pages is needed.",
|
||||
"",
|
||||
"A passing test will print the page with the text: '" + getPageText(outputBin) + "'",
|
||||
"to the corresponding printer " + outputBin + " ouput bin.",
|
||||
"",
|
||||
"The test fails if the page is not printed in to the corresponding output bin.",
|
||||
};
|
||||
|
||||
String title = String.format("Print %s output bin test: %d from %d",
|
||||
outputBin, testCount + 1, testTotalCount);
|
||||
final JDialog dialog = new JDialog((Frame) null, title, Dialog.ModalityType.DOCUMENT_MODAL);
|
||||
JTextArea textArea = new JTextArea(String.join("\n", instructions));
|
||||
textArea.setEditable(false);
|
||||
final JButton testButton = new JButton("Start Test");
|
||||
final JButton passButton = new JButton("PASS");
|
||||
passButton.setEnabled(false);
|
||||
passButton.addActionListener((e) -> {
|
||||
pass();
|
||||
dialog.dispose();
|
||||
});
|
||||
final JButton failButton = new JButton("FAIL");
|
||||
failButton.setEnabled(false);
|
||||
failButton.addActionListener((e) -> {
|
||||
fail(outputBin);
|
||||
dialog.dispose();
|
||||
});
|
||||
testButton.addActionListener((e) -> {
|
||||
testButton.setEnabled(false);
|
||||
runPrint(outputBin);
|
||||
passButton.setEnabled(true);
|
||||
failButton.setEnabled(true);
|
||||
});
|
||||
|
||||
JPanel mainPanel = new JPanel(new BorderLayout());
|
||||
mainPanel.add(textArea, BorderLayout.CENTER);
|
||||
JPanel buttonPanel = new JPanel(new FlowLayout());
|
||||
buttonPanel.add(testButton);
|
||||
buttonPanel.add(passButton);
|
||||
buttonPanel.add(failButton);
|
||||
mainPanel.add(buttonPanel, BorderLayout.SOUTH);
|
||||
dialog.add(mainPanel);
|
||||
dialog.pack();
|
||||
dialog.setVisible(true);
|
||||
dialog.addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
System.out.println("Dialog closing");
|
||||
fail(outputBin);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void closeDialogs() {
|
||||
for (Window w : Dialog.getWindows()) {
|
||||
w.dispose();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user