/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.print;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Stroke;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Rectangle2D;
import java.awt.print.PageFormat;
import java.awt.print.Pageable;
import java.awt.print.Printable;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openflexo.utils.DrawUtils;
public class FlexoPrintableDelegate implements Printable, Pageable {
private static final Logger logger = Logger.getLogger(FlexoPrintableDelegate.class.getPackage().getName());
private enum PaintMode {
PREVIEW, PRINTING
};
private double scale = 1.0;
private double previewScale = 1.0;
private PageFormat _pageFormat;
private int _pageIndex;
private PaintMode _paintMode = PaintMode.PREVIEW;
private FlexoPrintableComponent _printableComponent;
private PrintManagingController _controller;
public FlexoPrintableDelegate(FlexoPrintableComponent printableComponent, PrintManagingController controller) {
super();
_controller = controller;
_printableComponent = printableComponent;
removeAllMouseListeners();
_printTitle = _printableComponent.getDefaultPrintableName();
updatePageLayout();
}
private void removeAllMouseListeners() {
removeAllMouseListenersForComponent((Component) _printableComponent);
}
private void removeAllMouseListenersForComponent(Component aComponent) {
Vector<MouseListener> mlToRemove = new Vector<MouseListener>();
for (MouseListener ml : aComponent.getMouseListeners()) {
mlToRemove.add(ml);
}
for (MouseListener ml : mlToRemove) {
if (logger.isLoggable(Level.FINER)) {
logger.finer("Remove MouseListener for " + aComponent);
}
aComponent.removeMouseListener(ml);
}
Vector<MouseMotionListener> mmlToRemove = new Vector<MouseMotionListener>();
for (MouseMotionListener mml : aComponent.getMouseMotionListeners()) {
mmlToRemove.add(mml);
}
for (MouseMotionListener mml : mmlToRemove) {
if (logger.isLoggable(Level.FINER)) {
logger.finer("Remove MouseMotionListener for " + aComponent);
}
aComponent.removeMouseMotionListener(mml);
}
if (aComponent instanceof Container) {
for (Component comp : ((Container) aComponent).getComponents()) {
removeAllMouseListenersForComponent(comp);
}
}
}
@Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) /* throws PrinterException */
{
if (logger.isLoggable(Level.FINE)) {
logger.fine("PRINT page " + pageIndex);
logger.fine("pageFormat= " + pageFormat);
logger.fine("graphics= " + graphics);
}
_pageFormat = pageFormat;
if (pageIndex >= getNumberOfPages()) {
return Printable.NO_SUCH_PAGE;
}
_paintMode = PaintMode.PRINTING;
_pageIndex = pageIndex;
_printableComponent.refreshComponent();
_printableComponent.print(graphics);
return Printable.PAGE_EXISTS;
}
public void preview(PageFormat pageFormat) /* throws PrinterException */
{
_pageFormat = pageFormat;
_paintMode = PaintMode.PREVIEW;
updatePageLayout();
refresh();
}
public static class PaintParameters {
int i, j;
double tx = 0.0;
double ty = 0.0;
double marginScale = 1.0;
double leftMargin = 0.0;
double rightMargin = 0.0;
double topMargin = 0.0;
double bottomMargin = 0.0;
}
public PaintParameters paintPrelude(Graphics2D g2) {
PaintParameters returned = new PaintParameters();
if (_paintMode == PaintMode.PREVIEW) {
g2.scale(previewScale, previewScale);
} else if (_paintMode == PaintMode.PRINTING) {
returned.j = _pageIndex / widthPageNb;
returned.i = _pageIndex - widthPageNb * returned.j;
if (logger.isLoggable(Level.FINE)) {
logger.fine("CALLED paint with _pageIndex=" + _pageIndex + " i=" + returned.i + " j=" + returned.j);
}
Rectangle pageBounds = getPageRect(_pageFormat);
Rectangle imageablePageBounds = getImageablePageRect(_pageFormat);
returned.marginScale = Math.min((double) imageablePageBounds.width / (double) pageBounds.width,
(double) imageablePageBounds.height / (double) pageBounds.height);
g2.scale(returned.marginScale, returned.marginScale);
if (logger.isLoggable(Level.FINER)) {
logger.finer("marginScale =" + returned.marginScale);
}
returned.leftMargin = imageablePageBounds.x;
returned.rightMargin = pageBounds.width - imageablePageBounds.x;
returned.topMargin = imageablePageBounds.x;
returned.bottomMargin = pageBounds.height - imageablePageBounds.y;
returned.tx = (double) -pageBounds.width * returned.i + returned.leftMargin;
returned.ty = (double) -pageBounds.height * returned.j + returned.topMargin;
if (logger.isLoggable(Level.FINER)) {
logger.finer("Translate tx=" + returned.tx + " ty=" + returned.ty);
}
g2.translate(returned.tx, returned.ty);
}
g2.scale(scale, scale);
return returned;
}
public void paintPostlude(Graphics2D g2, PaintParameters params) {
g2.scale(1 / scale, 1 / scale);
if (_paintMode == PaintMode.PREVIEW) {
// paintOptimalView(graphics);
paintPages(g2);
}
if (showPages()) {
showPages(g2);
}
if (showTitles()) {
showTitles(g2);
}
if (_paintMode == PaintMode.PREVIEW) {
g2.scale(1 / previewScale, 1 / previewScale);
} else if (_paintMode == PaintMode.PRINTING) {
g2.translate(-params.tx, -params.ty);
g2.scale(1 / params.marginScale, 1 / params.marginScale);
}
}
/* public void paint(Graphics graphics)
{
int i,j;
double tx = 0.0;
double ty = 0.0;
double marginScale = 1.0;
if (_paintMode == PaintMode.PREVIEW) {
((Graphics2D)graphics).scale(previewScale, previewScale);
}
else if (_paintMode == PaintMode.PRINTING) {
j = _pageIndex / widthPageNb;
i = _pageIndex - widthPageNb*j;
if (logger.isLoggable(Level.FINE))
logger.fine("CALLED paint with _pageIndex="+_pageIndex+" i="+i+" j="+j);
Rectangle pageBounds = getPageRect(_pageFormat);
Rectangle imageablePageBounds = getImageablePageRect(_pageFormat);
marginScale = Math.min((double)imageablePageBounds.width/(double)pageBounds.width, (double)imageablePageBounds.height/(double)pageBounds.height);
((Graphics2D)graphics).scale(marginScale, marginScale);
if (logger.isLoggable(Level.FINER))
logger.finer("marginScale ="+marginScale);
double leftMargin = imageablePageBounds.x;
double rightMargin = pageBounds.width-imageablePageBounds.x;
double topMargin = imageablePageBounds.x;
double bottomMargin = pageBounds.height-imageablePageBounds.y;
tx = (double)-pageBounds.width*i+leftMargin;
ty = (double)-pageBounds.height*j+topMargin;
if (logger.isLoggable(Level.FINER))
logger.finer("Translate tx="+tx+" ty="+ty);
((Graphics2D)graphics).translate(tx,ty);
}
((Graphics2D)graphics).scale(scale, scale);
super.paint(graphics);
((Graphics2D)graphics).scale(1/scale, 1/scale);
if (_paintMode == PaintMode.PREVIEW) {
//paintOptimalView(graphics);
paintPages(graphics);
}
if (showPages())
showPages(graphics);
if (showTitles())
showTitles(graphics);
if (_paintMode == PaintMode.PREVIEW) {
((Graphics2D)graphics).scale(1/previewScale, 1/previewScale);
}
else if (_paintMode == PaintMode.PRINTING) {
((Graphics2D)graphics).translate(-tx,-ty);
((Graphics2D)graphics).scale(1/marginScale, 1/marginScale);
}
}*/
private void showPages(Graphics2D g2) {
g2.setColor(Color.black);
int fontHeight = g2.getFontMetrics().getHeight();
int fontDesent = g2.getFontMetrics().getDescent();
Rectangle pageBounds = getPageRect(_pageFormat);
Rectangle imageablePageBounds = getImageablePageRect(_pageFormat);
int bottomMargin = pageBounds.height - imageablePageBounds.height - imageablePageBounds.y;
for (int i = 0; i < widthPageNb; i++) {
for (int j = 0; j < heightPageNb; j++) {
int pageIndex = j * widthPageNb + i;
// logger.info("Print page "+(pageIndex+1)+" scaleX="+g2.getTransform().getScaleX()+" scaleY="+g2.getTransform().getScaleY());
if (_paintMode == PaintMode.PREVIEW) {
g2.drawString("Page: " + (pageIndex + 1) + "/" + getNumberOfPages(), pageBounds.width / 2 - 35 + i * pageBounds.width,
pageBounds.height - fontHeight - fontDesent - bottomMargin + j * pageBounds.height);
} else if (_paintMode == PaintMode.PRINTING) {
g2.drawString("Page: " + (pageIndex + 1) + "/" + getNumberOfPages(), pageBounds.width / 2 - 35 + i * pageBounds.width,
pageBounds.height - fontHeight - fontDesent + j * pageBounds.height);
}
}
}
}
private void showTitles(Graphics2D g2) {
g2.setColor(Color.black);
// int fontHeight=g2.getFontMetrics().getHeight();
// int fontDesent=g2.getFontMetrics().getDescent();
Rectangle2D titleBounds = g2.getFontMetrics().getStringBounds(getPrintTitle(), g2);
Rectangle pageBounds = getPageRect(_pageFormat);
Rectangle imageablePageBounds = getImageablePageRect(_pageFormat);
// int bottomMargin = pageBounds.height-imageablePageBounds.height-imageablePageBounds.y;
for (int i = 0; i < widthPageNb; i++) {
for (int j = 0; j < heightPageNb; j++) {
// int pageIndex = j*widthPageNb+i;
if (_paintMode == PaintMode.PREVIEW) {
g2.drawString(getPrintTitle(), (int) (pageBounds.width / 2 - titleBounds.getWidth() / 2) + i * pageBounds.width,
imageablePageBounds.y + 15 + j * pageBounds.height);
} else if (_paintMode == PaintMode.PRINTING) {
g2.drawString(getPrintTitle(), (int) (pageBounds.width / 2 - titleBounds.getWidth() / 2) + i * pageBounds.width, 15 + j
* pageBounds.height);
}
}
}
}
@Override
public int getNumberOfPages() {
if (logger.isLoggable(Level.FINER)) {
logger.fine("numberOfPages=" + widthPageNb * heightPageNb);
}
return widthPageNb * heightPageNb;
}
/*private void paintOptimalView(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
DrawUtils.turnOnAntiAlising(g2);
DrawUtils.setRenderQuality(g2);
DrawUtils.setColorRenderQuality(g2);
g2.setColor(Color.BLUE);
Rectangle optimalBounds = getOptimalBounds();
if (logger.isLoggable(Level.FINER))
logger.finer("Optimal: "+optimalBounds);
if (optimalBounds != null) {
g2.drawRect(optimalBounds.x, optimalBounds.y, optimalBounds.width, optimalBounds.height);
}
}*/
private static float[] dash = { 3.0f, 3.0f };
public static final Stroke DASHED_STROKE = new BasicStroke(1.0f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10.0f, dash, 0.0f);
private void paintPages(Graphics2D g2) {
DrawUtils.turnOnAntiAlising(g2);
DrawUtils.setRenderQuality(g2);
DrawUtils.setColorRenderQuality(g2);
g2.setColor(Color.RED);
Stroke oldStroke = g2.getStroke();
g2.setStroke(DASHED_STROKE);
Rectangle pageBounds = getPageRect(_pageFormat);
if (logger.isLoggable(Level.FINER)) {
logger.finer("pageBounds: " + pageBounds);
}
for (int i = 0; i < widthPageNb; i++) {
for (int j = 0; j < heightPageNb; j++) {
paintPage(g2, i, j);
}
}
g2.setColor(Color.YELLOW);
Rectangle imageablePageBounds = getImageablePageRect(_pageFormat);
if (logger.isLoggable(Level.FINER)) {
logger.finer("imageablePageBounds: " + imageablePageBounds);
}
if (pageBounds != null) {
g2.drawRect(imageablePageBounds.x, imageablePageBounds.y, imageablePageBounds.width, imageablePageBounds.height);
}
g2.setStroke(oldStroke);
}
private void paintPage(Graphics2D g2, int i, int j) {
Rectangle pageBounds = getPageRect(_pageFormat);
if (pageBounds != null) {
g2.drawRect(pageBounds.width * i, pageBounds.height * j, pageBounds.width, pageBounds.height);
}
}
protected Rectangle getOptimalBounds() {
return _printableComponent.getOptimalBounds();
}
protected Rectangle getImageablePageRect(PageFormat pageFormat) {
return new Rectangle((int) pageFormat.getImageableX(), (int) pageFormat.getImageableY(), (int) pageFormat.getImageableWidth(),
(int) pageFormat.getImageableHeight());
}
protected Rectangle getPageRect(PageFormat pageFormat) {
return new Rectangle(0, 0, (int) pageFormat.getWidth(), (int) pageFormat.getHeight());
}
public double getScale() {
return scale;
}
public void setScale(double scale) {
this.scale = scale;
if (logger.isLoggable(Level.FINER)) {
logger.finer("Scale is " + scale);
}
updatePageLayout();
}
public double getPreviewScale() {
return previewScale;
}
public void setPreviewScale(double previewScale) {
this.previewScale = previewScale;
if (logger.isLoggable(Level.FINER)) {
logger.finer("Preview scale is " + previewScale);
}
updateSize();
}
public void fitToPage() {
if (_pageFormat != null) {
Rectangle optimalBounds = getOptimalBounds();
Rectangle pageBounds = getPageRect(_pageFormat);
double scaleX = (double) pageBounds.width / (double) (optimalBounds.x + optimalBounds.width + 1);
double scaleY = (double) pageBounds.height / (double) (optimalBounds.y + optimalBounds.height + 1);
if (scaleX < scaleY) {
setScale(scaleX);
} else {
setScale(scaleY);
}
}
}
private int heightPageNb = 1;
private int widthPageNb = 1;
private void updatePageLayout() {
if (_pageFormat != null) {
Rectangle optimalBounds = getOptimalBounds();
Rectangle pageBounds = getPageRect(_pageFormat);
widthPageNb = (int) ((optimalBounds.x + optimalBounds.width) * scale / pageBounds.width) + 1;
heightPageNb = (int) ((optimalBounds.y + optimalBounds.height) * scale / pageBounds.height) + 1;
updateSize();
}
}
private void updateSize() {
Rectangle pageBounds = getPageRect(_pageFormat);
Dimension viewSize = new Dimension((int) (widthPageNb * pageBounds.width * previewScale),
(int) (heightPageNb * pageBounds.height * previewScale));
if (logger.isLoggable(Level.FINER)) {
logger.finer("Resized to " + viewSize);
}
_printableComponent.resizeComponent(viewSize);
}
public void refresh() {
_printableComponent.refreshComponent();
}
public PaintMode getPaintMode() {
return _paintMode;
}
public void setPaintMode(PaintMode paintMode) {
_paintMode = paintMode;
}
public int getHeightPageNb() {
return heightPageNb;
}
public int getWidthPageNb() {
return widthPageNb;
}
public PageFormat getPageFormat() {
return _pageFormat;
}
public void setPageFormat(PageFormat pageFormat) {
_pageFormat = pageFormat;
updatePageLayout();
refresh();
}
private boolean _showPages;
private boolean _showTitles;
private String _printTitle;
public String getPrintTitle() {
return _printTitle;
}
public void setPrintTitle(String printTitle) {
_printTitle = printTitle;
}
public boolean showPages() {
return _showPages;
}
public void setShowPages(boolean showPages) {
_showPages = showPages;
}
public boolean showTitles() {
return _showTitles;
}
public void setShowTitles(boolean showTitles) {
_showTitles = showTitles;
}
@Override
public PageFormat getPageFormat(int pageIndex) throws IndexOutOfBoundsException {
if (logger.isLoggable(Level.FINE)) {
logger.fine("getPageFormat() with " + pageIndex);
}
_pageIndex = pageIndex;
return _pageFormat;
}
@Override
public Printable getPrintable(int pageIndex) throws IndexOutOfBoundsException {
if (logger.isLoggable(Level.FINE)) {
logger.fine("getPrintable() with " + pageIndex);
}
_pageIndex = pageIndex;
return this;
}
public PrintManagingController getController() {
return _controller;
}
}