/* ========================
* JSynoptic : a free Synoptic editor
* ========================
*
* Project Info: http://jsynoptic.sourceforge.net/index.html
*
* This program is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* (C) Copyright 2001-2006, by :
* Corporate:
* EADS Astrium SAS
* EADS CRC
* Individual:
* Claude Cazenave
*
* $Id: PrintFormat.java,v 1.8 2007/06/29 16:29:04 ogor Exp $
*
* Changes
* -------
* 06 dec 2006 : Initial public release (CC);
*
*/
package jsynoptic.base;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Pageable;
import java.awt.print.Paper;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ResourceBundle;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import javax.print.PrintService;
import javax.print.StreamPrintService;
import javax.print.StreamPrintServiceFactory;
import simtools.diagram.DiagramComponent;
import simtools.diagram.DiagramParameters;
import simtools.ui.CustomizedLocale;
import simtools.ui.MenuResourceBundle;
/**
* A base class for printing synoptics.
* It manages 3 printing modes :
* to printer
* to file using postscript printing
* to image
* Paper size and orientation is taken into account for all these 3 modes
*
* @author cazenave_c
*
*/
public class PrintFormat {
static MenuResourceBundle resources;
static HashMap papers = null;
protected static HashMap formatsMap;
static {
// paper sizes look up
try {
resources = (MenuResourceBundle) ResourceBundle.getBundle(
"simtools.ui.resources.PrintDialogResources",
CustomizedLocale.get()
);
} catch (Exception e) {
System.err.println("Can't load PrintDialog resources");
System.exit(0);
}
papers = new HashMap();
int paperNumber = resources.getIntValue("paperNumber");
for (int i=0; i<paperNumber; i++) {
String name = resources.getStringValue("paper"+i+"Name");
Paper p = new Paper();
p.setSize(
resources.getDoubleValue("paper"+i+"Width"),
resources.getDoubleValue("paper"+i+"Height")
);
p.setImageableArea(
resources.getDoubleValue("paper"+i+"ImageableX"),
resources.getDoubleValue("paper"+i+"ImageableY"),
resources.getDoubleValue("paper"+i+"ImageableWidth"),
resources.getDoubleValue("paper"+i+"ImageableHeight")
);
papers.put(name, p);
}
// image file formats look up
formatsMap=new HashMap();
String[] formats=ImageIO.getWriterFormatNames();
for(int i=0;i<formats.length;i++){
Iterator it=ImageIO.getImageWritersByFormatName(formats[i]);
ImageWriter iw=(ImageWriter)it.next();
String[] suff=iw.getOriginatingProvider().getFileSuffixes();
for(int j=0;j<suff.length;j++){
if(!formatsMap.containsKey(suff[j])){
formatsMap.put(suff[j], formats[i]);
}
}
}
}
public static final int PRINTER_MODE=1;
public static final int PRINTER_FILE_MODE=2;
public static final int IMAGE_FILE_MODE=3;
protected PageFormat pageFormat;
/**
* Default prining context is A4 landscape
*/
public PrintFormat() {
pageFormat = new PageFormat();
// Sets the defaults
setPaper("A4");
pageFormat.setOrientation(PageFormat.LANDSCAPE);
}
/**
* Get known papers
* @return
*/
public String[] getKnownPapers(){
String[] res=new String[papers.size()];
papers.keySet().toArray(res);
return res;
}
/**
* Set paper name
* @param paperName (A4, A3, ...)
* @return
*/
public boolean setPaper(String paperName) {
Paper p=(Paper)papers.get(paperName);
if (p==null) return false;
pageFormat.setPaper(p);
return true;
}
/**
* Set paper orientation
* @param orientation: can be either a PORTRAIT, a LANDSCAPE or a REVERSE_LANDSCAPE
* @return true if set orientation was successful
*/
public boolean setOrientation(String orientation){
boolean orientationHasBeenSet = true;
if (orientation.equals("portrait"))
pageFormat.setOrientation(PageFormat.PORTRAIT);
else if (orientation.equals("landscape"))
pageFormat.setOrientation(PageFormat.LANDSCAPE);
else if (orientation.equals("reverseLandscape"))
pageFormat.setOrientation(PageFormat.REVERSE_LANDSCAPE);
else
orientationHasBeenSet=false;
return orientationHasBeenSet;
}
/**
* Get paper size
* @return
*/
public PageFormat getFormat() {
return pageFormat;
}
/**
* Printing generic exception
*/
public class PrintException extends Exception{
public PrintException(String message, Throwable cause){
super(message, cause);
}
}
/**
* @param comp
* @param mode
* @param dest
* @throws PrintException
*/
public void print(DiagramComponent comp, int mode, String dest) throws PrintException{
switch(mode){
case IMAGE_FILE_MODE:
try{
// Get a full path for destination file
dest = new File(dest).getCanonicalPath();
printImage(new File(dest), comp);
}catch(IOException e){
throw new PrintException("cannotExport", e);
}
break;
case PRINTER_FILE_MODE:
StreamPrintService psPrinter = null;
String psMimeType = "application/postscript";
StreamPrintServiceFactory[] factories =
PrinterJob.lookupStreamPrintServices(psMimeType);
if (factories.length<1) {
throw new PrintException("noPSService", null);
}
FileOutputStream fos = null;
try {
// Get a full path for destination file
dest = new File(dest).getCanonicalPath();
fos = new FileOutputStream(dest);
psPrinter = factories[0].getPrintService(fos);
} catch (Exception e) {
throw new PrintException("cannotPrintToFile", e);
}
printPrinter(psPrinter, comp);
psPrinter.dispose();
try {
fos.close();
} catch (Exception e2) {
throw new PrintException("cannotPrintToFile", e2);
}
break;
case PRINTER_MODE:
PrintService[] services = PrinterJob.lookupPrintServices();
if (services.length<1) {
throw new PrintException("noPrinter", null);
}
PrintService ps = null;
if(dest!=null){
for (int i=0; i<services.length; ++i) {
if (services[i].getName().equals(dest)) {
ps = services[i];
break;
}
}
if (ps==null) {
throw new PrintException("noPrinter", null);
}
}
else{
ps = services[0];
}
printPrinter(ps, comp);
break;
default:
throw new IllegalArgumentException();
}
}
/**
* Printing to a printer or a postscipt file
* @param ps
* @param comp
* @throws PrintException
*/
public void printPrinter(PrintService ps, final DiagramComponent comp) throws PrintException{
if (ps==null) {
throw new PrintException("noPrinter", null);
}
PrinterJob pj = PrinterJob.getPrinterJob();
try {
pj.setPrintService(ps);
}
catch (PrinterException pe) {
throw new PrintException("invalidPrinter", null);
}
pj.setPageable(new Pageable(){
public int getNumberOfPages() {
return 1;
}
public PageFormat getPageFormat(int pageIndex) throws IndexOutOfBoundsException {
return pageFormat;
}
public Printable getPrintable(int pageIndex) throws IndexOutOfBoundsException {
return comp;
}
});
try {
pj.print();
} catch (PrinterException pe2) {
throw new PrintException("printFailed",pe2);
}
}
/**
* Printing to an image
* @param f
* @param comp
* @throws PrintException
*/
protected void printImage(File f, DiagramComponent comp) throws PrintException, IOException{
int kext=f.getName().lastIndexOf(".");
String format=null;
if(kext>0){
String ext=f.getName().substring(kext+1);
format=(String)formatsMap.get(ext);
}
if(format==null){
format="png";
}
// get paper size
double w=pageFormat.getImageableWidth();
double h=pageFormat.getImageableHeight();
// create image accordingly
BufferedImage bi=new BufferedImage((int)w,(int)h,BufferedImage.TYPE_3BYTE_BGR);
Graphics2D g2=bi.createGraphics();
AffineTransform t=g2.getTransform();
// get diagram size
Point pmax;
if (comp.isAutofit()){
pmax = comp.getDiagramMaxPoint(g2);
pmax.x+=comp.getXMargin();
pmax.y+=comp.getYMargin();
}else{
pmax = new Point();
pmax.x = comp.getSize().width + 2*comp.getXMargin();
pmax.y = comp.getSize().height+ 2*comp.getYMargin();
}
if(comp.hasHeader()){
pmax.y+=comp.getHeaderHeight() + DiagramParameters.HEADER_MARGIN;
}
// compute scale factor
double s;
s=Math.min(w/pmax.x, h/pmax.y);
// repaint with background
Color c=comp.getParameters().backgr;
if (c!=null)
g2.setColor(c);
else
g2.setColor(Color.WHITE);
g2.setTransform(t);
g2.fillRect(0,0,(int)w,(int)h);
// apply scale factor
g2.scale(s,s);
// draw the diagram
comp.printDiagram(g2);
// write the image
ImageIO.write(bi,format,f);
}
}