001/* =========================================================== 002 * Orson Charts : a 3D chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C)opyright 2013-2022, by David Gilbert. All rights reserved. 006 * 007 * https://github.com/jfree/orson-charts 008 * 009 * This program is free software: you can redistribute it and/or modify 010 * it under the terms of the GNU General Public License as published by 011 * the Free Software Foundation, either version 3 of the License, or 012 * (at your option) any later version. 013 * 014 * This program is distributed in the hope that it will be useful, 015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 017 * GNU General Public License for more details. 018 * 019 * You should have received a copy of the GNU General Public License 020 * along with this program. If not, see <http://www.gnu.org/licenses/>. 021 * 022 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 023 * Other names may be trademarks of their respective owners.] 024 * 025 * If you do not wish to be bound by the terms of the GPL, an alternative 026 * commercial license can be purchased. For details, please see visit the 027 * Orson Charts home page: 028 * 029 * http://www.object-refinery.com/orsoncharts/index.html 030 * 031 */ 032 033package org.jfree.chart3d.label; 034 035import java.io.Serializable; 036import java.util.Formatter; 037 038import org.jfree.chart3d.data.DataUtils; 039import org.jfree.chart3d.data.PieDataset3D; 040import org.jfree.chart3d.internal.Args; 041 042/** 043 * A default implementation of the {@link PieLabelGenerator} interface. The 044 * implementation uses a {@link java.util.Formatter} instance to generate 045 * the labels. Three values are passed to the formatter: (1) the key for 046 * the current pie section, (2) the data value for the section (as a 047 * {@code Double}, possibly {@code null}) and (3) the calculated 048 * percentage value (as a {@code Double}, {@code Double.NaN} if the 049 * value is {@code null}). 050 * <br><br> 051 * NOTE: This class is serializable, but the serialization format is subject 052 * to change in future releases and should not be relied upon for persisting 053 * instances of this class. 054 * 055 * @since 1.2 056 */ 057@SuppressWarnings("serial") 058public class StandardPieLabelGenerator implements PieLabelGenerator, 059 Serializable { 060 061 /** 062 * A template string that will show the section key only. 063 * 064 * @since 1.2 065 */ 066 public static final String KEY_ONLY_TEMPLATE = "%s"; 067 068 /** 069 * A template string that will show the section key followed by the 070 * percentage in brackets (with zero decimal places). 071 * 072 * @since 1.2 073 */ 074 public static final String PERCENT_TEMPLATE = "%s (%3$,.0f%%)"; 075 076 /** 077 * A template string that will show the section key followed by the 078 * percentage in brackets (with two decimal places precision). 079 * 080 * @since 1.2 081 */ 082 public static final String PERCENT_TEMPLATE_2DP = "%s (%3$,.2f%%)"; 083 084 /** 085 * A template string that will show the section key followed by the 086 * value in brackets (with zero decimal places precision). 087 * 088 * @since 1.2 089 */ 090 public static final String VALUE_TEMPLATE = "%s (%2$,.0f)"; 091 092 /** 093 * A template string that will show the section key followed by the 094 * value in brackets (with two decimal places precision). 095 * 096 * @since 1.2 097 */ 098 public static final String VALUE_TEMPLATE_2DP = "%s (%2$,.2f)"; 099 100 /** 101 * The default template string (used in the default constructor, it is 102 * equivalent to {@link #PERCENT_TEMPLATE}). 103 * 104 * @since 1.2 105 */ 106 public static final String DEFAULT_TEMPLATE = PERCENT_TEMPLATE; 107 108 /** The label template. */ 109 private String template; 110 111 /** 112 * The default constructor, uses {@link #DEFAULT_TEMPLATE} for the 113 * template string. 114 */ 115 public StandardPieLabelGenerator() { 116 this(DEFAULT_TEMPLATE); 117 } 118 119 /** 120 * Creates a new instance with the specified template string (which will 121 * be passed to a {@code java.util.Formatter} instance when generating 122 * labels). See the class description for an explanation of the values 123 * that are available for use in the template string. 124 * 125 * @param template the template ({@code null} not permitted). 126 */ 127 public StandardPieLabelGenerator(String template) { 128 Args.nullNotPermitted(template, "template"); 129 this.template = template; 130 } 131 132 /** 133 * Generates the label for one section in a pie chart. 134 * 135 * @param dataset the dataset ({@code null} not permitted). 136 * @param key the key ({@code null} not permitted). 137 * 138 * @return The label (never {@code null} for this implementation). 139 */ 140 @Override @SuppressWarnings("unchecked") 141 public String generateLabel(PieDataset3D dataset, Comparable<?> key) { 142 Args.nullNotPermitted(dataset, "dataset"); 143 Args.nullNotPermitted(key, "key"); 144 Formatter formatter = new Formatter(new StringBuilder()); 145 Number value = (Number) dataset.getValue(key); 146 Number percent = Double.NaN; 147 if (value != null) { 148 double total = DataUtils.total(dataset); 149 percent = 100.0 * value.doubleValue() / total; 150 } 151 formatter.format(this.template, key, value, percent); 152 String result = formatter.toString(); 153 formatter.close(); 154 return result; 155 } 156 157 /** 158 * Tests this label generator for equality with an arbitrary object. 159 * 160 * @param obj the object ({@code null} permitted). 161 * 162 * @return A boolean. 163 */ 164 @Override 165 public boolean equals(Object obj) { 166 if (obj == this) { 167 return true; 168 } 169 if (!(obj instanceof StandardPieLabelGenerator)) { 170 return false; 171 } 172 StandardPieLabelGenerator that = (StandardPieLabelGenerator) obj; 173 if (!this.template.equals(that.template)) { 174 return false; 175 } 176 return true; 177 } 178 179 @Override 180 public int hashCode() { 181 return this.template.hashCode(); 182 } 183 184}