00001
00002
00003
00004 package org.math.plot;
00005
00006 import java.awt.BorderLayout;
00007 import java.awt.Dimension;
00008 import java.awt.GridLayout;
00009 import java.awt.event.ActionEvent;
00010 import java.beans.PropertyChangeListener;
00011 import java.util.LinkedList;
00012 import java.util.Vector;
00013
00014 import javax.swing.Action;
00015 import javax.swing.BorderFactory;
00016 import javax.swing.ButtonGroup;
00017 import javax.swing.JCheckBox;
00018 import javax.swing.JComponent;
00019 import javax.swing.JFrame;
00020 import javax.swing.JList;
00021 import javax.swing.JPanel;
00022 import javax.swing.JRadioButton;
00023 import javax.swing.JScrollPane;
00024 import javax.swing.JSlider;
00025 import javax.swing.JTable;
00026 import javax.swing.event.ChangeEvent;
00027 import javax.swing.event.ChangeListener;
00028 import javax.swing.event.ListSelectionEvent;
00029 import javax.swing.event.ListSelectionListener;
00030 import javax.swing.event.TableModelListener;
00031 import javax.swing.table.TableModel;
00032
00033 import org.math.plot.utils.Array;
00034
00039 public class DataSelectTable extends JPanel {
00040
00041 private static final long serialVersionUID = 41918175232722331L;
00042
00043 LinkedList<ParameterRow> rows;
00044
00045 private Object[][] _data, _selecteddata;
00046
00047 private LinkedList<Object[]> _tmpselecteddata;
00048
00049 boolean dataUpdated = false;
00050
00051 private int[] _tmpselectedIndex;
00052
00053 private int _nbselected;
00054
00055 private int[] _selectedindex;
00056
00057 private String[] _parametersNames;
00058
00059 private JTable _table;
00060
00061 int _dimension;
00062
00063 public DataSelectTable(Object[][] data, int dimension, String... parametersNames) {
00064 _data = data;
00065 _dimension = dimension;
00066
00067 _parametersNames = parametersNames;
00068
00069 if (_dimension > parametersNames.length)
00070 throw new IllegalArgumentException("Number of parameters must be > to dimension=" + _dimension);
00071
00072 if (_dimension == 1)
00073 buildRows(0);
00074 else if (_dimension == 2)
00075 buildRows(0, 1);
00076 else if (_dimension == 3)
00077 buildRows(0, 1, 2);
00078
00079 add(new JScrollPane(_table));
00080
00081 }
00082
00083 LinkedList<String> header;
00084
00085 LinkedList<Class< ? >> columnclasses;
00086
00087 class Model implements TableModel {
00088
00089 public Model(int... selectedaxis) {
00090
00091 }
00092
00093 public void setValueAt(Object value, int rowIndex, int columnIndex) {
00094
00095
00096 }
00097
00098 public void removeTableModelListener(TableModelListener l) {
00099
00100
00101 }
00102
00103 public boolean isCellEditable(int rowIndex, int columnIndex) {
00104
00105 return false;
00106 }
00107
00108 public Object getValueAt(int rowIndex, int columnIndex) {
00109 if (columnIndex == 0)
00110 return _parametersNames[rowIndex];
00111 if (columnIndex == _dimension - 2)
00112 return rows.get(rowIndex).xaxis;
00113 if (columnIndex == _dimension - 1)
00114 return rows.get(rowIndex).yaxis;
00115 if (columnIndex == _dimension)
00116 return rows.get(rowIndex).zaxis;
00117
00118 return null;
00119 }
00120
00121 public int getRowCount() {
00122 return _parametersNames.length;
00123 }
00124
00125 public String getColumnName(int columnIndex) {
00126 return header.get(columnIndex);
00127 }
00128
00129 public int getColumnCount() {
00130 return header.size();
00131 }
00132
00133 public Class< ? > getColumnClass(int columnIndex) {
00134 return columnclasses.get(columnIndex);
00135 }
00136
00137 public void addTableModelListener(TableModelListener l) {
00138
00139
00140 }
00141
00142 }
00143
00144 void buildRows(int... selectedaxis) {
00145
00146 header = new LinkedList<String>();
00147 header.add("Parameter");
00148 if (_dimension <= 1)
00149 header.add("X");
00150 if (_dimension <= 2)
00151 header.add("Y");
00152 if (_dimension <= 3)
00153 header.add("Z");
00154 header.add("min");
00155 header.add("<>");
00156 header.add("=");
00157 header.add("<>");
00158 header.add("max");
00159
00160 columnclasses = new LinkedList<Class< ? >>();
00161 columnclasses.add(String.class);
00162 if (_dimension <= 1)
00163 columnclasses.add(Boolean.class);
00164 if (_dimension <= 2)
00165 columnclasses.add(Boolean.class);
00166 if (_dimension <= 3)
00167 columnclasses.add(Boolean.class);
00168 columnclasses.add(Double.class);
00169 columnclasses.add(JSlider.class);
00170 columnclasses.add(Boolean.class);
00171 columnclasses.add(JSlider.class);
00172 columnclasses.add(Double.class);
00173
00174 ButtonGroup xgrp = new ButtonGroup();
00175 ButtonGroup ygrp = new ButtonGroup();
00176 ButtonGroup zgrp = new ButtonGroup();
00177 rows = new LinkedList<ParameterRow>();
00178 for (int i = 0; i < _parametersNames.length; i++) {
00179 rows.add(new ParameterRow(_parametersNames[i], getColumn(i, _data)));
00180
00181 rows.get(i).xaxis.setSelected(selectedaxis[0] == i);
00182 if (selectedaxis.length >= 2)
00183 rows.get(i).yaxis.setSelected(selectedaxis[1] == i);
00184 if (selectedaxis.length == 3)
00185 rows.get(i).zaxis.setSelected(selectedaxis[2] == i);
00186
00187 xgrp.add(rows.get(i).xaxis);
00188 ygrp.add(rows.get(i).yaxis);
00189 zgrp.add(rows.get(i).zaxis);
00190 }
00191 updateSelectedData();
00192 }
00193
00194 public void setData(Object[][] data) {
00195 if (data[0].length != _data[0].length)
00196 throw new IllegalArgumentException("new data dimension is not consistent with previous one.");
00197 _data = data;
00198
00199 int[] selectedaxis = new int[_dimension];
00200 for (int i = 0; i < rows.size(); i++) {
00201 if (rows.get(i).xaxis.isSelected())
00202 selectedaxis[0] = i;
00203 if (selectedaxis.length >= 2)
00204 if (rows.get(i).yaxis.isSelected())
00205 selectedaxis[1] = i;
00206 if (selectedaxis.length == 3)
00207 if (rows.get(i).zaxis.isSelected())
00208 selectedaxis[2] = i;
00209 rows.remove(i);
00210 }
00211
00212 dataUpdated = false;
00213 buildRows(selectedaxis);
00214
00215 fireSelectedDataChanged("setData");
00216 }
00217
00218 void updateSelectedData() {
00219 if (dataUpdated)
00220 return;
00221
00222 for (ParameterRow row : rows) {
00223 boolean isaxis = row.xaxis.isSelected() || row.yaxis.isSelected() || row.zaxis.isSelected();
00224 if (row._isNumber) {
00225 row.min.setEnabled(!isaxis);
00226 row.max.setEnabled(!isaxis);
00227 } else
00228 row.list.setEnabled(!isaxis);
00229
00230
00231
00232
00233
00234
00235
00236
00237 }
00238
00239 _tmpselectedIndex = new int[_data.length];
00240 _nbselected = 0;
00241 _tmpselecteddata = new LinkedList<Object[]>();
00242 for (int i = 0; i < _data.length; i++) {
00243 boolean sel = true;
00244
00245
00246
00247
00248
00249
00250 if (sel) {
00251 _tmpselecteddata.add(_data[i]);
00252 _tmpselectedIndex[_nbselected] = i;
00253 _nbselected++;
00254
00255
00256
00257
00258 }
00259 }
00260 dataUpdated = true;
00261 }
00262
00264 public void fireSelectedDataChanged(String from) {
00265 System.out.println("fireSelectedDataChanged from " + from);
00266 Object[][] sel = getSelectedFullData();
00267 System.out.println("selected full data :");
00268 System.out.println(Array.cat(_parametersNames));
00269 if (sel.length > 0)
00270 System.out.println(Array.cat(getSelectedFullData()));
00271
00272 sel = getSelectedProjectedData();
00273 System.out.println("selected projected data :");
00274 switch (_dimension) {
00275 case 1:
00276 System.out.println(Array.cat(new String[] { getSelectedXAxis() }));
00277 break;
00278 case 2:
00279 System.out.println(Array.cat(new String[] { getSelectedXAxis(), getSelectedYAxis() }));
00280 break;
00281 case 3:
00282 System.out.println(Array.cat(new String[] { getSelectedXAxis(), getSelectedYAxis(), getSelectedZAxis() }));
00283 break;
00284 }
00285 if (sel.length > 0)
00286 System.out.println(Array.cat(getSelectedProjectedData()));
00287
00288 }
00289
00291 public int[] getSelectedDataIndex() {
00292 updateSelectedData();
00293 _selectedindex = new int[_nbselected];
00294 for (int i = 0; i < _nbselected; i++)
00295 _selectedindex[i] = _tmpselectedIndex[i];
00296 return _selectedindex;
00297 }
00298
00300 public Object[][] getSelectedFullData() {
00301 updateSelectedData();
00302 _selecteddata = new Object[_tmpselecteddata.size()][_data[0].length];
00303 for (int i = 0; i < _selecteddata.length; i++)
00304 for (int j = 0; j < _selecteddata[i].length; j++)
00305 _selecteddata[i][j] = _tmpselecteddata.get(i)[j];
00306 return _selecteddata;
00307 }
00308
00310 public Object[][] getSelectedProjectedData() {
00311 updateSelectedData();
00312 int[] selextedaxis = getSelectedAxisIndex();
00313 _selecteddata = new Object[_tmpselecteddata.size()][_dimension];
00314 for (int i = 0; i < _selecteddata.length; i++)
00315 for (int j = 0; j < _dimension; j++)
00316 _selecteddata[i][j] = _tmpselecteddata.get(i)[selextedaxis[j]];
00317 return _selecteddata;
00318 }
00319
00320 public int[] getSelectedAxisIndex() {
00321 int[] selextedaxis = new int[_dimension];
00322 updateSelectedData();
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 return selextedaxis;
00338 }
00339
00341 public String getSelectedXAxis() {
00342 updateSelectedData();
00343 for (ParameterRow row : rows)
00344 if (row.xaxis.isSelected())
00345 return row._paramName;
00346 return null;
00347 }
00348
00350 public String getSelectedYAxis() {
00351 updateSelectedData();
00352 for (ParameterRow row : rows)
00353 if (row.yaxis.isSelected())
00354 return row._paramName;
00355 return null;
00356 }
00357
00359 public String getSelectedZAxis() {
00360 updateSelectedData();
00361 for (ParameterRow row : rows)
00362 if (row.zaxis.isSelected())
00363 return row._paramName;
00364 return null;
00365 }
00366
00367 static Object[] getColumn(int j, Object[][] mat) {
00368 Object[] col = new Object[mat.length];
00369 for (int i = 0; i < col.length; i++)
00370 col[i] = mat[i][j];
00371 return col;
00372 }
00373
00374 class ParameterRow {
00375
00376
00377
00378 String _paramName;
00379
00380
00381
00382 JRadioButton xaxis, yaxis, zaxis;
00383
00384 JComponent parameter;
00385
00386 JSlider min, max;
00387
00388 JCheckBox linkminmax;
00389
00390 JList list;
00391
00392
00393
00394 Vector<Object> _kernelStringValues;
00395
00396 boolean _isNumber;
00397
00398
00399
00400 double[] _kernelDoubleValues;
00401
00402 public ParameterRow(String paramName, Object[] values) {
00403 _paramName = paramName;
00404 _isNumber = Array.isDouble(values[0].toString());
00405
00406 if (!_isNumber) {
00407 _kernelStringValues = new Vector<Object>(values.length);
00408 for (int i = 0; i < values.length; i++)
00409 if (!_kernelStringValues.contains(values[i]))
00410 _kernelStringValues.add(values[i]);
00411 } else {
00412 Vector<Double> _tmpdvalues = new Vector<Double>(values.length);
00413 for (int i = 0; i < values.length; i++)
00414 if (!_tmpdvalues.contains(Double.valueOf(values[i].toString())))
00415 _tmpdvalues.add(Double.valueOf(values[i].toString()));
00416
00417 _kernelDoubleValues = new double[_tmpdvalues.size()];
00418 for (int i = 0; i < _kernelDoubleValues.length; i++)
00419 _kernelDoubleValues[i] = _tmpdvalues.get(i);
00420 }
00421
00422 setLayout(new GridLayout(1, 2));
00423
00424
00425
00426
00427 JPanel type = new JPanel(new BorderLayout());
00428
00429 JPanel XYZ = new JPanel(new GridLayout(_dimension, 1));
00430 xaxis = new JRadioButton("X");
00431 xaxis.addActionListener(new Action() {
00432 public void actionPerformed(ActionEvent e) {
00433 yaxis.setSelected(false);
00434 zaxis.setSelected(false);
00435 for (ParameterRow r : rows)
00436 if (!r._paramName.equals(_paramName))
00437 r.xaxis.setSelected(false);
00438 dataUpdated = false;
00439 fireSelectedDataChanged(_paramName + " xaxis");
00440 }
00441
00442 public void setEnabled(boolean b) {
00443 }
00444
00445 public void removePropertyChangeListener(PropertyChangeListener listener) {
00446 }
00447
00448 public void putValue(String key, Object value) {
00449 }
00450
00451 public boolean isEnabled() {
00452 return true;
00453 }
00454
00455 public Object getValue(String key) {
00456 return null;
00457 }
00458
00459 public void addPropertyChangeListener(PropertyChangeListener listener) {
00460 }
00461 });
00462 XYZ.add(xaxis);
00463 yaxis = new JRadioButton("Y");
00464 yaxis.addActionListener(new Action() {
00465 public void actionPerformed(ActionEvent e) {
00466 xaxis.setSelected(false);
00467 zaxis.setSelected(false);
00468 for (ParameterRow r : rows)
00469 if (!r._paramName.equals(_paramName))
00470 r.yaxis.setSelected(false);
00471 dataUpdated = false;
00472 fireSelectedDataChanged(_paramName + " yaxis");
00473
00474 }
00475
00476 public void setEnabled(boolean b) {
00477 }
00478
00479 public void removePropertyChangeListener(PropertyChangeListener listener) {
00480 }
00481
00482 public void putValue(String key, Object value) {
00483 }
00484
00485 public boolean isEnabled() {
00486 return true;
00487 }
00488
00489 public Object getValue(String key) {
00490 return null;
00491 }
00492
00493 public void addPropertyChangeListener(PropertyChangeListener listener) {
00494 }
00495 });
00496 if (_dimension >= 2)
00497 XYZ.add(yaxis);
00498
00499 zaxis = new JRadioButton("Z");
00500 zaxis.addActionListener(new Action() {
00501 public void actionPerformed(ActionEvent e) {
00502 xaxis.setSelected(false);
00503 yaxis.setSelected(false);
00504 for (ParameterRow r : rows)
00505 if (!r._paramName.equals(_paramName))
00506 r.zaxis.setSelected(false);
00507 dataUpdated = false;
00508 fireSelectedDataChanged(_paramName + " zaxis");
00509 }
00510
00511 public void setEnabled(boolean b) {
00512 }
00513
00514 public void removePropertyChangeListener(PropertyChangeListener listener) {
00515 }
00516
00517 public void putValue(String key, Object value) {
00518 }
00519
00520 public boolean isEnabled() {
00521 return true;
00522 }
00523
00524 public Object getValue(String key) {
00525 return null;
00526 }
00527
00528 public void addPropertyChangeListener(PropertyChangeListener listener) {
00529 }
00530 });
00531 if (_dimension == 3)
00532 XYZ.add(zaxis);
00533
00534 type.add(XYZ, BorderLayout.WEST);
00535
00536 if (_isNumber) {
00537 parameter = new JPanel();
00538 parameter.setLayout(new GridLayout(2, 1));
00539
00540 min = new JSlider(1, _kernelDoubleValues.length, 1);
00541
00542 min.setMinorTickSpacing(1);
00543 min.setSnapToTicks(true);
00544 min.setPaintTicks(true);
00545 max = new JSlider(1, _kernelDoubleValues.length, _kernelDoubleValues.length);
00546 max.setMinorTickSpacing(1);
00547 max.setSnapToTicks(true);
00548 max.setPaintTicks(true);
00549 min.addChangeListener(new ChangeListener() {
00550 public void stateChanged(ChangeEvent e) {
00551 if (max.getValue() < min.getValue())
00552 max.setValue(min.getValue());
00553 dataUpdated = false;
00554 fireSelectedDataChanged(_paramName + " min");
00555
00556 }
00557 });
00558 max.addChangeListener(new ChangeListener() {
00559 public void stateChanged(ChangeEvent e) {
00560 if (max.getValue() < min.getValue())
00561 min.setValue(max.getValue());
00562 dataUpdated = false;
00563 fireSelectedDataChanged(_paramName + " max");
00564
00565 }
00566 });
00567 parameter.add(min, 0);
00568 parameter.add(max, 1);
00569 } else {
00570
00571 list = new JList(_kernelStringValues);
00572 list.setSelectedIndices(buildIntSeq(0, _kernelStringValues.size() - 1));
00573 list.addListSelectionListener(new ListSelectionListener() {
00574 public void valueChanged(ListSelectionEvent e) {
00575 dataUpdated = false;
00576 fireSelectedDataChanged(_paramName + " list");
00577 }
00578 });
00579 parameter = new JScrollPane(list);
00580 }
00581 type.add(parameter, BorderLayout.CENTER);
00582 add(type, 1);
00583
00584 setBorder(BorderFactory.createEtchedBorder());
00585 setPreferredSize(new Dimension(400, 60));
00586
00587 }
00588
00589 int[] buildIntSeq(int min, int max) {
00590 int[] seq = new int[max - min + 1];
00591 for (int i = 0; i < seq.length; i++)
00592 seq[i] = min + i;
00593 return seq;
00594 }
00595
00596 boolean check(Object value) {
00597 if (_isNumber) {
00598 double dval = Double.valueOf(value.toString());
00599 return (dval >= _kernelDoubleValues[min.getValue() - 1] && dval <= _kernelDoubleValues[max.getValue() - 1]);
00600 } else {
00601 for (int i = 0; i < list.getSelectedIndices().length; i++) {
00602 if (_kernelStringValues.get(list.getSelectedIndices()[i]).equals(value))
00603 return true;
00604 }
00605 return false;
00606 }
00607 }
00608
00609 }
00610
00611 public static void main(String[] args) {
00612 final PlotPanel pp = new Plot3DPanel(PlotPanel.WEST);
00613 pp.setPreferredSize(new Dimension(400, 400));
00614 new FrameView(pp).setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
00615
00616 Object[][] data = { { 0, 0, 0, 0, "a0" }, { 1, 1, 1, 1, "a1" }, { 2, 2, 2, 2, "a2" }, { 3, 3, 3, 3, "a3" }, { 4, 3, 3, 3, "a3" }, { 5, 3, 3, 3, "a4" } };
00617
00618 DataSelectTable dsp = new DataSelectTable(data, 3, "x1", "x2", "x3", "x4", "x5") {
00619 private static final long serialVersionUID = 1L;
00620
00621 @Override
00622 public void fireSelectedDataChanged(String from) {
00623 super.fireSelectedDataChanged(from);
00624 pp.setAxisLabel(0, getSelectedXAxis());
00625 pp.setAxisLabel(1, getSelectedYAxis());
00626 pp.setAxisLabel(2, getSelectedZAxis());
00627
00628 if (pp.getPlots().size() == 0)
00629 pp.addPlot("SCATTER", "data", pp.mapData(getSelectedProjectedData()));
00630 else {
00631 if (from.endsWith("axis")) {
00632 pp.resetMapData();
00633 pp.removeAllPlots();
00634 pp.addPlot("SCATTER", "data", pp.mapData(getSelectedProjectedData()));
00635 } else
00636 pp.getPlot(0).setData(pp.mapData(getSelectedProjectedData()));
00637 }
00638
00639 }
00640 };
00641 new FrameView(dsp).setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652 }
00653
00654 }