/* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-2007, by Object Refinery Limited and Contributors.
*
* Project Info: http://www.jfree.org/jfreechart/index.html
*
* This library 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 library 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 library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* ------------------
* LegendGraphic.java
* ------------------
* (C) Copyright 2004-2007, by Object Refinery Limited.
*
* Original Author: David Gilbert (for Object Refinery Limited);
* Contributor(s): -;
*
* Changes
* -------
* 26-Oct-2004 : Version 1 (DG);
* 21-Jan-2005 : Modified return type of RectangleAnchor.coordinates()
* method (DG);
* 20-Apr-2005 : Added new draw() method (DG);
* 13-May-2005 : Fixed to respect margin, border and padding settings (DG);
* 01-Sep-2005 : Implemented PublicCloneable (DG);
* ------------- JFREECHART 1.0.x ---------------------------------------------
* 13-Dec-2006 : Added fillPaintTransformer attribute, so legend graphics can
* display gradient paint correctly, updated equals() and
* corrected clone() (DG);
* 01-Aug-2007 : Updated API docs (DG);
*
*/
package com.positive.charts.title;
import java.awt.Paint;
import java.awt.Shape;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.GCData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import com.positive.charts.block.AbstractBlock;
import com.positive.charts.block.Block;
import com.positive.charts.block.LengthConstraintType;
import com.positive.charts.block.RectangleConstraint;
import com.positive.charts.data.util.PublicCloneable;
import com.positive.charts.data.util.RectangleAnchor;
import com.positive.charts.util.RectangleUtil;
import com.positive.charts.util.Size2D;
/**
* The graphical item within a legend item.
*/
public class LegendGraphic extends AbstractBlock implements Block,
PublicCloneable {
/** For serialization. */
static final long serialVersionUID = -1338791523854985009L;
/*
* Translates a shape to a new location such that the anchor point (relative
* to the rectangular bounds of the shape) aligns with the specified (x, y)
* coordinate in Java2D space.
*
* @param shape the shape (<code>null</code> not permitted).
*
* @param anchor the anchor (<code>null</code> not permitted).
*
* @param locationX the x-coordinate (in Java2D space).
*
* @param locationY the y-coordinate (in Java2D space).
*
* @return A new and translated shape.
*/
public static Rectangle createTranslatedShape(final Rectangle shape,
final RectangleAnchor anchor, final double locationX,
final double locationY) {
if (shape == null) {
throw new IllegalArgumentException("Null 'shape' argument.");
}
if (anchor == null) {
throw new IllegalArgumentException("Null 'anchor' argument.");
}
final Point anchorPoint = RectangleAnchor.coordinates(shape, anchor);
final double tx = locationX - anchorPoint.x;
final double ty = locationY - anchorPoint.y;
return new Rectangle((int) (shape.x + tx), (int) (shape.y + ty),
shape.width, shape.height);
}
/**
* A flag that controls whether or not the shape is visible - see also
* lineVisible.
*/
private boolean shapeVisible;
/**
* The shape to display. To allow for accurate positioning, the center of
* the shape should be at (0, 0).
*/
private transient Rectangle shape;
/**
* Defines the location within the block to which the shape will be aligned.
*/
private RectangleAnchor shapeLocation;
/**
* Defines the point on the shape's bounding rectangle that will be aligned
* to the drawing location when the shape is rendered.
*/
private RectangleAnchor shapeAnchor;
/** A flag that controls whether or not the shape is filled. */
private boolean shapeFilled;
/** The fill paint for the shape. */
private transient Color fillPaint;
/**
* The fill paint transformer (used if the fillPaint is an instance of
* GradientPaint).
*
* @since 1.0.4
*/
// private GradientPaintTransformer fillPaintTransformer;
/** A flag that controls whether or not the shape outline is visible. */
private boolean shapeOutlineVisible;
/** The outline paint for the shape. */
// private transient Paint outlinePaint;
/** The outline stroke for the shape. */
// private transient Stroke outlineStroke;
/**
* A flag that controls whether or not the line is visible - see also
* shapeVisible.
*/
private boolean lineVisible;
/** The line. */
private transient Rectangle line;
private Color linePaint;
/** The line stroke. */
// private transient Stroke lineStroke;
/** The line paint. */
// private transient Paint linePaint;
/**
* Creates a new legend graphic.
*
* @param shape
* the shape (<code>null</code> not permitted).
* @param fillPaint
* the fill paint (<code>null</code> not permitted).
*/
public LegendGraphic(final Rectangle shape, final Color fillPaint) {
if (shape == null) {
throw new IllegalArgumentException("Null 'shape' argument.");
}
if (fillPaint == null) {
throw new IllegalArgumentException("Null 'fillPaint' argument.");
}
this.shapeVisible = true;
this.shape = shape;
this.shapeAnchor = RectangleAnchor.CENTER;
this.shapeLocation = RectangleAnchor.CENTER;
this.shapeFilled = true;
this.fillPaint = fillPaint;
this.setPadding(2.0, 2.0, 2.0, 2.0);
}
/**
* Arranges the contents of the block, within the given constraints, and
* returns the block size.
*
* @param g2
* the graphics device.
* @param constraint
* the constraint (<code>null</code> not permitted).
*
* @return The block size (in Java2D units, never <code>null</code>).
*/
public Size2D arrange(final GC g2, final RectangleConstraint constraint) {
final RectangleConstraint contentConstraint = this
.toContentConstraint(constraint);
final LengthConstraintType w = contentConstraint
.getWidthConstraintType();
final LengthConstraintType h = contentConstraint
.getHeightConstraintType();
Size2D contentSize = null;
if (w == LengthConstraintType.NONE) {
if (h == LengthConstraintType.NONE) {
contentSize = this.arrangeNN(g2);
} else if (h == LengthConstraintType.RANGE) {
throw new RuntimeException("Not yet implemented.");
} else if (h == LengthConstraintType.FIXED) {
throw new RuntimeException("Not yet implemented.");
}
} else if (w == LengthConstraintType.RANGE) {
if (h == LengthConstraintType.NONE) {
throw new RuntimeException("Not yet implemented.");
} else if (h == LengthConstraintType.RANGE) {
throw new RuntimeException("Not yet implemented.");
} else if (h == LengthConstraintType.FIXED) {
throw new RuntimeException("Not yet implemented.");
}
} else if (w == LengthConstraintType.FIXED) {
if (h == LengthConstraintType.NONE) {
throw new RuntimeException("Not yet implemented.");
} else if (h == LengthConstraintType.RANGE) {
throw new RuntimeException("Not yet implemented.");
} else if (h == LengthConstraintType.FIXED) {
contentSize = new Size2D(contentConstraint.getWidth(),
contentConstraint.getHeight());
}
}
return new Size2D(this.calculateTotalWidth(contentSize.getWidth()),
this.calculateTotalHeight(contentSize.getHeight()));
}
/**
* Performs the layout with no constraint, so the content size is determined
* by the bounds of the shape and/or line drawn to represent the series.
*
* @param g2
* the graphics device.
*
* @return The content size.
*/
protected Size2D arrangeNN(final GC g2) {
Rectangle contentSize = null;
if (this.line != null) {
return new Size2D(this.line.width, this.line.height);
}
if (this.shape != null) {
contentSize = RectangleUtil.createUnion(this.line, this.shape);
}
return new Size2D(contentSize.width, contentSize.height);
}
/**
* Returns a clone of this <code>LegendGraphic</code> instance.
*
* @return A clone of this <code>LegendGraphic</code> instance.
*
* @throws CloneNotSupportedException
* if there is a problem cloning.
*/
public Object clone() throws CloneNotSupportedException {
final LegendGraphic clone = (LegendGraphic) super.clone();
// clone.shape = ShapeUtilities.clone(this.shape);
// clone.line = ShapeUtilities.clone(this.line);
return clone;
}
/**
* Draws the graphic item within the specified area.
*
* @param g2
* the graphics device.
* @param area
* the area.
*/
public void draw(final GC g2, Rectangle area) {
area = this.trimMargin(area);
this.drawBorder(g2, area);
area = this.trimBorder(area);
area = this.trimPadding(area);
if (this.lineVisible) {
final Point location = RectangleAnchor.coordinates(area,
this.shapeLocation);
final Rectangle aLine = createTranslatedShape(this.getLine(),
this.shapeAnchor, location.x, location.y);
g2.setForeground(this.linePaint);
// g2.setStroke(this.lineStroke);
g2.drawLine(aLine.x, aLine.y, aLine.x + aLine.width, aLine.y
+ aLine.height);
}
if (this.shapeVisible) {
final Point location = RectangleAnchor.coordinates(area,
this.shapeLocation);
final Rectangle s = createTranslatedShape(this.shape,
this.shapeAnchor, location.x, location.y);
// s.width=100;
// s.height=100;
if (this.shapeFilled) {
// Paint p = this.fillPaint;
// if (p instanceof GradientPaint) {
// GradientPaint gp = (GradientPaint) this.fillPaint;
// p = this.fillPaintTransformer.transform(gp, s);
// }
g2.setBackground(this.fillPaint);
g2.fillRectangle(s);
}
// if (this.shapeOutlineVisible) {
// //g2.setPaint(this.outlinePaint);
// //g2.setStroke(this.outlineStroke);
// g2.draw(s);
// }
}
}
/**
* Draws the block within the specified area.
*
* @param g2
* the graphics device.
* @param area
* the area.
* @param params
* ignored (<code>null</code> permitted).
*
* @return Always <code>null</code>.
*/
public Object draw(final GC g2, final Rectangle area, final Object params) {
this.draw(g2, area);
return null;
}
/**
* Tests this <code>LegendGraphic</code> instance for equality with an
* arbitrary object.
*
* @param obj
* the object (<code>null</code> permitted).
*
* @return A boolean.
*/
public boolean equals(final Object obj) {
if (!(obj instanceof LegendGraphic)) {
return false;
}
final LegendGraphic that = (LegendGraphic) obj;
if (this.shapeVisible != that.shapeVisible) {
return false;
}
// if (!ShapeUtilities.equal(this.shape, that.shape)) {
// return false;
// }
if (this.shapeFilled != that.shapeFilled) {
return false;
}
// if (!PaintUtilities.equal(this.fillPaint, that.fillPaint)) {
// return false;
// }
// if (!ObjectUtilities.equal(this.fillPaintTransformer,
// that.fillPaintTransformer)) {
// return false;
// }
if (this.shapeOutlineVisible != that.shapeOutlineVisible) {
return false;
}
// if (!PaintUtilities.equal(this.outlinePaint, that.outlinePaint)) {
// return false;
// }
// if (!ObjectUtilities.equal(this.outlineStroke, that.outlineStroke)) {
// return false;
// }
if (this.shapeAnchor != that.shapeAnchor) {
return false;
}
if (this.shapeLocation != that.shapeLocation) {
return false;
}
if (this.lineVisible != that.lineVisible) {
return false;
}
// if (!ShapeUtilities.equal(this.line, that.line)) {
// return false;
// }
// if (!PaintUtilities.equal(this.linePaint, that.linePaint)) {
// return false;
// }
// if (!ObjectUtilities.equal(this.lineStroke, that.lineStroke)) {
// return false;
// }
return super.equals(obj);
}
/**
* Returns the paint used to fill the shape.
*
* @return The fill paint.
*
* @see #setFillPaint(Paint)
*/
public Color getFillPaint() {
return this.fillPaint;
}
/**
* Returns the line centered about (0, 0).
*
* @return The line.
*
* @see #setLine(Shape)
*/
public Rectangle getLine() {
return this.line;
}
/**
* Returns the shape.
*
* @return The shape.
*
* @see #setShape(Shape)
*/
public Rectangle getShape() {
return this.shape;
}
// /**
// * Returns the outline paint.
// *
// * @return The paint.
// *
// * @see #setOutlinePaint(Paint)
// */
// public Rectangle getOutlinePaint() {
// return this.outlinePaint;
// }
// /**
// * Sets the outline paint.
// *
// * @param paint
// * the paint.
// *
// * @see #getOutlinePaint()
// */
// public void setOutlinePaint(Paint paint) {
// this.outlinePaint = paint;
// }
//
// /**
// * Returns the outline stroke.
// *
// * @return The stroke.
// *
// * @see #setOutlineStroke(Stroke)
// */
// public Stroke getOutlineStroke() {
// return this.outlineStroke;
// }
// /**
// * Sets the outline stroke.
// *
// * @param stroke
// * the stroke.
// *
// * @see #getOutlineStroke()
// */
// public void setOutlineStroke(Stroke stroke) {
// this.outlineStroke = stroke;
// }
/**
* Returns the shape anchor.
*
* @return The shape anchor.
*
* @see #getShapeAnchor()
*/
public RectangleAnchor getShapeAnchor() {
return this.shapeAnchor;
}
/**
* Returns the shape location.
*
* @return The shape location.
*
* @see #setShapeLocation(RectangleAnchor)
*/
public RectangleAnchor getShapeLocation() {
return this.shapeLocation;
}
/**
* Returns a hash code for this instance.
*
* @return A hash code.
*/
public int hashCode() {
final int result = 193;
return result;
}
public void internal_dispose_GC(final int handle, final GCData data) {
}
public int internal_new_GC(final GCData data) {
return 0;
}
/**
* Returns the flag that controls whether or not the line is visible.
*
* @return A boolean.
*
* @see #setLineVisible(boolean)
*/
public boolean isLineVisible() {
return this.lineVisible;
}
/**
* Returns a flag that controls whether or not the shapes are filled.
*
* @return A boolean.
*
* @see #setShapeFilled(boolean)
*/
public boolean isShapeFilled() {
return this.shapeFilled;
}
/**
* Returns a flag that controls whether the shape outline is visible.
*
* @return A boolean.
*
* @see #setShapeOutlineVisible(boolean)
*/
public boolean isShapeOutlineVisible() {
return this.shapeOutlineVisible;
}
// /**
// * Returns the line paint.
// *
// * @return The paint.
// *
// * @see #setLinePaint(Paint)
// */
// public Paint getLinePaint() {
// return this.linePaint;
// }
//
// /**
// * Sets the line paint.
// *
// * @param paint
// * the paint.
// *
// * @see #getLinePaint()
// */
// public void setLinePaint(Paint paint) {
// this.linePaint = paint;
// }
// /**
// * Returns the line stroke.
// *
// * @return The stroke.
// *
// * @see #setLineStroke(Stroke)
// */
// public Stroke getLineStroke() {
// return this.lineStroke;
// }
//
// /**
// * Sets the line stroke.
// *
// * @param stroke
// * the stroke.
// *
// * @see #getLineStroke()
// */
// public void setLineStroke(Stroke stroke) {
// this.lineStroke = stroke;
// }
/**
* Returns a flag that controls whether or not the shape is visible.
*
* @return A boolean.
*
* @see #setShapeVisible(boolean)
*/
public boolean isShapeVisible() {
return this.shapeVisible;
}
/**
* Provides serialization support.
*
* @param stream
* the input stream.
*
* @throws IOException
* if there is an I/O error.
* @throws ClassNotFoundException
* if there is a classpath problem.
*/
private void readObject(final ObjectInputStream stream) throws IOException,
ClassNotFoundException {
stream.defaultReadObject();
// this.shape = SerialUtilities.readShape(stream);
// this.fillPaint = SerialUtilities.readPaint(stream);
// this.outlinePaint = SerialUtilities.readPaint(stream);
// this.outlineStroke = SerialUtilities.readStroke(stream);
// this.line = SerialUtilities.readShape(stream);
// this.linePaint = SerialUtilities.readPaint(stream);
// this.lineStroke = SerialUtilities.readStroke(stream);
}
/**
* Sets the paint used to fill the shape.
*
* @param paint
* the paint.
*
* @see #getFillPaint()
*/
public void setFillPaint(final Color paint) {
this.fillPaint = paint;
}
/**
* Sets the line. A Shape is used here, because then you can use Line2D,
* GeneralPath or any other Shape to represent the line.
*
* @param line
* the line.
*
* @see #getLine()
*/
public void setLine(final Rectangle line) {
this.line = line;
}
/**
* Sets the flag that controls whether or not the line is visible.
*
* @param visible
* the flag.
*
* @see #isLineVisible()
*/
public void setLineVisible(final boolean visible) {
this.lineVisible = visible;
}
/**
* Sets the shape.
*
* @param shape
* the shape.
*
* @see #getShape()
*/
public void setShape(final Rectangle shape) {
this.shape = shape;
}
/**
* Sets the shape anchor. This defines a point on the shapes bounding
* rectangle that will be used to align the shape to a location.
*
* @param anchor
* the anchor (<code>null</code> not permitted).
*
* @see #setShapeAnchor(RectangleAnchor)
*/
public void setShapeAnchor(final RectangleAnchor anchor) {
if (anchor == null) {
throw new IllegalArgumentException("Null 'anchor' argument.");
}
this.shapeAnchor = anchor;
}
/**
* Sets a flag that controls whether or not the shape is filled.
*
* @param filled
* the flag.
*
* @see #isShapeFilled()
*/
public void setShapeFilled(final boolean filled) {
this.shapeFilled = filled;
}
/**
* Sets the shape location. This defines a point within the drawing area
* that will be used to align the shape to.
*
* @param location
* the location (<code>null</code> not permitted).
*
* @see #getShapeLocation()
*/
public void setShapeLocation(final RectangleAnchor location) {
if (location == null) {
throw new IllegalArgumentException("Null 'location' argument.");
}
this.shapeLocation = location;
}
/**
* Sets a flag that controls whether or not the shape outline is visible.
*
* @param visible
* the flag.
*
* @see #isShapeOutlineVisible()
*/
public void setShapeOutlineVisible(final boolean visible) {
this.shapeOutlineVisible = visible;
}
/**
* Sets a flag that controls whether or not the shape is visible.
*
* @param visible
* the flag.
*
* @see #isShapeVisible()
*/
public void setShapeVisible(final boolean visible) {
this.shapeVisible = visible;
}
/**
* Provides serialization support.
*
* @param stream
* the output stream.
*
* @throws IOException
* if there is an I/O error.
*/
private void writeObject(final ObjectOutputStream stream)
throws IOException {
stream.defaultWriteObject();
// SerialUtilities.writeShape(this.shape, stream);
// SerialUtilities.writePaint(this.fillPaint, stream);
// SerialUtilities.writePaint(this.outlinePaint, stream);
// SerialUtilities.writeStroke(this.outlineStroke, stream);
// SerialUtilities.writeShape(this.line, stream);
// SerialUtilities.writePaint(this.linePaint, stream);
// SerialUtilities.writeStroke(this.lineStroke, stream);
}
}