/*
* 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 org.eclipse.nebula.paperclips.core.internal.util.ResourcePool;
import org.eclipse.nebula.paperclips.core.internal.util.Util;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
/**
* A Print for drawing horizontal and vertical lines.
* <p>
* LinePrints are either horizontally or vertically greedy, according to the
* orientation of the line. Greedy prints take up all the available space on the
* page.
*
* @author Matthew Hall
*/
public class LinePrint implements Print {
final int orientation;
double thickness;
RGB rgb = new RGB(0, 0, 0);
/**
* Constructs a horizontal LinePrint.
*/
public LinePrint() {
this(SWT.HORIZONTAL);
}
/**
* Constructs a LinePrint with the given orientation and 1-point thickness.
*
* @param orientation
* one of SWT#HORIZONTAL or SWT#VERTICAL.
*/
public LinePrint(int orientation) {
this(orientation, 1.0);
}
/**
* Constructs a LinePrint with the given orientation and thickness.
*
* @param orientation
* one of SWT#HORIZONTAL or SWT#VERTICAL.
* @param thickness
* the line thickness, expressed in points.
*/
public LinePrint(int orientation, double thickness) {
this.orientation = checkOrientation(orientation);
this.thickness = checkThickness(thickness);
}
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + orientation;
result = prime * result + ((rgb == null) ? 0 : rgb.hashCode());
long temp;
temp = Double.doubleToLongBits(thickness);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
LinePrint other = (LinePrint) obj;
if (orientation != other.orientation)
return false;
if (rgb == null) {
if (other.rgb != null)
return false;
} else if (!rgb.equals(other.rgb))
return false;
if (Double.doubleToLongBits(thickness) != Double
.doubleToLongBits(other.thickness))
return false;
return true;
}
/**
* Returns the line orientation (one of {@link SWT#HORIZONTAL} or
* {@link SWT#VERTICAL}).
*
* @return the line orientation.
*/
public int getOrientation() {
return orientation;
}
private int checkOrientation(int orientation) {
if ((orientation & SWT.HORIZONTAL) == SWT.HORIZONTAL)
return SWT.HORIZONTAL;
else if ((orientation & SWT.VERTICAL) == SWT.VERTICAL)
return SWT.VERTICAL;
else
return SWT.HORIZONTAL;
}
private double checkThickness(double thickness) {
if (thickness < 0)
return 0;
return thickness;
}
/**
* Returns the line thickness, in points. 72 points = 1".
*
* @return the line thickness, in points.
*/
public double getThickness() {
return thickness;
}
/**
* Sets the line thickness, in points. 72 points = 1".
*
* @param thickness
* the line thickness, in points.
*/
public void setThickness(double thickness) {
this.thickness = thickness;
}
/**
* Sets the line color to the argument.
*
* @param foreground
* the new line color.
*/
public void setRGB(RGB foreground) {
Util.notNull(foreground);
this.rgb = foreground;
}
/**
* Returns the line color.
*
* @return the line color.
*/
public RGB getRGB() {
return rgb;
}
public PrintIterator iterator(Device device, GC gc) {
return new LineIterator(this, device, gc);
}
}
class LineIterator implements PrintIterator {
private final Device device;
private final GC gc;
final int orientation;
final Point thickness;
final RGB rgb;
private boolean hasNext = true;
LineIterator(LinePrint print, Device device, GC gc) {
this.device = device;
this.gc = gc;
this.orientation = print.orientation;
this.rgb = print.rgb;
Point dpi = device.getDPI();
// (convert from points to pixels on device)
this.thickness = new Point(Math.max(1, (int) Math.round(print.thickness
* dpi.x / 72)), Math.max(1, (int) Math.round(print.thickness
* dpi.y / 72)));
}
LineIterator(LineIterator that) {
this.device = that.device;
this.gc = that.gc;
this.orientation = that.orientation;
this.rgb = that.rgb;
this.hasNext = that.hasNext;
this.thickness = that.thickness;
}
public boolean hasNext() {
return hasNext;
}
Point getSize(int width, int height) {
return orientation == SWT.VERTICAL ? new Point(thickness.x, height)
: new Point(width, thickness.y);
}
public PrintPiece next(int width, int height) {
if (!hasNext())
PaperClips.error("No more content"); //$NON-NLS-1$
// Make sure the line fits :)
Point size = getSize(width, height);
if (size.x > width || size.y > height)
return null;
PrintPiece result = new LinePiece(device, size, rgb);
hasNext = false;
return result;
}
public Point minimumSize() {
return new Point(thickness.x, thickness.y);
}
public Point preferredSize() {
return new Point(thickness.x, thickness.y);
}
public PrintIterator copy() {
return new LineIterator(this);
}
}
class LinePiece implements PrintPiece {
private final Device device;
private final Point size;
private final RGB rgb;
LinePiece(Device device, Point size, RGB rgb) {
this.device = device;
this.size = size;
this.rgb = rgb;
}
public Point getSize() {
return new Point(size.x, size.y);
}
public void paint(GC gc, int x, int y) {
Color oldBackground = gc.getBackground();
Point size = getSize();
try {
gc.setBackground(ResourcePool.forDevice(device).getColor(rgb));
gc.fillRectangle(x, y, size.x, size.y);
} finally {
gc.setBackground(oldBackground);
}
}
public void dispose() {
} // Shared resources, nothing to dispose
}