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.renderer; 034 035import java.awt.Color; 036import java.awt.Font; 037import java.io.Serializable; 038import javax.swing.event.EventListenerList; 039 040import org.jfree.chart3d.ChartElementVisitor; 041import org.jfree.chart3d.internal.Args; 042import org.jfree.chart3d.label.ItemLabelPositioning; 043 044/** 045 * A base class for 3D renderers. 046 */ 047public abstract class AbstractRenderer3D implements Renderer3D, Serializable { 048 049 /** The font used to draw item labels. */ 050 private Font itemLabelFont; 051 052 /** The foreground color for item labels. */ 053 private Color itemLabelColor; 054 055 /** The background color for item labels. */ 056 private Color itemLabelBackgroundColor; 057 058 /** The item label positioning. */ 059 private ItemLabelPositioning itemLabelPositioning; 060 061 /** Storage for registered change listeners. */ 062 private final transient EventListenerList listenerList; 063 064 /** 065 * A flag that controls whether or not the renderer will notify listeners 066 * of changes (defaults to {@code true}, but sometimes it is useful 067 * to disable this). 068 */ 069 private boolean notify; 070 071 /** 072 * Default constructor. 073 */ 074 protected AbstractRenderer3D() { 075 this.itemLabelFont = new Font(Font.SERIF, Font.PLAIN, 12); 076 this.itemLabelColor = Color.WHITE; 077 this.itemLabelBackgroundColor = new Color(100, 100, 100, 100); //Renderer3D.TRANSPARENT_COLOR; 078 this.itemLabelPositioning = ItemLabelPositioning.CENTRAL; 079 this.listenerList = new EventListenerList(); 080 this.notify = true; 081 } 082 083 /** 084 * Returns the font used to display item labels, if there are any. 085 * The default value is {@code Font(Font.SERIF, Font.PLAIN, 8)}. 086 * 087 * @return The font (never {@code null}). 088 * 089 * @since 1.3 090 */ 091 public Font getItemLabelFont() { 092 return itemLabelFont; 093 } 094 095 /** 096 * Sets the font used to display item labels and sends a change event 097 * to all registered listeners. 098 * 099 * @param itemLabelFont the font ({@code null} not permitted). 100 * 101 * @since 1.3 102 */ 103 public void setItemLabelFont(Font itemLabelFont) { 104 Args.nullNotPermitted(itemLabelFont, "itemLabelFont"); 105 this.itemLabelFont = itemLabelFont; 106 fireChangeEvent(true); 107 } 108 109 /** 110 * Returns the foreground color used to display item labels. The default 111 * value is {@code Color.BLACK}. 112 * 113 * @return The foreground color (never {@code null}). 114 * 115 * @since 1.3 116 */ 117 public Color getItemLabelColor() { 118 return itemLabelColor; 119 } 120 121 /** 122 * Sets the foreground color used to display item labels and sends a 123 * change event to all registered listeners. 124 * 125 * @param itemLabelColor the new color ({@code null} not permitted). 126 * 127 * @since 1.3 128 */ 129 public void setItemLabelColor(Color itemLabelColor) { 130 Args.nullNotPermitted(itemLabelColor, "itemLabelColor"); 131 this.itemLabelColor = itemLabelColor; 132 fireChangeEvent(true); 133 } 134 135 /** 136 * Returns the background color for item labels. 137 * 138 * @return The background color (never {@code null}). 139 * 140 * @since 1.3 141 */ 142 public Color getItemLabelBackgroundColor() { 143 return itemLabelBackgroundColor; 144 } 145 146 /** 147 * Sets the background color and sends a change event to all registered 148 * listeners. 149 * 150 * @param color the new color ({@code null} not permitted). 151 * 152 * @since 1.3 153 */ 154 public void setItemLabelBackgroundColor(Color color) { 155 Args.nullNotPermitted(color, "color"); 156 this.itemLabelBackgroundColor = color ; 157 fireChangeEvent(true); 158 } 159 160 /** 161 * Returns the item label positioning. The default value is 162 * {@link ItemLabelPositioning#CENTRAL}. 163 * 164 * @return The item label positioning (never {@code null}). 165 * 166 * @since 1.3 167 */ 168 public ItemLabelPositioning getItemLabelPositioning() { 169 return itemLabelPositioning; 170 } 171 172 /** 173 * Sets the item label positioning and sends a change event to all 174 * registered listeners. 175 * 176 * @param positioning the new positioning ({@code null} not 177 * permitted). 178 * 179 * @since 1.3 180 */ 181 public void setItemLabelPositioning(ItemLabelPositioning positioning) { 182 Args.nullNotPermitted(positioning, "positioning"); 183 this.itemLabelPositioning = positioning; 184 fireChangeEvent(true); 185 } 186 187 /** 188 * Returns a flag that controls whether or not change events are sent to 189 * registered listeners. 190 * 191 * @return A boolean. 192 * 193 * @see #setNotify(boolean) 194 */ 195 public boolean isNotify() { 196 return this.notify; 197 } 198 199 /** 200 * Sets a flag that controls whether or not listeners receive 201 * {@link Renderer3DChangeEvent} notifications. 202 * 203 * @param notify a boolean. 204 * 205 * @see #isNotify() 206 */ 207 public void setNotify(boolean notify) { 208 this.notify = notify; 209 // if the flag is being set to true, there may be queued up changes... 210 if (notify) { 211 fireChangeEvent(true); 212 } 213 } 214 215 /** 216 * Receives a {@link ChartElementVisitor}. This is part of a general 217 * purpose mechanism for traversing the chart structure and performing 218 * operations on the elements in the structure. You won't normally call 219 * this method directly. 220 * 221 * @param visitor the visitor ({@code null} not permitted). 222 * 223 * @since 1.2 224 */ 225 @Override 226 public void receive(ChartElementVisitor visitor) { 227 visitor.visit(this); 228 } 229 230 /** 231 * Registers an object for notification of changes to the renderer. 232 * 233 * @param listener the object to be registered. 234 * 235 * @see #removeChangeListener(Renderer3DChangeListener) 236 */ 237 @Override 238 public void addChangeListener(Renderer3DChangeListener listener) { 239 this.listenerList.add(Renderer3DChangeListener.class, listener); 240 } 241 242 /** 243 * Unregisters an object for notification of changes to the renderer. 244 * 245 * @param listener the object to be unregistered. 246 * 247 * @see #addChangeListener(Renderer3DChangeListener) 248 */ 249 @Override 250 public void removeChangeListener(Renderer3DChangeListener listener) { 251 this.listenerList.remove(Renderer3DChangeListener.class, listener); 252 } 253 254 /** 255 * Notifies all registered listeners that the plot has been modified. 256 * 257 * @param event information about the change event. 258 */ 259 public void notifyListeners(Renderer3DChangeEvent event) { 260 // if the 'notify' flag has been switched to false, we don't notify 261 // the listeners 262 if (!this.notify) { 263 return; 264 } 265 Object[] listeners = this.listenerList.getListenerList(); 266 for (int i = listeners.length - 2; i >= 0; i -= 2) { 267 if (listeners[i] == Renderer3DChangeListener.class) { 268 ((Renderer3DChangeListener) listeners[i + 1]).rendererChanged( 269 event); 270 } 271 } 272 } 273 274 /** 275 * Sends a {@link Renderer3DChangeEvent} to all registered listeners. 276 * 277 * @param requiresWorldUpdate a flag indicating whether or not the change 278 * requires the 3D world to be updated. 279 */ 280 protected void fireChangeEvent(boolean requiresWorldUpdate) { 281 notifyListeners(new Renderer3DChangeEvent(this, requiresWorldUpdate)); 282 } 283 284 /** 285 * Tests this renderer for equality with an arbitrary object. The 286 * change listeners are NOT considered in the test, but the 287 * {@code notify} flag is taken into account. 288 * 289 * @param obj the object ({@code null} permitted). 290 * 291 * @return A boolean. 292 */ 293 @Override 294 public boolean equals(Object obj) { 295 if (obj == this) { 296 return true; 297 } 298 if (!(obj instanceof AbstractRenderer3D)) { 299 return false; 300 } 301 AbstractRenderer3D that = (AbstractRenderer3D) obj; 302 if (this.notify != that.notify) { 303 return false; 304 } 305 if (!this.itemLabelFont.equals(that.itemLabelFont)) { 306 return false; 307 } 308 if (!this.itemLabelColor.equals(that.itemLabelColor)) { 309 return false; 310 } 311 if (!this.itemLabelBackgroundColor.equals( 312 that.itemLabelBackgroundColor)) { 313 return false; 314 } 315 if (this.itemLabelPositioning != that.itemLabelPositioning) { 316 return false; 317 } 318 return true; 319 } 320}