/*
* Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (C) 2009 Volker Berlin (i-net software)
* Copyright (C) 2010, 2011 Karsten Heinrich (i-net software)
* 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.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintService;
import javax.print.ServiceUIFactory;
import javax.print.attribute.Attribute;
import javax.print.attribute.AttributeSet;
import javax.print.attribute.AttributeSetUtilities;
import javax.print.attribute.HashPrintServiceAttributeSet;
import javax.print.attribute.PrintServiceAttribute;
import javax.print.attribute.PrintServiceAttributeSet;
import javax.print.attribute.standard.Chromaticity;
import javax.print.attribute.standard.ColorSupported;
import javax.print.attribute.standard.Copies;
import javax.print.attribute.standard.CopiesSupported;
import javax.print.attribute.standard.Destination;
import javax.print.attribute.standard.Fidelity;
import javax.print.attribute.standard.JobName;
import javax.print.attribute.standard.Media;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.print.attribute.standard.MediaSize;
import javax.print.attribute.standard.MediaSizeName;
import javax.print.attribute.standard.MediaTray;
import javax.print.attribute.standard.OrientationRequested;
import javax.print.attribute.standard.PageRanges;
import javax.print.attribute.standard.PrintQuality;
import javax.print.attribute.standard.PrinterIsAcceptingJobs;
import javax.print.attribute.standard.PrinterName;
import javax.print.attribute.standard.PrinterResolution;
import javax.print.attribute.standard.PrinterState;
import javax.print.attribute.standard.PrinterStateReasons;
import javax.print.attribute.standard.QueuedJobCount;
import javax.print.attribute.standard.RequestingUserName;
import javax.print.attribute.standard.SheetCollate;
import javax.print.attribute.standard.Sides;
import javax.print.event.PrintServiceAttributeListener;
import cli.System.NewsStyleUriParser;
import cli.System.Type;
import cli.System.Collections.IEnumerator;
import cli.System.Drawing.RectangleF;
import cli.System.Drawing.Printing.Duplex;
import cli.System.Drawing.Printing.PaperKind;
import cli.System.Drawing.Printing.PaperSize;
import cli.System.Drawing.Printing.PaperSource;
import cli.System.Drawing.Printing.PrintDocument;
import cli.System.Drawing.Printing.PrinterSettings;
import cli.System.Drawing.Printing.PrinterSettings.PaperSizeCollection;
import cli.System.Drawing.Printing.PrinterSettings.PaperSourceCollection;
import cli.System.Net.Mime.MediaTypeNames;
/**
* @author Volker Berlin
*/
public class Win32PrintService implements PrintService {
// note: the Win32PrintService is implemented as foreign service (doesn't implement SunPrinterJobService)
// to avoid implementing the WPrinterJob
private static final DocFlavor[] supportedFlavors = {
DocFlavor.SERVICE_FORMATTED.PAGEABLE,
DocFlavor.SERVICE_FORMATTED.PRINTABLE,
};
/** Mapping for PageSize.RawKind to predefined MediaSizeName */
private static final MediaSizeName[] MEDIA_NAMES = new MediaSizeName[44];
/* it turns out to be inconvenient to store the other categories
* separately because many attributes are in multiple categories.
*/
private static Class[] otherAttrCats = {
JobName.class,
RequestingUserName.class,
Copies.class,
Destination.class,
OrientationRequested.class,
PageRanges.class,
Media.class,
MediaPrintableArea.class,
Fidelity.class,
// We support collation on 2D printer jobs, even if the driver can't.
SheetCollate.class,
SunAlternateMedia.class,
Chromaticity.class
};
// conversion from 1/100 Inch (.NET) to �m (Java)
private static final int INCH100_TO_MYM = 254;
private static final int MATCH_DIFF = 500; // 0.5 mm
static {
MEDIA_NAMES[0] = MediaSizeName.NA_LETTER;
MEDIA_NAMES[1] = MediaSizeName.NA_LETTER ;
MEDIA_NAMES[2] = MediaSizeName.TABLOID ;
MEDIA_NAMES[3] = MediaSizeName.LEDGER ;
MEDIA_NAMES[4] = MediaSizeName.NA_LEGAL ;
MEDIA_NAMES[5] = MediaSizeName.INVOICE ; // Statement
MEDIA_NAMES[6] = MediaSizeName.EXECUTIVE ;
MEDIA_NAMES[7] = MediaSizeName.ISO_A3 ;
MEDIA_NAMES[8] = MediaSizeName.ISO_A4 ;
MEDIA_NAMES[9] = MediaSizeName.ISO_A4 ; // A4Small, 10
MEDIA_NAMES[10] = MediaSizeName.ISO_A5 ;
MEDIA_NAMES[11] = MediaSizeName.JIS_B4 ;
MEDIA_NAMES[12] = MediaSizeName.JIS_B5 ;
MEDIA_NAMES[13] = MediaSizeName.FOLIO ;
MEDIA_NAMES[14] = MediaSizeName.QUARTO ;
MEDIA_NAMES[15] = MediaSizeName.NA_10X14_ENVELOPE ;
MEDIA_NAMES[16] = MediaSizeName.B ; // 10x17 Envelope
MEDIA_NAMES[17] = MediaSizeName.NA_LETTER ; // Note
MEDIA_NAMES[18] = MediaSizeName.NA_NUMBER_9_ENVELOPE ;
MEDIA_NAMES[19] = MediaSizeName.NA_NUMBER_10_ENVELOPE ; // 20
MEDIA_NAMES[20] = MediaSizeName.NA_NUMBER_11_ENVELOPE ;
MEDIA_NAMES[21] = MediaSizeName.NA_NUMBER_12_ENVELOPE ;
MEDIA_NAMES[22] = MediaSizeName.NA_NUMBER_14_ENVELOPE ;
MEDIA_NAMES[23] = MediaSizeName.C ;
MEDIA_NAMES[24] = MediaSizeName.D ;
MEDIA_NAMES[25] = MediaSizeName.E ;
MEDIA_NAMES[26] = MediaSizeName.ISO_DESIGNATED_LONG ;
MEDIA_NAMES[27] = MediaSizeName.ISO_C5 ;
MEDIA_NAMES[28] = MediaSizeName.ISO_C3 ;
MEDIA_NAMES[29] = MediaSizeName.ISO_C4 ; // 30
MEDIA_NAMES[30] = MediaSizeName.ISO_C6 ;
MEDIA_NAMES[31] = MediaSizeName.ITALY_ENVELOPE ;
MEDIA_NAMES[32] = MediaSizeName.ISO_B4 ;
MEDIA_NAMES[33] = MediaSizeName.ISO_B5 ;
MEDIA_NAMES[34] = MediaSizeName.ISO_B6 ;
MEDIA_NAMES[35] = MediaSizeName.ITALY_ENVELOPE ;
MEDIA_NAMES[36] = MediaSizeName.MONARCH_ENVELOPE ;
MEDIA_NAMES[37] = MediaSizeName.PERSONAL_ENVELOPE ;
MEDIA_NAMES[38] = MediaSizeName.NA_10X15_ENVELOPE ; // USStandardFanfold
MEDIA_NAMES[39] = MediaSizeName.NA_9X12_ENVELOPE ; // GermanStandardFanfold, 40
MEDIA_NAMES[40] = MediaSizeName.FOLIO ; // GermanLegalFanfold
MEDIA_NAMES[41] = MediaSizeName.ISO_B4 ;
MEDIA_NAMES[42] = MediaSizeName.JAPANESE_POSTCARD ;
MEDIA_NAMES[43] = MediaSizeName.NA_9X11_ENVELOPE ;
// // augment the media size with the .NET default sizes available on the printer
// PrinterSettings ps = new PrinterSettings();
// IEnumerator printers = PrinterSettings.get_InstalledPrinters().GetEnumerator();
// printers.Reset();
// while( printers.MoveNext() ){
// ps.set_PrinterName( (String) printers.get_Current() );
// IEnumerator sizes = ps.get_PaperSizes().GetEnumerator();
// sizes.Reset();
// while( sizes.MoveNext() ){
// PaperSize size = (PaperSize) sizes.get_Current();
// int kind = size.get_RawKind();
// if( kind >= 0 && kind < MEDIA_NAMES.length && MEDIA_NAMES[kind] == null ){
// MEDIA_NAMES[kind] = new CustomMediaSizeName( size.get_PaperName() );
// int x = size.get_Width();
// int y = size.get_Height();
// if( x > y ){ // not allowed by MediaSize
// int tmp = x;
// x = y;
// y = tmp;
// }
// new MediaSize(x, y, INCH100_TO_MYM, MEDIA_NAMES[kind]); // cache entry in map
// }
// }
// }
}
private final PrintPeer peer;
private final String printer;
private final PrinterSettings settings;
private PrinterName name;
private MediaTray[] mediaTrays;
transient private ServiceNotifier notifier = null;
public Win32PrintService(String name, PrintPeer peer){
if(name == null){
throw new IllegalArgumentException("null printer name");
}
this.peer = peer;
printer = name;
settings = new PrintDocument().get_PrinterSettings();
settings.set_PrinterName(printer);
}
@Override
public String getName(){
return printer;
}
private PrinterName getPrinterName(){
if(name == null){
name = new PrinterName(printer, null);
}
return name;
}
public void wakeNotifier() {
synchronized (this) {
if (notifier != null) {
notifier.wake();
}
}
}
@Override
public void addPrintServiceAttributeListener(PrintServiceAttributeListener listener){
synchronized (this) {
if (listener == null) {
return;
}
if (notifier == null) {
notifier = new ServiceNotifier(this);
}
notifier.addListener(listener);
}
}
@Override
public void removePrintServiceAttributeListener(PrintServiceAttributeListener listener){
synchronized (this) {
if (listener == null || notifier == null ) {
return;
}
notifier.removeListener(listener);
if (notifier.isEmpty()) {
notifier.stopNotifier();
notifier = null;
}
}
}
@Override
public DocPrintJob createPrintJob(){
SecurityManager security = System.getSecurityManager();
if(security != null){
security.checkPrintJobAccess();
}
return new Win32PrintJob(this, peer);
}
@Override
public <T extends PrintServiceAttribute>T getAttribute(Class<T> category){
if(category == null){
throw new NullPointerException("category");
}
if(!(PrintServiceAttribute.class.isAssignableFrom(category))){
throw new IllegalArgumentException("The categhory '" + category + "' is not a valid PrintServiceAttribute");
}
if(category == ColorSupported.class){
// works better than settings.get_SupportsColor();
if(settings.get_DefaultPageSettings().get_Color()){
return (T)ColorSupported.SUPPORTED;
}else{
return (T)ColorSupported.NOT_SUPPORTED;
}
}else if(category == PrinterName.class){
return (T)getPrinterName();
} else {
// QueuedJobCount and PrinterIsAcceptingJobs
return (T)peer.getPrinterStatus(printer, category);
}
}
@Override
public PrintServiceAttributeSet getAttributes(){
PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet();
attrs.add(getPrinterName());
PrinterIsAcceptingJobs acptJobs = getAttribute(PrinterIsAcceptingJobs.class);
if(acptJobs != null){
attrs.add(acptJobs);
}
PrinterState prnState = getAttribute(PrinterState.class);
if(prnState != null){
attrs.add(prnState);
}
PrinterStateReasons prnStateReasons = getAttribute(PrinterStateReasons.class);
if(prnStateReasons != null){
attrs.add(prnStateReasons);
}
QueuedJobCount jobCount = getAttribute(QueuedJobCount.class);
if(jobCount != null){
attrs.add(jobCount);
}
// TODO: Seems to be more accurate than settings.get_SupportsColor(), which doesn't work for CutePDF
if(settings.get_DefaultPageSettings().get_Color()){
attrs.add(ColorSupported.SUPPORTED);
}else{
attrs.add(ColorSupported.NOT_SUPPORTED);
}
return AttributeSetUtilities.unmodifiableView(attrs);
}
@Override
public Object getDefaultAttributeValue(Class<? extends Attribute> category){
if (category == null) {
throw new NullPointerException("category must not be null");
}
if ( !Attribute.class.isAssignableFrom( category ) ) {
throw new IllegalArgumentException( category +" has to be an " + Attribute.class.getName() );
}
if ( !isAttributeCategorySupported( category ) ) {
return null;
}
if (category == Copies.class) {
short copies = settings.get_Copies();
return new Copies( copies > 0 ? copies : 1 );
}
if (category == Chromaticity.class) {
// NOTE: this works for CutePDF, settings.get_SupportsColor() does not
return settings.get_DefaultPageSettings().get_Color() ? Chromaticity.COLOR : Chromaticity.MONOCHROME;
}
if (category == JobName.class) {
return new JobName( "Java Printing", null ); // TODO this is Java-Default, use another one for IKVM?
}
if (category == OrientationRequested.class) {
return settings.get_DefaultPageSettings().get_Landscape() ? OrientationRequested.LANDSCAPE : OrientationRequested.PORTRAIT;
}
if (category == PageRanges.class) {
return new PageRanges(1, Integer.MAX_VALUE );
}
if (category == Media.class) {
int rawKind = settings.get_DefaultPageSettings().get_PaperSize().get_RawKind();
if( rawKind > MEDIA_NAMES.length || rawKind < 1 || MEDIA_NAMES[ rawKind - 1 ] == null ){ // custom page format
return settings.get_DefaultPageSettings().get_PaperSize().get_PaperName();
} else {
return MEDIA_NAMES[ rawKind - 1 ];
}
}
if (category == MediaPrintableArea.class) {
RectangleF area = settings.get_DefaultPageSettings().get_PrintableArea();
// get_PrintableArea is in 1/100 inch, see http://msdn.microsoft.com/de-de/library/system.drawing.printing.pagesettings.printablearea(v=VS.90).aspx
return new MediaPrintableArea(area.get_X()/100, area.get_Y()/100, area.get_Width()/100, area.get_Height()/100, MediaPrintableArea.INCH);
}
if (category == Destination.class) {
String path = "out.prn";
try {
return new Destination( ( new File( path ) ).toURI() );
} catch (SecurityException se) {
try {
return new Destination( new URI( "file:" + path) );
} catch (URISyntaxException e) {
return null;
}
}
}
if (category == Sides.class) {
switch( settings.get_Duplex().Value ){
case cli.System.Drawing.Printing.Duplex.Default: // MSDN: 'The printer's default duplex setting.' - what ever that might be
case cli.System.Drawing.Printing.Duplex.Simplex:
return Sides.ONE_SIDED;
case cli.System.Drawing.Printing.Duplex.Horizontal:
return Sides.TWO_SIDED_LONG_EDGE;
case cli.System.Drawing.Printing.Duplex.Vertical:
return Sides.TWO_SIDED_SHORT_EDGE;
}
}
if (category == PrinterResolution.class) {
cli.System.Drawing.Printing.PrinterResolution res = settings.get_DefaultPageSettings().get_PrinterResolution();
return new PrinterResolution( res.get_X(), res.get_Y(), PrinterResolution.DPI);
}
if (category == ColorSupported.class) {
if ( settings.get_SupportsColor() ) {
return ColorSupported.SUPPORTED;
} else {
return ColorSupported.NOT_SUPPORTED;
}
}
if( category == PrintQuality.class ){
return PrintQuality.NORMAL; // TODO not correct, only available when using a PrintServer instance?
}
if (category == RequestingUserName.class) {
try{
return new RequestingUserName( System.getProperty("user.name", ""), null);
} catch( SecurityException e ){
return new RequestingUserName( "", null);
}
}
if (category == SheetCollate.class){
return settings.get_Collate() ? SheetCollate.COLLATED : SheetCollate.UNCOLLATED;
}
if (category == Fidelity.class) {
return Fidelity.FIDELITY_FALSE;
}
return null;
}
@Override
public ServiceUIFactory getServiceUIFactory(){
return null;
}
@Override
public Class<?>[] getSupportedAttributeCategories(){
ArrayList<Class> categList = new ArrayList<Class>(otherAttrCats.length+3);
for (int i=0; i < otherAttrCats.length; i++) {
categList.add(otherAttrCats[i]);
}
if (settings.get_CanDuplex()) {
categList.add(Sides.class);
}
if (settings.get_PrinterResolutions().get_Count() > 0) {
categList.add(PrinterResolution.class);
}
return categList.toArray(new Class[categList.size()]);
}
@Override
public Object getSupportedAttributeValues(Class<? extends Attribute> category, DocFlavor flavor, AttributeSet attributes){
if ( category == null || !Attribute.class.isAssignableFrom( category ) ) {
throw new IllegalArgumentException( "The category '" + category + "' is not an Attribute" );
}
if( !isAttributeCategorySupported(category) ){
return null;
}
if (category == JobName.class || category == RequestingUserName.class || category == ColorSupported.class
|| category == Destination.class ) {
return getDefaultAttributeValue(category);
}
if( category == Copies.class ){
return new CopiesSupported(1, settings.get_MaximumCopies() );
}
if( category == Media.class ){
PaperSizeCollection sizes = settings.get_PaperSizes();
List<Media> medias = new ArrayList<Media>();
for( int i = 0; i < sizes.get_Count(); i++ ){
PaperSize media = sizes.get_Item(i);
MediaSizeName mediaName = findMatchingMedia( sizes.get_Item(i) );
if( mediaName != null
&& !medias.contains( mediaName )){ // slow but better than creating a HashSet here
medias.add( mediaName);
}
}
// add media trays
MediaTray[] trays = getMediaTrays();
for( MediaTray tray : trays ){
medias.add( tray );
}
return medias.size() > 0 ? medias.toArray( new Media[medias.size() ] ) : null;
}
if (category == PageRanges.class) {
if (flavor == null|| flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE)
|| flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {
PageRanges[] arr = new PageRanges[1];
arr[0] = new PageRanges(1, Integer.MAX_VALUE);
return arr;
} else {
return null;
}
}
if (category == Fidelity.class) {
return new Fidelity[]{ Fidelity.FIDELITY_FALSE, Fidelity.FIDELITY_TRUE};
}
if (category == PrintQuality.class) {
return new PrintQuality[]{ PrintQuality.DRAFT, PrintQuality.HIGH, PrintQuality.NORMAL };
}
boolean printPageAble = flavor == null|| flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE)
|| flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE);
if (category == Sides.class) {
if ( printPageAble ) {
return new Sides[]{ Sides.ONE_SIDED, Sides.TWO_SIDED_LONG_EDGE, Sides.TWO_SIDED_SHORT_EDGE};
} else {
return null;
}
}
if (category == SheetCollate.class) {
if ( printPageAble ) {
return new SheetCollate[]{ SheetCollate.COLLATED, SheetCollate.UNCOLLATED} ;
} else {
return null;
}
}
boolean imageBased = printPageAble || flavor.equals(DocFlavor.INPUT_STREAM.GIF)
|| flavor.equals(DocFlavor.INPUT_STREAM.JPEG)
|| flavor.equals(DocFlavor.INPUT_STREAM.PNG)
|| flavor.equals(DocFlavor.BYTE_ARRAY.GIF)
|| flavor.equals(DocFlavor.BYTE_ARRAY.JPEG)
|| flavor.equals(DocFlavor.BYTE_ARRAY.PNG)
|| flavor.equals(DocFlavor.URL.GIF)
|| flavor.equals(DocFlavor.URL.JPEG)
|| flavor.equals(DocFlavor.URL.PNG);
if (category == OrientationRequested.class) {
if( imageBased ){
return new OrientationRequested[]{ OrientationRequested.PORTRAIT, OrientationRequested.LANDSCAPE, OrientationRequested.REVERSE_LANDSCAPE };
} else {
return null;
}
}
if (category == Chromaticity.class) {
if( imageBased ){
if( settings.get_DefaultPageSettings().get_Color() ){
return new Chromaticity[]{ Chromaticity.MONOCHROME, Chromaticity.COLOR };
} else {
return new Chromaticity[]{ Chromaticity.MONOCHROME };
}
} else {
return null;
}
}
return null;
}
private MediaTray[] getMediaTrays(){
if( mediaTrays != null ){
// the print service is a singleton per printer so we only do this once
return mediaTrays;
}
PaperSourceCollection trays = settings.get_PaperSources();
int count = trays.get_Count();
List<MediaTray> trayList = new ArrayList<MediaTray>();
for( int i=0; i < count; i++ ){
PaperSource tray = trays.get_Item(i);
MediaTray javaTray = getDefaultTray(tray);
if( javaTray != null ){
trayList.add( javaTray );
} else {
trayList.add( new NetMediaTray( tray ) );
}
}
mediaTrays = trayList.toArray( new MediaTray[trayList.size()]);
return mediaTrays;
}
@Override
public DocFlavor[] getSupportedDocFlavors(){
int len = supportedFlavors.length;
DocFlavor[] result = new DocFlavor[len];
System.arraycopy(supportedFlavors, 0, result, 0, len);
return result;
}
@Override
public AttributeSet getUnsupportedAttributes(DocFlavor flavor, AttributeSet attributes){
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isAttributeCategorySupported(Class<? extends Attribute> category){
if ( category == null || !Attribute.class.isAssignableFrom( category ) ) {
throw new IllegalArgumentException( "The category '" + category + "' is not an Attribute" );
}
Class<?>[] supported = getSupportedAttributeCategories();
for( int i=0; i < supported.length; i++ ){
if( category == supported[i] ){
return true;
}
}
return false;
}
@Override
public boolean isAttributeValueSupported(Attribute attrval, DocFlavor flavor, AttributeSet attributes){
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isDocFlavorSupported(DocFlavor flavor){
for (int f=0; f<supportedFlavors.length; f++) {
if (flavor.equals(supportedFlavors[f])) {
return true;
}
}
return false;
}
@Override
public String toString(){
return "Win32 Printer : " + getName();
}
@Override
public boolean equals(Object obj){
return (obj == this || (obj instanceof Win32PrintService && ((Win32PrintService)obj).getName()
.equals(getName())));
}
@Override
public int hashCode(){
return this.getClass().hashCode() + getName().hashCode();
}
/**
* Tries to find a matching {@link MediaSizeName} for a paper by it's size
* @param paper
* @return
*/
private MediaSizeName findMatchingMedia( PaperSize paper ){
if( paper.get_RawKind() > 0 && paper.get_RawKind() <= MEDIA_NAMES.length ){
// match to predefined size
return MEDIA_NAMES[ paper.get_RawKind() - 1 ];
}
int x = paper.get_Width() * INCH100_TO_MYM;
int y = paper.get_Height() * INCH100_TO_MYM;
if( x > y ){ // MediaSizes are always portrait!
int tmp = x;
x = y;
y = tmp;
}
for( MediaSizeName name : MEDIA_NAMES ){
MediaSize media = MediaSize.getMediaSizeForName(name);
if( media != null ){
if( Math.abs( x - media.getX(1) ) < MATCH_DIFF && Math.abs( y - media.getY(1) ) < MATCH_DIFF ){
return name;
}
}
}
return null;
}
/**
* Returns the Java-default {@link MediaTray} for a paper source. This is required since these default
* trays are public constants which can be used without checking for the actually present media trays
* @param source the .NET paper source to get the predefined source for
* @return the media tray or null, in case there is no mapping for the paper source
*/
private MediaTray getDefaultTray( PaperSource source ){
// convert from .NET kind to java's pre defined MediaTrays
switch( source.get_RawKind() ){
case 1 : return MediaTray.TOP;
case 2 : return MediaTray.BOTTOM;
case 3 : return MediaTray.MIDDLE;
case 4 : return MediaTray.MANUAL;
case 5 : return MediaTray.ENVELOPE;
case 6 : return Win32MediaTray.ENVELOPE_MANUAL;
case 7 : return Win32MediaTray.AUTO;
case 8 : return Win32MediaTray.TRACTOR;
case 9 : return Win32MediaTray.SMALL_FORMAT;
case 10 : return Win32MediaTray.LARGE_FORMAT;
case 11 : return MediaTray.LARGE_CAPACITY;
case 14 : return MediaTray.MAIN;
case 15 : return Win32MediaTray.FORMSOURCE;
// FIXME which PaperSourceKind is MediaTray.SIDE ???
}
return null;
}
/**
* Returns the .NET {@link PaperSource} for a media tray. This will be done either by mapping or
* directly in case the tray is a {@link NetMediaTray}
* @param tray the tray to get the paper source for, must not be null
* @return the selected {@link PaperSource} or null, in case there is no matching {@link PaperSource}
*/
public PaperSource getPaperSourceForTray( MediaTray tray ){
if( tray instanceof NetMediaTray ){
return ((NetMediaTray)tray).getPaperSource( this );
}
// try to find the appropriate paper source for the Java-Defined tray
PaperSourceCollection trays = settings.get_PaperSources();
int count = trays.get_Count();
for( int i=0; i < count; i++ ){
PaperSource paperSource = trays.get_Item(i);
if( getDefaultTray( paperSource ) == tray ){
return paperSource;
}
}
return null;
}
public static class NetMediaTray extends MediaTray{
private static final long serialVersionUID = 1L;
/** Not really used but required by the EnumSyntax super class */
private static AtomicInteger idCounter = new AtomicInteger(8);
private int rawKind;
private String name;
private transient PaperSource netSource;
public NetMediaTray( PaperSource netSource ) {
super( idCounter.getAndIncrement() );
this.rawKind = netSource.get_RawKind();
this.name = netSource.get_SourceName();
this.netSource = netSource;
}
public PaperSource getPaperSource( Win32PrintService service ){
if( netSource == null ){
PaperSourceCollection sources = service.settings.get_PaperSources();
int count = sources.get_Count();
for( int i=0; i < count; i++ ){
PaperSource source = sources.get_Item(i);
if( source.get_RawKind() == rawKind ){
netSource = source;
break;
}
}
}
return netSource;
}
@Override
public String toString() {
return netSource != null ? netSource.get_SourceName() : name;
}
}
}