/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2016, by Object Refinery Limited. All rights reserved. * * http://www.object-refinery.com/orsoncharts/index.html * * This program 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. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package com.orsoncharts.table; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.Dimension2D; import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.List; import java.util.Map; import com.orsoncharts.util.ArgChecks; /** * A table element that displays a shape. * <br><br> * NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class ShapeElement extends AbstractTableElement implements TableElement { /** * The shape (by convention, the shape should be centered on the point * (0, 0)). */ private Shape shape; private Color fillColor; /** * Creates a new shape element. * * @param shape the shape ({@code null} not permitted). * @param fillColor the fill color ({@code null} not permitted). */ public ShapeElement(Shape shape, Color fillColor) { super(); ArgChecks.nullNotPermitted(shape, "shape"); ArgChecks.nullNotPermitted(fillColor, "fillColor"); this.shape = shape; this.fillColor = fillColor; } /** * Returns the fill color. * * @return The fill color. * * @since 1.2 */ public Color getFillColor() { return this.fillColor; } /** * Sets the fill color. * * @param color the fill color ({@code null} not permitted). * * @since 1.2 */ public void setFillColor(Color color) { ArgChecks.nullNotPermitted(color, "color"); this.fillColor = color; } @Override public Dimension2D preferredSize(Graphics2D g2, Rectangle2D bounds, Map<String, Object> constraints) { Insets insets = getInsets(); Rectangle2D shapeBounds = shape.getBounds2D(); return new ElementDimension(Math.min(shapeBounds.getWidth() + insets.left + insets.right, bounds.getWidth()), Math.min(shapeBounds.getHeight() + insets.top + insets.bottom, bounds.getHeight())); } @Override public List<Rectangle2D> layoutElements(Graphics2D g2, Rectangle2D bounds, Map<String, Object> constraints) { List<Rectangle2D> result = new ArrayList<Rectangle2D>(1); Insets insets = getInsets(); Rectangle2D shapeBounds = this.shape.getBounds2D(); double w = Math.min(shapeBounds.getWidth() + insets.left + insets.right, bounds.getWidth()); double h = Math.min(shapeBounds.getHeight() + insets.top + insets.bottom, bounds.getHeight()); Rectangle2D pos = new Rectangle2D.Double(bounds.getCenterX() - w / 2.0, bounds.getCenterY() - h / 2.0, w, h); result.add(pos); return result; } /** * Draws the shape element within the specified bounds. * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). */ @Override public void draw(Graphics2D g2, Rectangle2D bounds) { draw(g2, bounds, null); } /** * Draws the element within the specified bounds. If the * {@code recordBounds} flag is set, this element and each of its * children will have their {@code BOUNDS_2D} property updated with * the current bounds. * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). * @param onDrawHandler an object that will receive notification before * and after the element is drawn ({@code null} permitted). * * @since 1.3 */ @Override public void draw(Graphics2D g2, Rectangle2D bounds, TableElementOnDraw onDrawHandler) { if (onDrawHandler != null) { onDrawHandler.beforeDraw(this, g2, bounds); } AffineTransform saved = g2.getTransform(); RectanglePainter background = getBackground(); if (background != null) { background.fill(g2, bounds); } g2.translate(bounds.getCenterX(), bounds.getCenterY()); g2.setPaint(this.fillColor); g2.fill(shape); g2.setTransform(saved); if (onDrawHandler != null) { onDrawHandler.afterDraw(this, g2, bounds); } } /** * Receives a visitor. * * @param visitor the visitor ({@code null} not permitted). * * @since 1.2 */ @Override public void receive(TableElementVisitor visitor) { visitor.visit(this); } /** * Returns a string representation of this element, primarily for * debugging purposes. * * @return A string representation of this element. */ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("ShapeElement[shape=").append(this.shape).append("]"); return sb.toString(); } }