001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Aleksei V. Ivaschenko
019: * @version $Revision: 1.3 $
020: */package org.apache.harmony.x.print.awt;
021:
022: import java.awt.Dialog;
023: import java.awt.Frame;
024: import java.awt.GraphicsEnvironment;
025: import java.awt.HeadlessException;
026: import java.awt.KeyboardFocusManager;
027: import java.awt.Rectangle;
028: import java.awt.Window;
029: import java.awt.print.PageFormat;
030: import java.awt.print.Pageable;
031: import java.awt.print.Paper;
032: import java.awt.print.Printable;
033: import java.awt.print.PrinterException;
034: import java.awt.print.PrinterJob;
035: import java.io.PrintStream;
036: import java.security.AccessController;
037: import java.security.PrivilegedAction;
038: import java.util.Locale;
039:
040: import javax.print.Doc;
041: import javax.print.DocFlavor;
042: import javax.print.DocPrintJob;
043: import javax.print.PrintException;
044: import javax.print.PrintService;
045: import javax.print.PrintServiceLookup;
046: import javax.print.ServiceUI;
047: import javax.print.SimpleDoc;
048: import javax.print.attribute.HashPrintRequestAttributeSet;
049: import javax.print.attribute.PrintRequestAttributeSet;
050: import javax.print.attribute.Size2DSyntax;
051: import javax.print.attribute.standard.Copies;
052: import javax.print.attribute.standard.JobName;
053: import javax.print.attribute.standard.Media;
054: import javax.print.attribute.standard.MediaPrintableArea;
055: import javax.print.attribute.standard.MediaSize;
056: import javax.print.attribute.standard.MediaSizeName;
057: import javax.print.attribute.standard.OrientationRequested;
058: import javax.print.attribute.standard.RequestingUserName;
059: import javax.swing.JOptionPane;
060:
061: import org.apache.harmony.x.print.ServiceUIDialog;
062: import org.apache.harmony.x.print.attributes.MediaMargins;
063:
064: public class PSPrinterJob extends PrinterJob {
065:
066: private Printable psPrintable;
067: private Pageable psDocument;
068: private PageFormat psFormat;
069: private PrintStream stream;
070:
071: PrintRequestAttributeSet attrs; // Job attributes
072: private PrintService service = null; // Job print service
073:
074: static String os = null; // OS type
075:
076: static {
077: AccessController.doPrivileged(new PrivilegedAction() {
078: public Object run() {
079: os = System.getProperty("os.name");
080: if (os.startsWith("Windows")) {
081: System.loadLibrary("print");
082: }
083: return null;
084: }
085: });
086: }
087:
088: public PSPrinterJob() {
089: super ();
090: attrs = new HashPrintRequestAttributeSet();
091: service = PrintServiceLookup.lookupDefaultPrintService();
092: /* Probably need to add default attributes to attrs here */
093: }
094:
095: public void setPrintable(Printable painter) {
096: psPrintable = painter;
097: }
098:
099: /*
100: * @see java.awt.print.PrinterJob#setPrintable(Printable, PageFormat)
101: */
102: public void setPrintable(Printable painter, PageFormat format) {
103: psPrintable = painter;
104: psFormat = format;
105: }
106:
107: /*
108: * @see java.awt.print.PrinterJob#setPageable(Pageable)
109: */
110: public void setPageable(Pageable document)
111: throws NullPointerException {
112: if (document == null) {
113: throw new NullPointerException("Pageable argument is null");
114: }
115: psDocument = document;
116: }
117:
118: /*
119: * @see java.awt.print.PrinterJob#print()
120: */
121: public void print() throws PrinterException {
122: Doc doc = null;
123: if (psPrintable != null) {
124: Pageable pageable = new Pageable() {
125: public int getNumberOfPages() {
126: return UNKNOWN_NUMBER_OF_PAGES;
127: }
128:
129: public PageFormat getPageFormat(int pageIndex)
130: throws IndexOutOfBoundsException {
131: return (psFormat != null) ? psFormat
132: : defaultPage();
133: }
134:
135: public Printable getPrintable(int pageIndex)
136: throws IndexOutOfBoundsException {
137: return psPrintable;
138: }
139: };
140:
141: doc = new SimpleDoc(pageable,
142: DocFlavor.SERVICE_FORMATTED.PAGEABLE, null);
143: } else if (psDocument != null) {
144: doc = new SimpleDoc(psDocument,
145: DocFlavor.SERVICE_FORMATTED.PAGEABLE, null);
146: } else {
147: throw new PrinterException(
148: "Neither Printable nor Pageable were "
149: + "specified.");
150: }
151:
152: PrintService pService = service;
153: if (pService == null) {
154: pService = PrintServiceLookup.lookupDefaultPrintService();
155: }
156:
157: try {
158: DocPrintJob job = pService.createPrintJob();
159: job.print(doc, attrs);
160: } catch (PrintException pe) {
161: throw new PrinterException(pe.getMessage());
162: }
163: }
164:
165: /*
166: * @see java.awt.print.PrinterJob#print(PrintRequestAttributeSet)
167: */
168: public void print(PrintRequestAttributeSet attributes)
169: throws PrinterException {
170: attrs = attributes;
171: print();
172: }
173:
174: public PrintService getPrintService() {
175: return service;
176: }
177:
178: public void setPrintService(PrintService printservice)
179: throws PrinterException {
180: if (printservice
181: .isDocFlavorSupported(DocFlavor.SERVICE_FORMATTED.PRINTABLE)
182: && printservice
183: .isDocFlavorSupported(DocFlavor.SERVICE_FORMATTED.PAGEABLE)) {
184: service = printservice;
185: } else {
186: throw new PrinterException("PrintService doesn't support "
187: + "SERVICE_FORMATTED doc flavors.");
188: }
189: }
190:
191: public void setJobName(String jobName) {
192: attrs.add(new JobName(jobName, Locale.getDefault()));
193: }
194:
195: public void setCopies(int copies) {
196: attrs.add(new Copies(copies));
197: }
198:
199: public int getCopies() {
200: return attrs.containsKey(Copies.class) ? ((Copies) (attrs
201: .get(Copies.class))).getValue() : 1;
202: }
203:
204: public String getUserName() {
205: return attrs.containsKey(RequestingUserName.class) ? ((RequestingUserName) (attrs
206: .get(RequestingUserName.class))).getValue()
207: : null;
208: }
209:
210: public String getJobName() {
211: return attrs.containsKey(JobName.class) ? ((JobName) (attrs
212: .get(JobName.class))).getValue() : null;
213: }
214:
215: /*
216: * This method shows Windows native print dialog on Windows and
217: * javax.print.ServiceUI standard print dialog on Linux. We suppose that on
218: * Linux this dialog should contain the list of native print services only,
219: * however corresponding native agent function is not realized yet.
220: *
221: * Throws HeadlessException if Graphics Environment is headless.
222: */
223: public boolean printDialog() throws HeadlessException {
224: if (GraphicsEnvironment.isHeadless()) {
225: throw new HeadlessException();
226: }
227:
228: if (os.startsWith("Windows")) { /* Windows OS */
229:
230: /* call Windows native dialog */
231: String res = getPrinter(service.getName(), getCopies());
232:
233: if (res != null) {
234: try {
235: setPrintService(findPrintService(res));
236: return true;
237: } catch (PrinterException e) {
238: JOptionPane.showMessageDialog(KeyboardFocusManager
239: .getCurrentKeyboardFocusManager()
240: .getActiveWindow(),
241: "Can not set selected printer!",
242: "Incorrect service",
243: JOptionPane.ERROR_MESSAGE);
244: }
245: }
246: return false;
247: }
248: /* Linux OS */
249: /*
250: * TODO: Need to create new native agent function which returns
251: * a list of native printers. Need to call javax.print.ServiceUI
252: * print dialog with this native printers list instead of all
253: * registered print services list as it is realized here!
254: */
255: printDialog(attrs);
256: return false;
257: }
258:
259: /*
260: * Calls cross-platforms print dialog with all registered print services
261: * (this function just calls ServiceUI.printDialog(...) method with
262: * corresponding parameters).
263: *
264: * Parameters:
265: * attrs - attributes for the dialog
266: *
267: * Throws:
268: * NullPointerException - if attrs is null
269: * HeadlessException - if Graphics Environment is headless
270: */
271: public boolean printDialog(PrintRequestAttributeSet dialogAttrs)
272: throws HeadlessException {
273:
274: if (dialogAttrs == null) {
275: throw new NullPointerException();
276: } else if (GraphicsEnvironment.isHeadless()) {
277: throw new HeadlessException();
278: }
279:
280: /* Combine this PrinterJob attrs attribute set and printerAttrs set
281: and resolve MediaPrintableArea/MediaMargins conflict if it is
282: needed */
283: PrintRequestAttributeSet sum = updateMediaAndMarginsIfNeeded(dialogAttrs);
284:
285: Rectangle screen = GraphicsEnvironment
286: .getLocalGraphicsEnvironment().getDefaultScreenDevice()
287: .getDefaultConfiguration().getBounds();
288:
289: /* call cross-platform print dialog */
290: PrintService newSrv = ServiceUI.printDialog(null,
291: screen.width / 3, screen.height / 3,
292: lookupServicesForDialog(), service,
293: DocFlavor.SERVICE_FORMATTED.PRINTABLE, sum);
294:
295: if (newSrv != null) {
296: /* Set selected print service and update attrs attribute set
297: if user clicked "Print" button */
298: try {
299: setPrintService(newSrv);
300: this .attrs.clear();
301: this .attrs.addAll(sum);
302: return true;
303: } catch (PrinterException e) {
304: System.out.println(e);
305: return false;
306: }
307: }
308: return false; /* "Cancel button was pressed */
309: }
310:
311: /*
312: * This method calls standard page dialog that allows PageFormat
313: * modification.
314: * Parameters:
315: * page - PageFormat for modification
316: * Returns:
317: * original page if the dialog is cancelled or print service for the
318: * job is not set
319: * new PageFormat object from the dialog if the user click "Print"
320: * button
321: * Throws HeadlessException if Graphics Environment is headless.
322: */
323: public PageFormat pageDialog(PageFormat page)
324: throws HeadlessException {
325: if (getPrintService() == null) {
326: return page;
327: }
328:
329: /* get attribute set which combines this job attribute set and
330: attributes for the given page PageFormat */
331: HashPrintRequestAttributeSet myattrs = getAttrsForPageFormat(page);
332: return pageDialog(myattrs);
333: }
334:
335: /*
336: * This method calls standard page dialog with the given attribute set
337: * Parameters:
338: * attrs - attribute set for the dialog
339: * Returns:
340: * original page if the dialog is cancelled or print service for the
341: * job is not set
342: * new PageFormat object from the dialog if the user click "Print"
343: * button
344: * Throws:
345: * HeadlessException if Graphics Environment is headless.
346: * NullPointerException if attrs is null
347: */
348: public PageFormat pageDialog(PrintRequestAttributeSet arg_attrs)
349: throws HeadlessException {
350:
351: if (GraphicsEnvironment.isHeadless()) {
352: throw new HeadlessException();
353: } else if (arg_attrs == null) {
354: throw new NullPointerException();
355: } else if (getPrintService() == null) {
356: JOptionPane.showMessageDialog(
357: KeyboardFocusManager
358: .getCurrentKeyboardFocusManager()
359: .getActiveWindow(),
360: "Print service is not set for the PrinterJob!",
361: "Error!", JOptionPane.ERROR_MESSAGE);
362: return null;
363: }
364:
365: Window wnd = KeyboardFocusManager
366: .getCurrentKeyboardFocusManager().getActiveWindow();
367: Window owner = (((wnd instanceof Dialog) || (wnd instanceof Frame)) ? wnd
368: : new Frame());
369:
370: /* Combine this PrinterJob this.attrs attribute set and attrs set
371: and resolve MediaPrintableArea/MediaMargins conflict if it is
372: needed */
373: PrintRequestAttributeSet sum = updateMediaAndMarginsIfNeeded(arg_attrs);
374:
375: Rectangle screen = GraphicsEnvironment
376: .getLocalGraphicsEnvironment().getDefaultScreenDevice()
377: .getDefaultConfiguration().getBounds();
378:
379: /* create and show the page dialog */
380: ServiceUIDialog dialog = new ServiceUIDialog(null,
381: screen.width / 3, screen.height / 3, getPrintService(),
382: sum, owner);
383: dialog.show();
384:
385: if (owner != wnd) {
386: owner.dispose();
387: }
388:
389: /* update this.attrs attribute set and result page format to return */
390: if (dialog.getResult() == ServiceUIDialog.APPROVE_PRINT) {
391: PrintRequestAttributeSet newattrs = dialog.getAttributes();
392:
393: if (!newattrs.containsKey(Media.class)) {
394: this .attrs.remove(Media.class);
395: }
396: if (!newattrs.containsKey(OrientationRequested.class)) {
397: this .attrs.remove(OrientationRequested.class);
398: }
399: if (!newattrs.containsKey(MediaPrintableArea.class)) {
400: this .attrs.remove(MediaPrintableArea.class);
401: }
402: if (!newattrs.containsKey(MediaMargins.class)) {
403: this .attrs.remove(MediaMargins.class);
404: }
405: this .attrs.addAll(newattrs);
406: return getPageFormatForAttrs(newattrs);
407: }
408:
409: return null;
410:
411: }
412:
413: /*
414: * Returns this printer job's attribute set
415: */
416: public PrintRequestAttributeSet getAttributes() {
417: return attrs;
418: }
419:
420: /*
421: * Native method which calls Windows java native dialog.
422: * This method add/update Copies attribute into the attr attribute set
423: * and set new selected printer if user clicked OK.
424: * It does not change any other PrinterJob attributes now.
425: * TODO: wtite new Windows native agent function which save dialog DEVMODE
426: * structure and returns correct attribute set for it.
427: */
428: native String getPrinter(String defaultPrinter, int copies);
429:
430: public PageFormat defaultPage(PageFormat page) {
431: attrs.addAll(getAttrsForPageFormat(page));
432: return getPageFormatForAttrs(attrs);
433: }
434:
435: // ---------------------------------------------------------------
436:
437: /*
438: * Returns PrintRequestAttributeSet which corresponds to given page
439: * PageFormat. We always adds MediaMArgins (not MediaPrintableArea)
440: * attribute for the result attribute set.
441: */
442: protected HashPrintRequestAttributeSet getAttrsForPageFormat(
443: PageFormat page) {
444:
445: HashPrintRequestAttributeSet lattrs = new HashPrintRequestAttributeSet();
446:
447: /* Add Orientation attribute */
448: switch (page.getOrientation()) {
449: case PageFormat.LANDSCAPE:
450: lattrs.add(OrientationRequested.LANDSCAPE);
451: break;
452: case PageFormat.PORTRAIT:
453: lattrs.add(OrientationRequested.PORTRAIT);
454: break;
455: case PageFormat.REVERSE_LANDSCAPE:
456: lattrs.add(OrientationRequested.REVERSE_LANDSCAPE);
457: break;
458: }
459:
460: /* Add Media attribute */
461: MediaSizeName media = MediaSize.findMedia((float) (page
462: .getWidth() / 72.0), (float) (page.getHeight() / 72.0),
463: Size2DSyntax.INCH);
464: if (media != null) {
465: lattrs.add(media);
466: }
467:
468: /* Add MediaMargins attribute */
469: lattrs.add(new MediaMargins(
470: (float) (page.getImageableX() / 72.0), (float) (page
471: .getImageableY() / 72.0), (float) ((page
472: .getWidth()
473: - page.getImageableX() - page
474: .getImageableWidth()) / 72.0), (float) ((page
475: .getHeight()
476: - page.getImageableHeight() - page
477: .getImageableY()) / 72.0), MediaMargins.INCH));
478:
479: return lattrs;
480: }
481:
482: /*
483: * Returns PageFormat object which corresponds to the given newattrs
484: * attribute set.
485: */
486: protected PageFormat getPageFormatForAttrs(
487: PrintRequestAttributeSet newattrs) {
488:
489: PageFormat pf = new PageFormat();
490:
491: if (newattrs.containsKey(OrientationRequested.class)) {
492: OrientationRequested or = (OrientationRequested) newattrs
493: .get(OrientationRequested.class);
494: pf
495: .setOrientation(or
496: .equals(OrientationRequested.LANDSCAPE) ? PageFormat.LANDSCAPE
497: : (or
498: .equals(OrientationRequested.REVERSE_LANDSCAPE) ? PageFormat.REVERSE_LANDSCAPE
499: : PageFormat.PORTRAIT));
500: }
501:
502: Paper paper = new Paper();
503: MediaSize size = MediaSize
504: .getMediaSizeForName(newattrs.containsKey(Media.class)
505: && (newattrs.get(Media.class).getClass()
506: .isAssignableFrom(MediaSizeName.class)) ? (MediaSizeName) newattrs
507: .get(Media.class)
508: : MediaSizeName.ISO_A4);
509: paper.setSize(size.getX(Size2DSyntax.INCH) * 72.0, size
510: .getY(Size2DSyntax.INCH) * 72.0);
511:
512: MediaMargins mm;
513: if (newattrs.containsKey(MediaMargins.class)) {
514: mm = (MediaMargins) newattrs.get(MediaMargins.class);
515: } else if (newattrs.containsKey(MediaPrintableArea.class)) {
516: mm = new MediaMargins(size, (MediaPrintableArea) attrs
517: .get(MediaPrintableArea.class));
518: } else {
519: mm = new MediaMargins(25.4F, 25.4F, 25.4F, 25.4F,
520: MediaMargins.MM);
521: }
522: paper.setImageableArea(mm.getX1(MediaMargins.INCH) * 72.0, mm
523: .getY1(MediaMargins.INCH) * 72.0, (size
524: .getX(Size2DSyntax.INCH)
525: - mm.getX1(MediaMargins.INCH) - mm
526: .getX2(MediaMargins.INCH)) * 72.0, (size
527: .getY(Size2DSyntax.INCH)
528: - mm.getY1(MediaMargins.INCH) - mm
529: .getY2(MediaMargins.INCH)) * 72.0);
530: pf.setPaper(paper);
531: return pf;
532: }
533:
534: /*
535: * Find PrintService with the given name
536: */
537: protected PrintService findPrintService(String name) {
538: PrintService srvs[] = PrintServiceLookup.lookupPrintServices(
539: null, null);
540: if (srvs != null) {
541: for (int i = 0; i < srvs.length; i++) {
542: if (srvs[i].getName().equals(name)) {
543: return srvs[i];
544: }
545: }
546: }
547: return null;
548: }
549:
550: /*
551: * This method returns all registered PrintServices list if this list
552: * contains this printer job's print service.
553: * If this list does not contain this job's print service, this function
554: * returns new print services list which contains all registered services
555: * plus this jib's service.
556: */
557: protected PrintService[] lookupServicesForDialog() {
558: PrintService[] services = lookupPrintServices();
559: if (services != null) {
560: for (int i = 0; i < services.length; i++) {
561: if (services[i].equals(service)) {
562: return services;
563: }
564: }
565: PrintService[] ret = new PrintService[services.length + 1];
566: for (int i = 0; i < services.length; i++) {
567: ret[i] = services[i];
568: }
569: ret[services.length] = service;
570: return ret;
571: }
572:
573: return new PrintService[] { service };
574:
575: }
576:
577: /*
578: * This method adds newAttrs attributes to this.attrs attribute set. If
579: * newAttrs contains MediaMargins or MediaPrintableAttribute, result
580: * attribute set must not contain MediaPrintableArea or MediaMargins from
581: * this.attrs attribute set because of the possible conflict.
582: */
583: protected PrintRequestAttributeSet updateMediaAndMarginsIfNeeded(
584: PrintRequestAttributeSet newAttrs) {
585:
586: /* create copy of this.attrs*/
587: PrintRequestAttributeSet sum = new HashPrintRequestAttributeSet(
588: this .attrs);
589:
590: /* remove MediaMargins and MediaPrintableArea attributes from the copy
591: of job attributes if newAttrs contains MediaMargins or
592: PrintableArea */
593: if (newAttrs.containsKey(MediaPrintableArea.class)
594: || attrs.containsKey(MediaMargins.class)) {
595: sum.remove(MediaPrintableArea.class);
596: sum.remove(MediaMargins.class);
597: }
598:
599: sum.addAll(newAttrs);
600: return sum;
601: }
602:
603: /*
604: * TODO: Need to implement this methods
605: */
606: public void cancel() {
607: /* */
608: }
609:
610: public boolean isCancelled() {
611: return false;
612: }
613:
614: public PageFormat validatePage(PageFormat page) {
615: return null;
616: }
617:
618: }
|