1 /* -----------------------------------------------------------------------
2 * Copyright 2014 Equinox Software, Inc.
3 * Bill Erickson <berick@esilibrary.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * -----------------------------------------------------------------------
16 package org.evergreen_ils.hatch;
19 import org.eclipse.jetty.util.log.Log;
20 import org.eclipse.jetty.util.log.Logger;
23 import javafx.print.*;
24 import javafx.scene.web.WebEngine;
25 import javafx.collections.ObservableSet;
26 import javafx.collections.SetChangeListener;
28 import javax.print.PrintService;
29 import javax.print.PrintServiceLookup;
30 import javax.print.attribute.Attribute;
31 import javax.print.attribute.AttributeSet;
32 import javax.print.attribute.PrintRequestAttributeSet;
33 import javax.print.attribute.standard.Media;
34 import javax.print.attribute.standard.OrientationRequested;
36 import java.lang.IllegalArgumentException;
40 import java.util.List;
41 import java.util.ArrayList;
42 import java.util.HashMap;
43 import java.util.LinkedList;
45 import java.util.LinkedHashSet;
47 public class PrintManager {
49 static final Logger logger = Log.getLogger("PrintManager");
51 public Map<String,Object> configurePrinter(
52 Map<String,Object> params) throws IllegalArgumentException {
54 Map<String,Object> settings =
55 (Map<String,Object>) params.get("config");
57 PrinterJob job = buildPrinterJob(settings);
59 job.showPrintDialog(null);
64 // extract modifications to the settings applied within the dialog
65 return extractSettingsFromJob(job);
68 public PrinterJob buildPrinterJob(
69 Map<String,Object> settings) throws IllegalArgumentException {
71 String name = (String) settings.get("printer");
72 Printer printer = getPrinterByName(name);
75 throw new IllegalArgumentException("No such printer: " + name);
77 PageLayout layout = buildPageLayout(settings, printer);
78 PrinterJob job = PrinterJob.createPrinterJob(printer);
80 if (layout != null) job.getJobSettings().setPageLayout(layout);
82 // apply any provided settings to the job
83 applySettingsToJob(settings, job);
88 protected PageLayout buildPageLayout(
89 Map<String,Object> settings, Printer printer) {
91 // modify the default page layout with our settings
92 Map<String,Object> layoutMap =
93 (Map<String,Object>) settings.get("pageLayout");
95 if (layoutMap == null) {
96 // Start with a sane default.
97 // The Java default is wonky
98 return printer.createPageLayout(
100 PageOrientation.PORTRAIT,
101 Printer.MarginType.DEFAULT
105 PrinterAttributes printerAttrs = printer.getPrinterAttributes();
107 // find the paper by name
109 String paperName = (String) layoutMap.get("paper");
110 Set<Paper> papers = printerAttrs.getSupportedPapers();
111 for (Paper source : papers) {
112 if (source.getName().equals(paperName)) {
113 logger.info("Found matching paper for " + paperName);
120 paper = printerAttrs.getDefaultPaper();
122 return printer.createPageLayout(
124 PageOrientation.valueOf((String) layoutMap.get("pageOrientation")),
125 ((Number) layoutMap.get("leftMargin")).doubleValue(),
126 ((Number) layoutMap.get("rightMargin")).doubleValue(),
127 ((Number) layoutMap.get("topMargin")).doubleValue(),
128 ((Number) layoutMap.get("bottomMargin")).doubleValue()
132 // applies the settings in settings to the provided print job
133 protected void applySettingsToJob(
134 Map<String,Object> settings, PrinterJob job) {
136 JobSettings jobSettings = job.getJobSettings();
138 PrinterAttributes printerAttrs =
139 job.getPrinter().getPrinterAttributes();
141 String collation = (String) settings.get("collation");
142 Long copies = (Long) settings.get("copies");
143 String printColor = (String) settings.get("printColor");
144 String printQuality = (String) settings.get("printQuality");
145 String printSides = (String) settings.get("printSides");
146 String paperSource = (String) settings.get("paperSource");
147 Object[] pageRanges = (Object[]) settings.get("pageRanges");
149 if (collation != null)
150 jobSettings.setCollation(Collation.valueOf(collation));
153 jobSettings.setCopies(((Long) settings.get("copies")).intValue());
155 if (printColor != null)
156 jobSettings.setPrintColor(PrintColor.valueOf(printColor));
158 if (printQuality != null)
159 jobSettings.setPrintQuality(PrintQuality.valueOf(printQuality));
161 if (printSides != null)
162 jobSettings.setPrintSides(PrintSides.valueOf(printSides));
164 // find the paperSource by name
165 if (paperSource != null) {
166 Set<PaperSource> paperSources =
167 printerAttrs.getSupportedPaperSources();
169 // note: "Automatic" appears to be a virtual source,
170 // meaning no source.. meaning let the printer decide.
171 for (PaperSource source : paperSources) {
172 if (source.getName().equals(paperSource)) {
173 logger.info("matched paper source for " + paperSource);
174 jobSettings.setPaperSource(source);
181 if (pageRanges != null) {
182 logger.info("pageRanges = " + pageRanges.toString());
183 List<PageRange> builtRanges = new LinkedList<PageRange>();
184 int i = 0, start = 0, end = 0;
186 if (i % 2 == 0 && i > 0)
187 builtRanges.add(new PageRange(start, end));
189 if (i == pageRanges.length) break;
191 int current = ((Long) pageRanges[i]).intValue();
192 if (i % 2 == 0) start = current; else end = current;
196 jobSettings.setPageRanges(builtRanges.toArray(new PageRange[0]));
201 public void print(WebEngine engine, Map<String,Object>params) {
203 //debugPrintService(null); // testing
206 Map<String,String> attrs =
207 (Map<String,String>) params.get("attributes");
209 String printerName = (String) attrs.get("printer-name");
210 PrintService service = getPrintServiceByName(printerName);
212 if (service == null) {
213 logger.warn("printer '" + printerName + "' not found!");
218 PrinterJob job = PrinterJob.createPrinterJob();
219 Attribute mediaAttr = getAttribute(
220 service, Media.class, (String) attrs.get("media"));
222 Attribute orientationAttr = getAttribute(
223 service, RequestedOrientation.class,
224 (String) attrs.get("orientation"));
226 PrintRequestAttributeSet attrSet = new PrintRequestAttributeSet();
227 if (mediaAttr != null) attrSet.add(mediaAttr);
228 if (orientationAttr != null) attrSet.add(orientationAttr);
232 //getPrinterByName(); ...
233 Printer printer = Printer.getDefaultPrinter(); // TODO
234 PageLayout firstLayout = printer.createPageLayout(
236 PageOrientation.LANDSCAPE,
237 0.1 * 72, 0.2 * 72, 0.3 * 72, 0.4 * 72
240 logger.info("orig job page layout " + firstLayout.toString());
241 PrinterJob job = PrinterJob.createPrinterJob(printer);
243 job.getJobSettings().setPageLayout(firstLayout);
244 if (!job.showPrintDialog(null)) return; // print canceled by user
246 Map<String,Object> settings = extractSettingsFromJob(job);
250 HatchWebSocketHandler socket =
251 (HatchWebSocketHandler) params.get("socket");
253 socket.reply(settings, (Long) params.get("msgid"));
256 protected Map<String,Object> extractSettingsFromJob(PrinterJob job) {
257 Map<String,Object> settings = new HashMap<String,Object>();
258 JobSettings jobSettings = job.getJobSettings();
261 jobSettings.collationProperty().getName(),
262 jobSettings.collationProperty().getValue()
265 jobSettings.copiesProperty().getName(),
266 jobSettings.copiesProperty().getValue()
270 jobSettings.getPaperSource().getName()
273 jobSettings.printColorProperty().getName(),
274 jobSettings.printColorProperty().getValue()
277 jobSettings.printQualityProperty().getName(),
278 jobSettings.printQualityProperty().getValue()
281 jobSettings.printSidesProperty().getName(),
282 jobSettings.printSidesProperty().getValue()
285 // nested properties...
287 // page layout --------------
288 PageLayout layout = jobSettings.getPageLayout();
289 Map<String,Object> layoutMap = new HashMap<String,Object>();
290 layoutMap.put("bottomMargin", layout.getBottomMargin());
291 layoutMap.put("leftMargin", layout.getLeftMargin());
292 layoutMap.put("topMargin", layout.getTopMargin());
293 layoutMap.put("rightMargin", layout.getRightMargin());
294 layoutMap.put("pageOrientation", layout.getPageOrientation().toString());
295 layoutMap.put("printableHeight", layout.getPrintableHeight());
296 layoutMap.put("printableWidth", layout.getPrintableWidth());
297 layoutMap.put("paper", layout.getPaper().getName());
299 settings.put("pageLayout", layoutMap);
301 // page ranges --------------
302 PageRange[] ranges = jobSettings.getPageRanges();
303 if (ranges != null) {
304 List<Integer> pageRanges = new LinkedList<Integer>();
306 if (ranges.length == 1 &&
307 ranges[0].getStartPage() == 1 &&
308 ranges[0].getEndPage() == Integer.MAX_VALUE) {
309 // full range -- no need to store
312 for (PageRange range : ranges) {
313 pageRanges.add(range.getStartPage());
314 pageRanges.add(range.getEndPage());
316 settings.put("pageRanges", pageRanges);
320 logger.info("compiled printer properties: " + settings.toString());
324 protected Printer[] getPrinters() {
325 ObservableSet<Printer> printerObserver = Printer.getAllPrinters();
327 if (printerObserver == null) return new Printer[0];
329 return (Printer[]) printerObserver.toArray(new Printer[0]);
332 protected List<Map<String,Object>> getPrintersAsMaps() {
333 Printer[] printers = getPrinters();
335 List<Map<String,Object>> printerMaps =
336 new LinkedList<Map<String,Object>>();
338 Printer defaultPrinter = Printer.getDefaultPrinter();
340 for (Printer printer : printers) {
341 HashMap<String, Object> printerMap = new HashMap<String, Object>();
342 printerMaps.add(printerMap);
343 printerMap.put("name", printer.getName());
344 if (printer.getName().equals(defaultPrinter.getName())) {
345 printerMap.put("is-default", new Boolean(true));
347 logger.info("found printer " + printer.getName());
354 protected Printer getPrinterByName(String name) {
355 Printer[] printers = getPrinters();
356 for (Printer printer : printers) {
357 if (printer.getName().equals(name))
364 private void debugPrintService(PrintService printer) {
366 PrintService[] printServices;
367 String defaultPrinter = "";
369 if (printer != null) {
370 printServices = new PrintService[] {printer};
372 printServices = PrintServiceLookup.lookupPrintServices(null, null);
373 PrintService def = PrintServiceLookup.lookupDefaultPrintService();
374 if (def != null) defaultPrinter = def.getName();
377 for (PrintService service : printServices) {
378 logger.info("Printer Debug: found printer " + service.getName());
379 if (service.getName().equals(defaultPrinter)) {
380 logger.info(" Printer Debug: Is Default");
383 AttributeSet attributes = service.getAttributes();
384 for (Attribute a : attributes.toArray()) {
385 String name = a.getName();
386 String value = attributes.get(a.getClass()).toString();
387 logger.info(" Printer Debug: " + name + " => " + value);
392 public PrintService getPrintServiceByName(String name) {
393 PrintService[] printServices =
394 PrintServiceLookup.lookupPrintServices(null, null);
395 for (PrintService service : printServices) {
396 if (service.getName().equals(name))
403 public List<HashMap> getPrinters() {
405 List<HashMap> printers = new LinkedList<HashMap>();
406 PrintService[] printServices =
407 PrintServiceLookup.lookupPrintServices(null, null);
409 String defaultPrinter = "";
410 PrintService def = PrintServiceLookup.lookupDefaultPrintService();
411 if (def != null) defaultPrinter = def.getName();
413 for (PrintService service : printServices) {
414 HashMap<String, Object> printer = new HashMap<String, Object>();
415 printers.add(printer);
417 if (service.getName().equals(defaultPrinter))
418 printer.put("is-default", new Boolean(true));
420 // collect information about the printer attributes we care about
421 Class[] attrClasses = {
423 //OrientationRequested.class
426 for (Class c : attrClasses) {
427 Attribute[] attrs = (Attribute[])
428 service.getSupportedAttributeValues(c, null, null);
430 if (attrs.length > 0) {
431 ArrayList<String> values = new ArrayList<String>(attrs.length);
432 for (Attribute a : attrs) {
433 String s = a.toString();
434 if (!values.contains(s)) values.add(s);
436 printer.put(attrs[0].getName(), values);
440 AttributeSet attributes = service.getAttributes();
441 for (Attribute a : attributes.toArray()) {
442 String name = a.getName();
443 String value = attributes.get(a.getClass()).toString();
444 printer.put(name, value);