001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2013, 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 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 025 * Other names may be trademarks of their respective owners.] 026 * 027 * -------------- 028 * LogFormat.java 029 * -------------- 030 * (C) Copyright 2007-2013, 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 * 03-Jul-2013 : Use ParamChecks (DG); 043 * 044 */ 045 046package org.jfree.chart.util; 047 048import java.text.DecimalFormat; 049import java.text.FieldPosition; 050import java.text.NumberFormat; 051import java.text.ParsePosition; 052 053/** 054 * A number formatter for logarithmic values. This formatter does not support 055 * parsing. 056 * 057 * @since 1.0.7 058 */ 059public class LogFormat extends NumberFormat { 060 061 /** The log base value. */ 062 private double base; 063 064 /** The natural logarithm of the base value. */ 065 private double baseLog; 066 067 /** The label for the log base (for example, "e"). */ 068 private String baseLabel; 069 070 /** 071 * The label for the power symbol. 072 * 073 * @since 1.0.10 074 */ 075 private String powerLabel; 076 077 /** A flag that controls whether or not the base is shown. */ 078 private boolean showBase; 079 080 /** The number formatter for the exponent. */ 081 private NumberFormat formatter = new DecimalFormat("0.0#"); 082 083 /** 084 * Creates a new instance using base 10. 085 * 086 * @since 1.0.13 087 */ 088 public LogFormat() { 089 this(10.0, "10", true); 090 } 091 092 /** 093 * Creates a new instance. 094 * 095 * @param base the base. 096 * @param baseLabel the base label (<code>null</code> not permitted). 097 * @param showBase a flag that controls whether or not the base value is 098 * shown. 099 */ 100 public LogFormat(double base, String baseLabel, boolean showBase) { 101 this(base, baseLabel, "^", showBase); 102 } 103 104 /** 105 * Creates a new instance. 106 * 107 * @param base the base. 108 * @param baseLabel the base label (<code>null</code> not permitted). 109 * @param powerLabel the power label (<code>null</code> not permitted). 110 * @param showBase a flag that controls whether or not the base value is 111 * shown. 112 * 113 * @since 1.0.10 114 */ 115 public LogFormat(double base, String baseLabel, String powerLabel, 116 boolean showBase) { 117 ParamChecks.nullNotPermitted(baseLabel, "baseLabel"); 118 ParamChecks.nullNotPermitted(powerLabel, "powerLabel"); 119 this.base = base; 120 this.baseLog = Math.log(this.base); 121 this.baseLabel = baseLabel; 122 this.showBase = showBase; 123 this.powerLabel = powerLabel; 124 } 125 126 /** 127 * Returns the number format used for the exponent. 128 * 129 * @return The number format (never <code>null</code>). 130 * 131 * @since 1.0.13. 132 */ 133 public NumberFormat getExponentFormat() { 134 return (NumberFormat) this.formatter.clone(); 135 } 136 137 /** 138 * Sets the number format used for the exponent. 139 * 140 * @param format the formatter (<code>null</code> not permitted). 141 * 142 * @since 1.0.13 143 */ 144 public void setExponentFormat(NumberFormat format) { 145 ParamChecks.nullNotPermitted(format, "format"); 146 this.formatter = format; 147 } 148 149 /** 150 * Calculates the log of a given value. 151 * 152 * @param value the value. 153 * 154 * @return The log of the value. 155 */ 156 private double calculateLog(double value) { 157 return Math.log(value) / this.baseLog; 158 } 159 160 /** 161 * Returns a formatted representation of the specified number. 162 * 163 * @param number the number. 164 * @param toAppendTo the string buffer to append to. 165 * @param pos the position. 166 * 167 * @return A string buffer containing the formatted value. 168 */ 169 @Override 170 public StringBuffer format(double number, StringBuffer toAppendTo, 171 FieldPosition pos) { 172 StringBuffer result = new StringBuffer(); 173 if (this.showBase) { 174 result.append(this.baseLabel); 175 result.append(this.powerLabel); 176 } 177 result.append(this.formatter.format(calculateLog(number))); 178 return result; 179 } 180 181 /** 182 * Formats the specified number as a hexadecimal string. The decimal 183 * fraction is ignored. 184 * 185 * @param number the number to format. 186 * @param toAppendTo the buffer to append to (ignored here). 187 * @param pos the field position (ignored here). 188 * 189 * @return The string buffer. 190 */ 191 @Override 192 public StringBuffer format(long number, StringBuffer toAppendTo, 193 FieldPosition pos) { 194 StringBuffer result = new StringBuffer(); 195 if (this.showBase) { 196 result.append(this.baseLabel); 197 result.append(this.powerLabel); 198 } 199 result.append(this.formatter.format(calculateLog(number))); 200 return result; 201 } 202 203 /** 204 * Parsing is not implemented, so this method always returns 205 * <code>null</code>. 206 * 207 * @param source ignored. 208 * @param parsePosition ignored. 209 * 210 * @return Always <code>null</code>. 211 */ 212 @Override 213 public Number parse (String source, ParsePosition parsePosition) { 214 return null; // don't bother with parsing 215 } 216 217 /** 218 * Tests this formatter for equality with an arbitrary object. 219 * 220 * @param obj the object (<code>null</code> permitted). 221 * 222 * @return A boolean. 223 */ 224 @Override 225 public boolean equals(Object obj) { 226 if (obj == this) { 227 return true; 228 } 229 if (!(obj instanceof LogFormat)) { 230 return false; 231 } 232 LogFormat that = (LogFormat) obj; 233 if (this.base != that.base) { 234 return false; 235 } 236 if (!this.baseLabel.equals(that.baseLabel)) { 237 return false; 238 } 239 if (this.baseLog != that.baseLog) { 240 return false; 241 } 242 if (this.showBase != that.showBase) { 243 return false; 244 } 245 if (!this.formatter.equals(that.formatter)) { 246 return false; 247 } 248 return super.equals(obj); 249 } 250 251 /** 252 * Returns a clone of this instance. 253 * 254 * @return A clone. 255 */ 256 @Override 257 public Object clone() { 258 LogFormat clone = (LogFormat) super.clone(); 259 clone.formatter = (NumberFormat) this.formatter.clone(); 260 return clone; 261 } 262 263}