001: /**
002: * Chart2D, a java library for drawing two dimensional charts.
003: * Copyright (C) 2001 Jason J. Simas
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: *
018: * The author of this library may be contacted at:
019: * E-mail: jjsimas@users.sourceforge.net
020: * Street Address: J J Simas, 887 Tico Road, Ojai, CA 93023-3555 USA
021: */package net.sourceforge.chart2d;
022:
023: import java.awt.Color;
024: import java.awt.Dimension;
025: import java.awt.Font;
026: import java.util.Vector;
027:
028: /**
029: * A data structure for holding the properties common to all Chart2D charts.
030: * Chart2D charts are all capable of having a legend.
031: * Pass this to any number of Chart2D objects.
032: */
033: public final class Chart2DProperties extends Properties {
034:
035: /**
036: * The number is 38.
037: */
038: public static final int MAX_INTEGER = 38;
039:
040: /**
041: * The number is -38.
042: */
043: public static final int MAX_FLOAT = -38;
044:
045: /**
046: * The default is MAX_INTEGER.
047: */
048: public final static int CHART_DATA_LABELS_PRECISION_DEFAULT = MAX_INTEGER;
049:
050: /**
051: * The default is true.
052: */
053: public final static boolean CHART_BETWEEN_CHART_AND_LEGEND_GAP_EXISTENCE_DEFAULT = true;
054:
055: /**
056: * The default is 5.
057: */
058: public final static int CHART_BETWEEN_CHART_AND_LEGEND_GAP_THICKNESS_MODEL_DEFAULT = 5;
059:
060: private int chartDataLabelsPrecision;
061: private boolean chartBetweenChartAndLegendGapExistence;
062: private int chartBetweenChartAndLegendGapThicknessModel;
063:
064: private boolean needsUpdate = true;
065: private final Vector chart2DVector = new Vector(5, 5);
066: private final Vector needsUpdateVector = new Vector(5, 5);
067:
068: /**
069: * Creates a Chart2DProperties object with the documented default values.
070: */
071: public Chart2DProperties() {
072:
073: needsUpdate = true;
074: setChart2DPropertiesToDefaults();
075: }
076:
077: /**
078: * Creates a Chart2DProperties object with property values copied from another object.
079: * The copying is a deep copy.
080: * @param chart2DProps The properties to copy.
081: */
082: public Chart2DProperties(Chart2DProperties chart2DProps) {
083:
084: needsUpdate = true;
085: setChart2DProperties(chart2DProps);
086: }
087:
088: /**
089: * Sets all properties to their default values.
090: */
091: public final void setChart2DPropertiesToDefaults() {
092:
093: needsUpdate = true;
094: setChartDataLabelsPrecision(CHART_DATA_LABELS_PRECISION_DEFAULT);
095: setChartBetweenChartAndLegendGapExistence(CHART_BETWEEN_CHART_AND_LEGEND_GAP_EXISTENCE_DEFAULT);
096: setChartBetweenChartAndLegendGapThicknessModel(CHART_BETWEEN_CHART_AND_LEGEND_GAP_THICKNESS_MODEL_DEFAULT);
097: }
098:
099: /**
100: * Sets all properties to be the values of another Chart2DProperties object.
101: * The copying is a deep copy.
102: * @param chart2DProps The properties to copy.
103: */
104: public final void setChart2DProperties(
105: Chart2DProperties chart2DProps) {
106:
107: needsUpdate = true;
108: setChartDataLabelsPrecision(chart2DProps
109: .getChartDataLabelsPrecision());
110: setChartBetweenChartAndLegendGapExistence(chart2DProps
111: .getChartBetweenChartAndLegendGapExistence());
112: setChartBetweenChartAndLegendGapThicknessModel(chart2DProps
113: .getChartBetweenChartAndLegendGapThicknessModel());
114: }
115:
116: /**
117: * Sets the look of labels that are supposed to describe the value of the
118: * data. For example, for pie charts this method will influence
119: * the labels that surround the chart, and for charts with axes this method
120: * will influence the labels on the numbers axis. The specific labels are
121: * first determined from the greatest and least value in the data set and
122: * other factors. This method then lets you adjust whether you want integer
123: * or floating point labels and how exact you want those labels to be. You
124: * do this using the precision parameter, and passing values between 38 and -38.
125: * Nonnegative ints indicate the labels will not contain
126: * a decimal (ie will be integer labels), and the specific nonnegative
127: * number indicates how many zeroes will be to the left of the decimal if
128: * it were there (ex. for the number 1976, a precision of 0 would return 1976,
129: * a precision of 1 would return 1980, a precision of 3 would return 2000, and
130: * a precision greater than 3 would also return 2000). If the number of
131: * desired zeroes is greater than the label, then the number of zeroes is
132: * automatically scaled back to be 1 less than the number of digits. Negative
133: * ints for precision indicate the labels will contain a decimal, and the
134: * specific negative number indicates how many digits to the right of the
135: * decimal are wanted (ex. for the number 1.935, a precision of -1 would
136: * return 1.9, a precision of -2 would return 1.94, a precision of -4 would
137: * return 1.9350). If the number of desired decimal places is larger than the
138: * number of places present in the number, then zeroes are added to form as
139: * many places as are desired up to -38. MAX_INTEGER or MAX_FLOAT will always
140: * indicate the maximum number of zeroes and the maximum number of decimal
141: * places possible by Chart2D's algorithm for adjusting these labels.
142: * @param precision The adjustement of the precision of numbers labels.
143: */
144: public final void setChartDataLabelsPrecision(int precision) {
145:
146: needsUpdate = true;
147: chartDataLabelsPrecision = precision;
148: }
149:
150: /**
151: * Sets whether the gap between the chart and the legend exists.
152: * If the legend doesn't exist, this gap will automatically not exist.
153: * @param existence If true, the gap exists.
154: */
155: public final void setChartBetweenChartAndLegendGapExistence(
156: boolean existence) {
157:
158: needsUpdate = true;
159: chartBetweenChartAndLegendGapExistence = existence;
160: }
161:
162: /**
163: * Sets the thickness of the gap between the chart and the legend for the chart's model size.
164: * @param thickness The model thickness of the gap.
165: */
166: public final void setChartBetweenChartAndLegendGapThicknessModel(
167: int thickness) {
168:
169: needsUpdate = true;
170: chartBetweenChartAndLegendGapThicknessModel = thickness;
171: }
172:
173: /**
174: * Gets the look of labels that are supposed to describe the value of the
175: * data. For example, for pie charts this method will influence
176: * the labels that surround the chart, and for charts with axes this method
177: * will influence the labels on the numbers axis. The specific labels are
178: * first determined from the greatest and least value in the data set and
179: * other factors. This method then lets you adjust whether you want integer
180: * or floating point labels and how exact you want those labels to be. You
181: * do this using the precision parameter, and passing values between 8 and -8.
182: * Nonnegative ints indicate the labels will not contain
183: * a decimal (ie will be integer labels), and the specific nonnegative
184: * number indicates how many zeroes will be to the left of the decimal if
185: * it were there (ex. for the number 1976, a precision of 0 would return 1976,
186: * a precision of 1 would return 1980, a precision of 3 would return 2000, and
187: * a precision greater than 3 would also return 2000). If the number of
188: * desired zeroes is greater than the label, then the number of zeroes is
189: * automatically scaled back to be 1 less than the number of digits. Negative
190: * ints for precision indicate the labels will contain a decimal, and the
191: * specific negative number indicates how many digits to the right of the
192: * decimal are wanted (ex. for the number 1.935, a precision of -1 would
193: * return 1.9, a precision of -2 would return 1.94, a precision of -4 would
194: * return 1.9350). If the number of desired decimal places is larger than the
195: * number of places present in the number, then zeroes are added to form as
196: * many places as are desired up to -8. MAX_INTEGER or MAX_FLOAT will always
197: * indicate the maximum number of zeroes and the maximum number of decimal
198: * places possible by Chart2D's algorithm for adjusting these labels.
199: * @return The adjustement of the precision of numbers labels.
200: */
201: public final int getChartDataLabelsPrecision() {
202: return chartDataLabelsPrecision;
203: }
204:
205: /**
206: * Gets whether the gap between the chart and the legend exists.
207: * If the legend doesn't exist, this gap will automatically not exist.
208: * @return If true, the gap exists.
209: */
210: public final boolean getChartBetweenChartAndLegendGapExistence() {
211: return chartBetweenChartAndLegendGapExistence;
212: }
213:
214: /**
215: * Gets the thickness of the gap between the chart and the legend for the chart's model size.
216: * @return The model thickness of the gap.
217: */
218: public final int getChartBetweenChartAndLegendGapThicknessModel() {
219: return chartBetweenChartAndLegendGapThicknessModel;
220: }
221:
222: /**
223: * Gets whether this object needs to be updated with new properties.
224: * @param chart2D The object that may need to be updated.
225: * @return If true then needs update.
226: */
227: final boolean getChart2DNeedsUpdate(Chart2D chart2D) {
228:
229: if (needsUpdate)
230: return true;
231: int index = -1;
232: if ((index = chart2DVector.indexOf(chart2D)) != -1) {
233: return ((Boolean) needsUpdateVector.get(index))
234: .booleanValue();
235: }
236: return false;
237: }
238:
239: /**
240: * Adds a Chart2D to the set of objects using these properties.
241: * @param chart2D The object to add.
242: */
243: final void addChart2D(Chart2D chart2D) {
244: if (!chart2DVector.contains(chart2D)) {
245: chart2DVector.add(chart2D);
246: needsUpdateVector.add(new Boolean(true));
247: }
248: }
249:
250: /**
251: * Removes a Chart2D from the set of objects using these properties.
252: * @param chart2D The object to remove.
253: */
254: final void removeChart2D(Chart2D chart2D) {
255: int index = -1;
256: if ((index = chart2DVector.indexOf(chart2D)) != -1) {
257: chart2DVector.remove(index);
258: needsUpdateVector.remove(index);
259: }
260: }
261:
262: /**
263: * Validates the properties of this object.
264: * If debug is true then prints a messages indicating whether each property is valid.
265: * Returns true if all the properties were valid and false otherwise.
266: * @param debug If true then will print status messages.
267: * @return If true then valid.
268: */
269: final boolean validate(boolean debug) {
270:
271: if (debug)
272: System.out.println("Validating Chart2DProperties");
273:
274: boolean valid = true;
275:
276: if (chartDataLabelsPrecision > MAX_INTEGER
277: || chartDataLabelsPrecision < MAX_FLOAT) {
278: valid = false;
279: if (debug)
280: System.out
281: .println("Problem with ChartDataLabelsPrecision");
282: }
283: if (chartBetweenChartAndLegendGapThicknessModel < 0) {
284: valid = false;
285: if (debug)
286: System.out
287: .println("ChartBetweenChartAndLegendGapThicknessModel < 0");
288: }
289:
290: if (debug) {
291: if (valid)
292: System.out.println("Chart2DProperties was valid");
293: else
294: System.out.println("Chart2DProperties was invalid");
295: }
296:
297: return valid;
298: }
299:
300: /**
301: * Updates the properties of this Chart2D.
302: * @param chart2D The Chart2D to update.
303: */
304: final void updateChart2D(Chart2D chart2D) {
305:
306: if (getChart2DNeedsUpdate(chart2D)) {
307:
308: if (needsUpdate) {
309: for (int i = 0; i < needsUpdateVector.size(); ++i) {
310: needsUpdateVector.set(i, new Boolean(true));
311: }
312: needsUpdate = false;
313: }
314:
315: int index = -1;
316: if ((index = chart2DVector.indexOf(chart2D)) != -1) {
317: needsUpdateVector.set(index, new Boolean(false));
318: }
319: }
320: }
321: }
|