001 /* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2009, by Object Refinery Limited and Contributors. 006 * 007 * Project Info: http://www.jfree.org/jfreechart/index.html 008 * 009 * This library is free software; you can redistribute it and/or modify it 010 * under the terms of the GNU Lesser General Public License as published by 011 * the Free Software Foundation; either version 2.1 of the License, or 012 * (at your option) any later version. 013 * 014 * This library is distributed in the hope that it will be useful, but 015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 017 * License for more details. 018 * 019 * You should have received a copy of the GNU Lesser General Public 020 * License along with this library; if not, write to the Free Software 021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 022 * USA. 023 * 024 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 025 * in the United States and other countries.] 026 * 027 * -------------- 028 * LogFormat.java 029 * -------------- 030 * (C) Copyright 2007-2009, by Object Refinery Limited and Contributors. 031 * 032 * Original Author: David Gilbert (for Object Refinery Limited); 033 * Contributor(s): -; 034 * 035 * Changes 036 * ------- 037 * 02-Aug-2007 : Version 1 (DG); 038 * 19-Feb-2008 : Implemented equals() and clone(), and added new powerLabel 039 * attribute as per Feature Request 1886036 (DG); 040 * 14-Jan-2009 : Added default constructor, and accessor methods for 041 * exponent formatter (DG); 042 * 043 */ 044 045 package org.jfree.chart.util; 046 047 import java.text.DecimalFormat; 048 import java.text.FieldPosition; 049 import java.text.NumberFormat; 050 import java.text.ParsePosition; 051 052 /** 053 * A number formatter for logarithmic values. This formatter does not support 054 * parsing. 055 * 056 * @since 1.0.7 057 */ 058 public class LogFormat extends NumberFormat { 059 060 /** The log base value. */ 061 private double base; 062 063 /** The natural logarithm of the base value. */ 064 private double baseLog; 065 066 /** The label for the log base (for example, "e"). */ 067 private String baseLabel; 068 069 /** 070 * The label for the power symbol. 071 * 072 * @since 1.0.10 073 */ 074 private String powerLabel; 075 076 /** A flag that controls whether or not the base is shown. */ 077 private boolean showBase; 078 079 /** The number formatter for the exponent. */ 080 private NumberFormat formatter = new DecimalFormat("0.0#"); 081 082 /** 083 * Creates a new instance using base 10. 084 * 085 * @since 1.0.13 086 */ 087 public LogFormat() { 088 this(10.0, "10", true); 089 } 090 091 /** 092 * Creates a new instance. 093 * 094 * @param base the base. 095 * @param baseLabel the base label (<code>null</code> not permitted). 096 * @param showBase a flag that controls whether or not the base value is 097 * shown. 098 */ 099 public LogFormat(double base, String baseLabel, boolean showBase) { 100 this(base, baseLabel, "^", showBase); 101 } 102 103 /** 104 * Creates a new instance. 105 * 106 * @param base the base. 107 * @param baseLabel the base label (<code>null</code> not permitted). 108 * @param powerLabel the power label (<code>null</code> not permitted). 109 * @param showBase a flag that controls whether or not the base value is 110 * shown. 111 * 112 * @since 1.0.10 113 */ 114 public LogFormat(double base, String baseLabel, String powerLabel, 115 boolean showBase) { 116 if (baseLabel == null) { 117 throw new IllegalArgumentException("Null 'baseLabel' argument."); 118 } 119 if (powerLabel == null) { 120 throw new IllegalArgumentException("Null 'powerLabel' argument."); 121 } 122 this.base = base; 123 this.baseLog = Math.log(this.base); 124 this.baseLabel = baseLabel; 125 this.showBase = showBase; 126 this.powerLabel = powerLabel; 127 } 128 129 /** 130 * Returns the number format used for the exponent. 131 * 132 * @return The number format (never <code>null</code>). 133 * 134 * @since 1.0.13. 135 */ 136 public NumberFormat getExponentFormat() { 137 return (NumberFormat) this.formatter.clone(); 138 } 139 140 /** 141 * Sets the number format used for the exponent. 142 * 143 * @param format the formatter (<code>null</code> not permitted). 144 * 145 * @since 1.0.13 146 */ 147 public void setExponentFormat(NumberFormat format) { 148 if (format == null) { 149 throw new IllegalArgumentException("Null 'format' argument."); 150 } 151 this.formatter = format; 152 } 153 154 /** 155 * Calculates the log of a given value. 156 * 157 * @param value the value. 158 * 159 * @return The log of the value. 160 */ 161 private double calculateLog(double value) { 162 return Math.log(value) / this.baseLog; 163 } 164 165 /** 166 * Returns a formatted representation of the specified number. 167 * 168 * @param number the number. 169 * @param toAppendTo the string buffer to append to. 170 * @param pos the position. 171 * 172 * @return A string buffer containing the formatted value. 173 */ 174 public StringBuffer format(double number, StringBuffer toAppendTo, 175 FieldPosition pos) { 176 StringBuffer result = new StringBuffer(); 177 if (this.showBase) { 178 result.append(this.baseLabel); 179 result.append(this.powerLabel); 180 } 181 result.append(this.formatter.format(calculateLog(number))); 182 return result; 183 } 184 185 /** 186 * Formats the specified number as a hexadecimal string. The decimal 187 * fraction is ignored. 188 * 189 * @param number the number to format. 190 * @param toAppendTo the buffer to append to (ignored here). 191 * @param pos the field position (ignored here). 192 * 193 * @return The string buffer. 194 */ 195 public StringBuffer format(long number, StringBuffer toAppendTo, 196 FieldPosition pos) { 197 StringBuffer result = new StringBuffer(); 198 if (this.showBase) { 199 result.append(this.baseLabel); 200 result.append("^"); 201 } 202 result.append(this.formatter.format(calculateLog(number))); 203 return result; 204 } 205 206 /** 207 * Parsing is not implemented, so this method always returns 208 * <code>null</code>. 209 * 210 * @param source ignored. 211 * @param parsePosition ignored. 212 * 213 * @return Always <code>null</code>. 214 */ 215 public Number parse (String source, ParsePosition parsePosition) { 216 return null; // don't bother with parsing 217 } 218 219 /** 220 * Tests this formatter for equality with an arbitrary object. 221 * 222 * @param obj the object (<code>null</code> permitted). 223 * 224 * @return A boolean. 225 */ 226 public boolean equals(Object obj) { 227 if (obj == this) { 228 return true; 229 } 230 if (!(obj instanceof LogFormat)) { 231 return false; 232 } 233 LogFormat that = (LogFormat) obj; 234 if (this.base != that.base) { 235 return false; 236 } 237 if (!this.baseLabel.equals(that.baseLabel)) { 238 return false; 239 } 240 if (this.baseLog != that.baseLog) { 241 return false; 242 } 243 if (this.showBase != that.showBase) { 244 return false; 245 } 246 if (!this.formatter.equals(that.formatter)) { 247 return false; 248 } 249 return super.equals(obj); 250 } 251 252 /** 253 * Returns a clone of this instance. 254 * 255 * @return A clone. 256 */ 257 public Object clone() { 258 LogFormat clone = (LogFormat) super.clone(); 259 clone.formatter = (NumberFormat) this.formatter.clone(); 260 return clone; 261 } 262 263 }