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