001: package JSci.awt;
002:
003: import java.util.ArrayList;
004: import java.util.List;
005: import javax.swing.event.TableModelEvent;
006: import javax.swing.event.TableModelListener;
007: import javax.swing.table.AbstractTableModel;
008:
009: /**
010: * The DefaultGraph2DModel class provides a default implementation
011: * of the Graph2DModel interface.
012: * @version 1.2
013: * @author Mark Hale
014: */
015: public final class DefaultGraph2DModel extends AbstractGraphModel
016: implements Graph2DModel, TableModelListener {
017: private static final int X_AXIS_COLUMN = 0;
018: private static final int SERIES_COLUMN = 1;
019:
020: private float defaultXAxis[] = new float[0];
021: private final List series = new ArrayList();
022: private int pos = 0;
023: private DataSeries curSeries = null;
024:
025: public DefaultGraph2DModel() {
026: }
027:
028: /**
029: * Sets the default x-axis values.
030: * A copy of the values is made.
031: * This method does not change the x-axis values of any data series
032: * and so does not fire any events.
033: */
034: public void setXAxis(float x[]) {
035: if (defaultXAxis.length != x.length)
036: defaultXAxis = new float[x.length];
037: System.arraycopy(x, 0, defaultXAxis, 0, x.length);
038: }
039:
040: /**
041: * Sets the default x-axis values.
042: * A copy of the values is made.
043: * This method does not change the x-axis values of any data series
044: * and so does not fire any events.
045: */
046: public void setXAxis(double x[]) {
047: if (defaultXAxis.length != x.length)
048: defaultXAxis = new float[x.length];
049: for (int i = 0; i < x.length; i++)
050: defaultXAxis[i] = (float) x[i];
051: }
052:
053: /**
054: * Sets the default x-axis values.
055: * This method does not change the x-axis values of any data series
056: * and so does not fire any events.
057: * @param a start of interval.
058: * @param b end of interval.
059: * @param n number of values.
060: */
061: public void setXAxis(float a, float b, int n) {
062: if (defaultXAxis.length != n)
063: defaultXAxis = new float[n];
064: final float scale = (b - a) / (n - 1);
065: for (int i = 0; i < n; i++)
066: defaultXAxis[i] = scale * i + a;
067: }
068:
069: /**
070: * Adds a data series using the default values for the x-axis.
071: * Be sure to call {@link #setXAxis(float[]) setXAxis} first.
072: */
073: public void addSeries(float newSeries[]) {
074: addSeries(new DataSeries(defaultXAxis, newSeries));
075: }
076:
077: /**
078: * Adds a data series using the default values for the x-axis.
079: * Be sure to call {@link #setXAxis(double[]) setXAxis} first.
080: */
081: public void addSeries(double newSeries[]) {
082: addSeries(new DataSeries(defaultXAxis, newSeries));
083: }
084:
085: /**
086: * Adds a data series.
087: */
088: public void addSeries(DataSeries newSeries) {
089: series.add(newSeries);
090: fireGraphDataChanged();
091: newSeries.addTableModelListener(this );
092: }
093:
094: /**
095: * Adds a data series.
096: * Convenience method.
097: */
098: public void addSeries(float newXAxis[], float newSeries[]) {
099: addSeries(new DataSeries(newXAxis, newSeries));
100: }
101:
102: /**
103: * Adds a data series.
104: * Convenience method.
105: */
106: public void addSeries(float newXAxis[], double newSeries[]) {
107: addSeries(new DataSeries(newXAxis, newSeries));
108: }
109:
110: /**
111: * Changes a data series.
112: */
113: public void changeSeries(int i, DataSeries newSeries) {
114: getSeries(i).removeTableModelListener(this );
115: series.set(i, newSeries);
116: fireGraphDataChanged();
117: newSeries.addTableModelListener(this );
118: }
119:
120: /**
121: * Changes a data series.
122: * Convenience method.
123: */
124: public void changeSeries(int i, float newSeries[]) {
125: getSeries(i).setValues(newSeries);
126: }
127:
128: /**
129: * Changes a data series.
130: * Convenience method.
131: */
132: public void changeSeries(int i, double newSeries[]) {
133: getSeries(i).setValues(newSeries);
134: }
135:
136: /**
137: * Remove a data series.
138: */
139: public void removeSeries(int i) {
140: getSeries(i).removeTableModelListener(this );
141: series.remove(i);
142: fireGraphDataChanged();
143: }
144:
145: public DataSeries getSeries(int i) {
146: return (DataSeries) series.get(i);
147: }
148:
149: /**
150: * Convenience method.
151: */
152: public void setSeriesVisible(int i, boolean flag) {
153: getSeries(i).setVisible(flag);
154: }
155:
156: /**
157: * Implementation of TabelModelListener.
158: * Application code will not use this method explicitly, it is used internally.
159: */
160: public void tableChanged(TableModelEvent evt) {
161: if (evt.getColumn() == SERIES_COLUMN)
162: fireGraphSeriesUpdated(series.indexOf(evt.getSource()));
163: else
164: fireGraphDataChanged();
165: }
166:
167: // Graph2DModel interface
168:
169: public float getXCoord(int i) {
170: return curSeries.getXCoord(i);
171: }
172:
173: public float getYCoord(int i) {
174: return curSeries.getValue(i);
175: }
176:
177: public int seriesLength() {
178: return curSeries.length();
179: }
180:
181: public void firstSeries() {
182: curSeries = getSeries(0);
183: for (pos = 0; !curSeries.isVisible() && pos < series.size() - 1;)
184: curSeries = getSeries(++pos);
185: }
186:
187: public boolean nextSeries() {
188: if (pos == series.size() - 1)
189: return false;
190: do {
191: curSeries = getSeries(++pos);
192: } while (!curSeries.isVisible() && pos < series.size() - 1);
193: return curSeries.isVisible();
194: }
195:
196: /**
197: * The DataSeries class encapsulates a data series for a graph.
198: */
199: public static class DataSeries extends AbstractTableModel {
200: protected float xAxis[] = new float[0];
201: protected float series[] = new float[0];
202: private boolean isVis = true;
203:
204: protected DataSeries() {
205: }
206:
207: public DataSeries(float xValues[], float yValues[]) {
208: setXAxis(xValues);
209: setValues(yValues);
210: }
211:
212: public DataSeries(float xValues[], double yValues[]) {
213: setXAxis(xValues);
214: setValues(yValues);
215: }
216:
217: public DataSeries(double xValues[], double yValues[]) {
218: setXAxis(xValues);
219: setValues(yValues);
220: }
221:
222: public void setXAxis(float xValues[]) {
223: if (xAxis.length != xValues.length)
224: xAxis = new float[xValues.length];
225: System.arraycopy(xValues, 0, xAxis, 0, xValues.length);
226: fireTableColumnUpdated(X_AXIS_COLUMN);
227: }
228:
229: public void setXAxis(double xValues[]) {
230: if (xAxis.length != xValues.length)
231: xAxis = new float[xValues.length];
232: for (int i = 0; i < xValues.length; i++)
233: xAxis[i] = (float) xValues[i];
234: fireTableColumnUpdated(X_AXIS_COLUMN);
235: }
236:
237: public void setValues(float yValues[]) {
238: if (series.length != yValues.length)
239: series = new float[yValues.length];
240: System.arraycopy(yValues, 0, series, 0, yValues.length);
241: fireTableColumnUpdated(SERIES_COLUMN);
242: }
243:
244: public void setValues(double yValues[]) {
245: if (series.length != yValues.length)
246: series = new float[yValues.length];
247: for (int i = 0; i < yValues.length; i++)
248: series[i] = (float) yValues[i];
249: fireTableColumnUpdated(SERIES_COLUMN);
250: }
251:
252: public float getXCoord(int i) {
253: return xAxis[i];
254: }
255:
256: public void setXCoord(int i, float x) {
257: xAxis[i] = x;
258: fireTableCellUpdated(i, X_AXIS_COLUMN);
259: }
260:
261: public float getValue(int i) {
262: return series[i];
263: }
264:
265: public void setValue(int i, float y) {
266: series[i] = y;
267: fireTableCellUpdated(i, SERIES_COLUMN);
268: }
269:
270: public int length() {
271: return Math.min(xAxis.length, series.length);
272: }
273:
274: public final void setVisible(boolean flag) {
275: if (flag != isVis) {
276: isVis = flag;
277: fireTableDataChanged();
278: }
279: }
280:
281: public final boolean isVisible() {
282: return isVis;
283: }
284:
285: private void fireTableColumnUpdated(int column) {
286: if (column == X_AXIS_COLUMN)
287: fireTableChanged(new TableModelEvent(this , 0,
288: xAxis.length - 1, column));
289: else if (column == SERIES_COLUMN)
290: fireTableChanged(new TableModelEvent(this , 0,
291: series.length - 1, column));
292: }
293:
294: // TableModelInterface
295:
296: public String getColumnName(int col) {
297: if (col == X_AXIS_COLUMN)
298: return "X";
299: else if (col == SERIES_COLUMN)
300: return "Y";
301: else
302: return null;
303: }
304:
305: public Class getColumnClass(int col) {
306: return Float.class;
307: }
308:
309: public final int getRowCount() {
310: return length();
311: }
312:
313: public final int getColumnCount() {
314: return 2;
315: }
316:
317: public Object getValueAt(int row, int col) {
318: if (col == X_AXIS_COLUMN)
319: return new Float(getXCoord(row));
320: else if (col == SERIES_COLUMN)
321: return new Float(getValue(row));
322: else
323: return null;
324: }
325:
326: public void setValueAt(Object value, int row, int col) {
327: if (col == X_AXIS_COLUMN)
328: setXCoord(row, ((Float) value).floatValue());
329: else if (col == SERIES_COLUMN)
330: setValue(row, ((Float) value).floatValue());
331: }
332:
333: public boolean isCellEditable(int row, int col) {
334: return true;
335: }
336: }
337: }
|