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