/* =========================================================== * 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.marker; import java.awt.geom.Point2D; import java.util.Map; import java.util.HashMap; import com.orsoncharts.util.ArgChecks; import com.orsoncharts.util.Anchor2D; /** * A record holder for data relating to markers that needs to be passed * to the 3D engine. * * @since 1.2 */ public class MarkerData { /** * The key used to store the marker on the axis. We can use this key * to retrieve the actual marker to get the label, font, color etc. */ private String markerKey; /** * The type of marker data (value or range). A value marker will have * a 'valueLine' stored in the data map. A range marker will have * a 'startLine' and an 'endLine' stored in the data map. */ private MarkerDataType type; /** Storage for data values (using a map for future expansion). */ private Map<String, Object> data; /** * Creates marker data for the case where there is a single line * (for example, the {@link NumberMarker} class). * * @param key the key for the marker ({@code null} not permitted). * @param pos the relative position along the axis (in the range 0.0 to * 1.0). */ public MarkerData(String key, double pos) { ArgChecks.nullNotPermitted(key, "key"); this.markerKey = key; this.type = MarkerDataType.VALUE; this.data = new HashMap<String, Object>(); this.data.put("valueLine", new MarkerLine(pos, false)); } /** * Creates marker data for the case where there are two lines. * (for example, the {@link RangeMarker} class). * * @param key the key ({@code null} not permitted). * @param startPos the relative start position. * @param startPegged is the start position pegged? * @param endPos the relative end position. * @param endPegged is the end position pegged? */ public MarkerData(String key, double startPos, boolean startPegged, double endPos, boolean endPegged) { ArgChecks.nullNotPermitted(key, "key"); this.markerKey = key; this.type = MarkerDataType.RANGE; this.data = new HashMap<String, Object>(); this.data.put("startLine", new MarkerLine(startPos, startPegged)); this.data.put("endLine", new MarkerLine(endPos, endPegged)); } /** * Creates a new instance based on an existing source that has type * {@code MarkerDataType.VALUE}. * * @param source the source ({@code null} not permitted). * @param v0 the vertex index for the start of the line. * @param v1 the vertex index for the end of the line. */ public MarkerData(MarkerData source, int v0, int v1) { ArgChecks.nullNotPermitted(source, "source"); if (!source.getType().equals(MarkerDataType.VALUE)) { throw new IllegalArgumentException("Must be MarkerDataType.VALUE"); } this.markerKey = source.markerKey; this.type = source.type; this.data = new HashMap<String, Object>(source.data); double pos = source.getValueLine().getPos(); MarkerLine valueLine = new MarkerLine(pos, false, v0, v1); this.data.put("valueLine", valueLine); } /** * Creates a new instance based on an existing source that has type * {@code MarkerDataType.Range}. * * @param source the source ({@code null} not permitted). * @param v0 the vertex index for the start of the first line. * @param v1 the vertex index for the end of the first line. * @param v2 the vertex index for the start of the second line. * @param v3 the vertex index for the end of the second line. */ public MarkerData(MarkerData source, int v0, int v1, int v2, int v3) { ArgChecks.nullNotPermitted(source, "source"); if (!source.getType().equals(MarkerDataType.RANGE)) { throw new IllegalArgumentException("Must be MarkerDataType.RANGE"); } this.markerKey = source.markerKey; this.type = MarkerDataType.RANGE; this.data = new HashMap<String, Object>(source.data); double startPos = source.getStartLine().getPos(); boolean startPegged = source.getStartLine().isPegged(); MarkerLine startLine = new MarkerLine(startPos, startPegged, v0, v1); this.data.put("startLine", startLine); double endPos = source.getEndLine().getPos(); boolean endPegged = source.getEndLine().isPegged(); MarkerLine endLine = new MarkerLine(endPos, endPegged, v2, v3); this.data.put("endLine", endLine); } /** * Returns the marker key (allows retrieval of the original marker object * when required). * * @return The marker key (never {@code null}). */ public String getMarkerKey() { return this.markerKey; } /** * Returns the type of marker data (value or range). * * @return The type (never {@code null}). */ public MarkerDataType getType() { return this.type; } /** * A convenience method that returns the value line data for a value marker. * * @return The value line (or {@code null}). */ public MarkerLine getValueLine() { return (MarkerLine) this.data.get("valueLine"); } /** * A convenience method that returns the start line data for a range marker. * * @return The start line (or {@code null}). */ public MarkerLine getStartLine() { return (MarkerLine) this.data.get("startLine"); } /** * A convenience method that returns the end line data for a range marker. * * @return The end line (or {@code null}). */ public MarkerLine getEndLine() { return (MarkerLine) this.data.get("endLine"); } /** * Returns the label anchor. * * @return The label anchor. */ public Anchor2D getLabelAnchor() { return (Anchor2D) this.data.get("labelAnchor"); } /** * Sets the label anchor. * * @param anchor the label anchor. */ public void setLabelAnchor(Anchor2D anchor) { this.data.put("labelAnchor", anchor); } /** * Returns the label vertex index. * * @return The label vertex index. */ public int getLabelVertexIndex() { Integer i = (Integer) this.data.get("labelVertexIndex"); return (i != null ? i.intValue() : -1); } /** * Sets the label vertex index. * * @param labelVertexIndex the label vertex index. */ public void setLabelVertexIndex(int labelVertexIndex) { this.data.put("labelVertexIndex", Integer.valueOf(labelVertexIndex)); } /** * Returns the label projection point. * * @return The label projection point (possibly {@code null}). */ public Point2D getLabelPoint() { return (Point2D) this.data.get("labelPoint"); } /** * Updates the projected points for this marker. This needs to be done * before the markers can be drawn. * * @param pts the projected points for the world. */ public void updateProjection(Point2D[] pts) { if (this.type.equals(MarkerDataType.VALUE)) { MarkerLine line = getValueLine(); line.setStartPoint(pts[line.getV0()]); line.setEndPoint(pts[line.getV1()]); } else if (this.type.equals(MarkerDataType.RANGE)) { MarkerLine startLine = getStartLine(); startLine.setStartPoint(pts[startLine.getV0()]); startLine.setEndPoint(pts[startLine.getV1()]); MarkerLine endLine = getEndLine(); endLine.setStartPoint(pts[endLine.getV0()]); endLine.setEndPoint(pts[endLine.getV1()]); } int labelVertex = getLabelVertexIndex(); if (labelVertex >= 0) { this.data.put("labelPoint", pts[labelVertex]); } else { this.data.put("labelPoint", null); } } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("MarkerData[key="); sb.append(this.markerKey); sb.append("]"); return sb.toString(); } }