/*
* Copyright (c) 2005 Matthew Hall and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Matthew Hall - initial API and implementation
*/
package org.eclipse.nebula.paperclips.core;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.nebula.paperclips.core.internal.util.PrintSizeStrategy;
import org.eclipse.nebula.paperclips.core.internal.util.Util;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
/**
* A Print which displays its child prints in series. Each element in the series
* is displayed one at a time (no more than one child per page, although one
* Print may span several pages).
* <p>
* Use this class as the top-level Print when several distinct Prints should be
* batched into one print job, but printed on separate pages.
*
* @author Matthew Hall
*/
public class SeriesPrint implements Print {
final List items = new ArrayList();
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((items == null) ? 0 : items.hashCode());
return result;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
SeriesPrint other = (SeriesPrint) obj;
if (items == null) {
if (other.items != null)
return false;
} else if (!items.equals(other.items))
return false;
return true;
}
/**
* Adds the given prints to this SeriesPrint.
*
* @param items
* the Prints to add
*/
public void add(Print[] items) {
Util.noNulls(items);
for (int i = 0; i < items.length; i++)
this.items.add(items[i]);
}
/**
* Adds the given print to this SeriesPrint.
*
* @param item
* the Print to add
*/
public void add(Print item) {
Util.notNull(item);
items.add(item);
}
/**
* Returns the number of Prints that have been added to this SeriesPrint.
*
* @return the number of Prints that have been added to this SeriesPrint.
*/
public int size() {
return items.size();
}
/**
* Returns an array of items in the series.
*
* @return an array of items in the series.
*/
public Print[] getItems() {
return (Print[]) items.toArray(new Print[items.size()]);
}
public PrintIterator iterator(Device device, GC gc) {
return new SeriesIterator(this, device, gc);
}
}
class SeriesIterator implements PrintIterator {
final PrintIterator[] iters;
int index;
SeriesIterator(SeriesPrint print, Device device, GC gc) {
this.iters = new PrintIterator[print.items.size()];
for (int i = 0; i < iters.length; i++)
iters[i] = ((Print) print.items.get(i)).iterator(device, gc);
this.index = 0;
}
SeriesIterator(SeriesIterator that) {
this.iters = (PrintIterator[]) that.iters.clone();
for (int i = index; i < iters.length; i++)
this.iters[i] = that.iters[i].copy();
this.index = that.index;
}
public boolean hasNext() {
return index < iters.length;
}
private Point computeSize(PrintSizeStrategy strategy) {
int width = 0;
int height = 0;
for (int i = 0; i < iters.length; i++) {
PrintIterator iter = iters[i];
Point printSize = strategy.computeSize(iter);
width = Math.max(width, printSize.x);
height = Math.max(height, printSize.y);
}
return new Point(width, height);
}
public Point minimumSize() {
return computeSize(PrintSizeStrategy.MINIMUM);
}
public Point preferredSize() {
return computeSize(PrintSizeStrategy.PREFERRED);
}
public PrintPiece next(int width, int height) {
if (!hasNext())
PaperClips.error("No more content"); //$NON-NLS-1$
PrintIterator iter = iters[index];
PrintPiece printPiece = PaperClips.next(iter, width, height);
if (printPiece != null && !iter.hasNext())
index++;
return printPiece;
}
public PrintIterator copy() {
return new SeriesIterator(this);
}
}