Frames | No Frames |
1: /* =========================================================== 2: * JFreeChart : a free chart library for the Java(tm) platform 3: * =========================================================== 4: * 5: * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors. 6: * 7: * Project Info: http://www.jfree.org/jfreechart/index.html 8: * 9: * This library is free software; you can redistribute it and/or modify it 10: * under the terms of the GNU Lesser General Public License as published by 11: * the Free Software Foundation; either version 2.1 of the License, or 12: * (at your option) any later version. 13: * 14: * This library is distributed in the hope that it will be useful, but 15: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 17: * License for more details. 18: * 19: * You should have received a copy of the GNU Lesser General Public 20: * License along with this library; if not, write to the Free Software 21: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 22: * USA. 23: * 24: * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 25: * in the United States and other countries.] 26: * 27: * --------------------- 28: * LookupPaintScale.java 29: * --------------------- 30: * (C) Copyright 2006, 2007, by Object Refinery Limited. 31: * 32: * Original Author: David Gilbert (for Object Refinery Limited); 33: * Contributor(s): -; 34: * 35: * $Id: LookupPaintScale.java,v 1.1.2.3 2007/03/09 15:59:21 mungady Exp $ 36: * 37: * Changes 38: * ------- 39: * 05-Jul-2006 : Version 1 (DG); 40: * 31-Jan-2007 : Fixed serialization support (DG); 41: * 09-Mar-2007 : Fixed cloning (DG); 42: * 43: */ 44: 45: package org.jfree.chart.renderer; 46: 47: import java.awt.Color; 48: import java.awt.Paint; 49: import java.io.IOException; 50: import java.io.ObjectInputStream; 51: import java.io.ObjectOutputStream; 52: import java.io.Serializable; 53: import java.util.Collections; 54: import java.util.List; 55: 56: import org.jfree.io.SerialUtilities; 57: import org.jfree.util.PaintUtilities; 58: import org.jfree.util.PublicCloneable; 59: 60: /** 61: * A paint scale that uses a lookup table to associate paint instances 62: * with data value ranges. 63: * 64: * @since 1.0.4 65: */ 66: public class LookupPaintScale 67: implements PaintScale, PublicCloneable, Serializable { 68: 69: /** 70: * Stores the paint for a value. 71: */ 72: class PaintItem implements Comparable, Serializable { 73: 74: /** The value. */ 75: Number value; 76: 77: /** The paint. */ 78: transient Paint paint; 79: 80: /** 81: * Creates a new instance. 82: * 83: * @param value the value. 84: * @param paint the paint. 85: */ 86: public PaintItem(Number value, Paint paint) { 87: this.value = value; 88: this.paint = paint; 89: } 90: 91: /* (non-Javadoc) 92: * @see java.lang.Comparable#compareTo(java.lang.Object) 93: */ 94: public int compareTo(Object obj) { 95: PaintItem that = (PaintItem) obj; 96: double d1 = this.value.doubleValue(); 97: double d2 = that.value.doubleValue(); 98: if (d1 > d2) { 99: return 1; 100: } 101: if (d1 < d2) { 102: return -1; 103: } 104: return 0; 105: } 106: 107: /** 108: * Tests this item for equality with an arbitrary object. 109: * 110: * @param obj the object (<code>null</code> permitted). 111: * 112: * @return A boolean. 113: */ 114: public boolean equals(Object obj) { 115: if (obj == this) { 116: return true; 117: } 118: if (!(obj instanceof PaintItem)) { 119: return false; 120: } 121: PaintItem that = (PaintItem) obj; 122: if (!this.value.equals(that.value)) { 123: return false; 124: } 125: if (!PaintUtilities.equal(this.paint, that.paint)) { 126: return false; 127: } 128: return true; 129: } 130: 131: /** 132: * Provides serialization support. 133: * 134: * @param stream the output stream. 135: * 136: * @throws IOException if there is an I/O error. 137: */ 138: private void writeObject(ObjectOutputStream stream) throws IOException { 139: stream.defaultWriteObject(); 140: SerialUtilities.writePaint(this.paint, stream); 141: } 142: 143: /** 144: * Provides serialization support. 145: * 146: * @param stream the input stream. 147: * 148: * @throws IOException if there is an I/O error. 149: * @throws ClassNotFoundException if there is a classpath problem. 150: */ 151: private void readObject(ObjectInputStream stream) 152: throws IOException, ClassNotFoundException { 153: stream.defaultReadObject(); 154: this.paint = SerialUtilities.readPaint(stream); 155: } 156: 157: } 158: 159: /** The lower bound. */ 160: private double lowerBound; 161: 162: /** The upper bound. */ 163: private double upperBound; 164: 165: /** The default paint. */ 166: private transient Paint defaultPaint; 167: 168: /** The lookup table. */ 169: private List lookupTable; 170: 171: /** 172: * Creates a new paint scale. 173: */ 174: public LookupPaintScale() { 175: this(0.0, 1.0, Color.lightGray); 176: } 177: 178: /** 179: * Creates a new paint scale with the specified default paint. 180: * 181: * @param lowerBound the lower bound. 182: * @param upperBound the upper bound. 183: * @param defaultPaint the default paint (<code>null</code> not 184: * permitted). 185: */ 186: public LookupPaintScale(double lowerBound, double upperBound, 187: Paint defaultPaint) { 188: if (lowerBound >= upperBound) { 189: throw new IllegalArgumentException( 190: "Requires lowerBound < upperBound."); 191: } 192: if (defaultPaint == null) { 193: throw new IllegalArgumentException("Null 'paint' argument."); 194: } 195: this.lowerBound = lowerBound; 196: this.upperBound = upperBound; 197: this.defaultPaint = defaultPaint; 198: this.lookupTable = new java.util.ArrayList(); 199: } 200: 201: /** 202: * Returns the default paint (never <code>null</code>). 203: * 204: * @return The default paint. 205: */ 206: public Paint getDefaultPaint() { 207: return this.defaultPaint; 208: } 209: 210: /** 211: * Returns the lower bound. 212: * 213: * @return The lower bound. 214: * 215: * @see #getUpperBound() 216: */ 217: public double getLowerBound() { 218: return this.lowerBound; 219: } 220: 221: /** 222: * Returns the upper bound. 223: * 224: * @return The upper bound. 225: * 226: * @see #getLowerBound() 227: */ 228: public double getUpperBound() { 229: return this.upperBound; 230: } 231: 232: /** 233: * Adds an entry to the lookup table. Any values from <code>n</code> up 234: * to but not including the next value in the table take on the specified 235: * <code>paint</code>. 236: * 237: * @param value the data value. 238: * @param paint the paint. 239: */ 240: public void add(Number value, Paint paint) { 241: PaintItem item = new PaintItem(value, paint); 242: int index = Collections.binarySearch(this.lookupTable, item); 243: if (index >= 0) { 244: this.lookupTable.set(index, item); 245: } 246: else { 247: this.lookupTable.add(-(index + 1), item); 248: } 249: } 250: 251: /** 252: * Returns the paint associated with the specified value. 253: * 254: * @param value the value. 255: * 256: * @return The paint. 257: * 258: * @see #getDefaultPaint() 259: */ 260: public Paint getPaint(double value) { 261: 262: // handle value outside bounds... 263: if (value < this.lowerBound) { 264: return this.defaultPaint; 265: } 266: if (value > this.upperBound) { 267: return this.defaultPaint; 268: } 269: 270: // for value in bounds, do the lookup... 271: Paint result = this.defaultPaint; 272: int index = this.lookupTable.size(); 273: boolean done = false; 274: while (index > 0 && !done) { 275: PaintItem item = (PaintItem) this.lookupTable.get(--index); 276: if (value >= item.value.doubleValue()) { 277: result = item.paint; 278: done = true; 279: } 280: } 281: return result; 282: } 283: 284: /** 285: * Tests this instance for equality with an arbitrary object. 286: * 287: * @param obj the object (<code>null</code> permitted). 288: * 289: * @return A boolean. 290: */ 291: public boolean equals(Object obj) { 292: if (obj == this) { 293: return true; 294: } 295: if (!(obj instanceof LookupPaintScale)) { 296: return false; 297: } 298: LookupPaintScale that = (LookupPaintScale) obj; 299: if (this.lowerBound != that.lowerBound) { 300: return false; 301: } 302: if (this.upperBound != that.upperBound) { 303: return false; 304: } 305: if (!PaintUtilities.equal(this.defaultPaint, that.defaultPaint)) { 306: return false; 307: } 308: if (!this.lookupTable.equals(that.lookupTable)) { 309: return false; 310: } 311: return true; 312: } 313: 314: /** 315: * Returns a clone of the instance. 316: * 317: * @return A clone. 318: * 319: * @throws CloneNotSupportedException if there is a problem cloning the 320: * instance. 321: */ 322: public Object clone() throws CloneNotSupportedException { 323: LookupPaintScale clone = (LookupPaintScale) super.clone(); 324: clone.lookupTable = new java.util.ArrayList(this.lookupTable); 325: return clone; 326: } 327: 328: /** 329: * Provides serialization support. 330: * 331: * @param stream the output stream. 332: * 333: * @throws IOException if there is an I/O error. 334: */ 335: private void writeObject(ObjectOutputStream stream) throws IOException { 336: stream.defaultWriteObject(); 337: SerialUtilities.writePaint(this.defaultPaint, stream); 338: } 339: 340: /** 341: * Provides serialization support. 342: * 343: * @param stream the input stream. 344: * 345: * @throws IOException if there is an I/O error. 346: * @throws ClassNotFoundException if there is a classpath problem. 347: */ 348: private void readObject(ObjectInputStream stream) 349: throws IOException, ClassNotFoundException { 350: stream.defaultReadObject(); 351: this.defaultPaint = SerialUtilities.readPaint(stream); 352: } 353: 354: }