package net.sf.sdedit.multipage;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JPanel;
import net.sf.sdedit.config.PrintConfiguration;
import net.sf.sdedit.diagram.Diagram;
import net.sf.sdedit.diagram.PaintDevice;
import net.sf.sdedit.drawable.Drawable;
import net.sf.sdedit.ui.components.ZoomPane;
import net.sf.sdedit.ui.components.Zoomable;
/**
*
* @author Markus Strauch
*/
public class MultipagePaintDevice extends PaintDevice {
private Dimension pageSize;
private Graphics2D graphics;
private Graphics2D boldGraphics;
private List<MultipagePanel> panels;
private double scale;
private PrintConfiguration properties;
public MultipagePaintDevice(PrintConfiguration properties, Dimension pageSize) {
super();
this.pageSize = pageSize;
panels = new ArrayList<MultipagePanel>();
this.properties = properties;
}
@Override
public void setDiagram(Diagram diagram) {
super.setDiagram(diagram);
graphics = (Graphics2D) new BufferedImage(1, 1,
BufferedImage.TYPE_USHORT_GRAY).getGraphics();
graphics.setFont(getFont(false));
boldGraphics = (Graphics2D) new BufferedImage(1, 1,
BufferedImage.TYPE_USHORT_GRAY).getGraphics();
boldGraphics.setFont(getFont(false));
}
public Dimension getPageSize() {
return pageSize;
}
private double computeScale() {
int h = pageSize.height;
int w = pageSize.width;
int H = getHeight();
int W = getWidth();
double xscale = 1D * w / W;
if (properties.isMultipage()) {
// Disabled (see also PrinterProperties dependency)
// if (properties.isFitToPage()) {
// return xscale;
// }
return Math.min(1, xscale);
}
double yscale = 1D * h / H;
if (properties.isFitToPage()) {
return Math.min(xscale, yscale);
}
return Math.min(1, Math.min(xscale, yscale));
}
public double getScale () {
return scale;
}
public void close() {
super.close();
scale = computeScale();
int numberOfPages;
if (properties.isMultipage()) {
numberOfPages = ((int) (getHeight() * scale)) / pageSize.height + 1;
} else {
numberOfPages = 1;
}
for (int i = 0; i < numberOfPages; i++) {
panels.add(new MultipagePanel(i));
}
}
public List<MultipagePaintDevice.MultipagePanel> getPanels() {
return panels;
}
public void announce(int height) {
if (properties.isMultipage()) {
int v0 = getDiagram().getVerticalPosition();
int v1 = v0 + height;
if (v1 / pageSize.height > v0 / pageSize.height) {
int diff = pageSize.height - v0 % pageSize.height;
getDiagram().extendLifelines(diff);
}
}
}
// @Override
// public void addSequenceElement (SequenceElement elem) {
// int y0 = elem.getTop() % pageSize.height;
// int y1 = y0 + elem.getHeight();
// int v = getDiagram().getVerticalPosition();
// if (y1 >= pageSize.height) {
// int beginOfNextPage = 0; // compute position where content of next
// page/panel begins
// // consider margins and heads
// getDiagram().extendLifelines(beginOfNextPage - v);
// elem.setTop(beginOfNextPage);
// }
// // TODO change Message.updateView such that lifelines are activated
// // after the arrow has been added (via addSequenceElement)
// // -- the top position of an arrow is valid only if it has
// // already been added to the PaintDevice
// super.addSequenceElement(elem);
// }
@Override
public int getTextHeight(boolean bold) {
return (bold ? boldGraphics : graphics).getFontMetrics().getHeight();
}
@Override
public int getTextWidth(String text, boolean bold) {
return (bold ? boldGraphics : graphics).getFontMetrics().stringWidth(
text);
}
public class MultipagePanel extends JPanel implements Zoomable<JPanel> {
private int index;
private ZoomPane zoomPane;
private Dimension dim;
MultipagePanel(int index) {
this.index = index;
dim = pageSize;
}
@Override
public Dimension getSize() {
return dim;
}
public Dimension getPreferredSize() {
return dim;
}
public Dimension getMinimumSize() {
return dim;
}
public Dimension getMaximumSize() {
return dim;
}
public int getHeight() {
return dim.height;
}
public int getWidth() {
return dim.width;
}
// compute the area in the center of the panel
@Override
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.scale(scale, scale);
Rectangle clipBounds = g2d.getClipBounds();
g2d.setColor(Color.WHITE);
g2d.fill(clipBounds);
Rectangle rect = null;
int w = (int) (pageSize.width / scale);
int h = (int) (pageSize.height / scale);
if (properties.isMultipage()) {
int y0 = index * (int) (pageSize.height / scale);
g2d.translate(0, -y0);
rect = new Rectangle(0, y0, w, h);
} else {
if (properties.isCenterVertically()) {
int yg = h - MultipagePaintDevice.this.getHeight();
if (yg > 0) {
g2d.translate(0, yg / 2);
}
}
}
if (properties.isCenterHorizontally()) {
int xg = w - MultipagePaintDevice.this.getWidth();
if (xg > 0) {
g2d.translate(xg / 2, 0);
}
}
for (Drawable drawable : MultipagePaintDevice.this) {
if (rect == null || drawable.intersects(rect)) {
drawable.draw(g2d);
}
}
g2d.dispose();
}
public JPanel asJComponent() {
return this;
}
public int getAbsoluteHeight() {
return pageSize.height;
}
public int getAbsoluteWidth() {
return pageSize.width;
}
public ZoomPane getZoomPane() {
return zoomPane;
}
public void setZoomPane(ZoomPane zoomPane) {
this.zoomPane = zoomPane;
}
}
}