package org.chesmapper.view.gui.table;
import java.awt.Component;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;
import org.chesmapper.map.dataInterface.CompoundProperty;
import org.chesmapper.map.dataInterface.NominalProperty;
import org.chesmapper.map.dataInterface.NumericProperty;
import org.chesmapper.view.cluster.ClusterController;
import org.chesmapper.view.cluster.Clustering;
import org.chesmapper.view.gui.ViewControler;
import org.chesmapper.view.gui.util.CompoundPropertyHighlighter;
import org.chesmapper.view.gui.util.Highlighter;
import org.mg.javalib.util.CountedSet;
import org.mg.javalib.util.DoubleArraySummary;
import org.mg.javalib.util.StringUtil;
public class FeatureTable extends DataTable
{
List<Highlighter> highlighters;
public FeatureTable(ViewControler viewControler, ClusterController clusterControler, Clustering clustering)
{
super(viewControler, clusterControler, clustering);
}
protected JTable createTable()
{
table = new JTable(tableModel);
sorter = new TableRowSorter<DefaultTableModel>();
table.setRowSorter(sorter);
sorter.setModel(tableModel);
table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.getSelectionModel().addListSelectionListener(new ListSelectionListener()
{
@Override
public void valueChanged(ListSelectionEvent e)
{
if (selfUpdate)
return;
int row = table.getSelectedRow();
if (row != -1)
{
row = sorter.convertRowIndexToModel(row);
Highlighter p = (Highlighter) tableModel.getValueAt(row, 1);
viewControler.setHighlighter(p);
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
table.requestFocus();
}
});
}
}
});
table.setDefaultRenderer(Double.class, new DefaultTableCellRenderer()
{
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column)
{
return super.getTableCellRendererComponent(table,
value instanceof Double ? StringUtil.formatDouble((Double) value) : value, isSelected,
hasFocus, row, column);
}
});
viewControler.addViewListener(new PropertyChangeListener()
{
@Override
public void propertyChange(PropertyChangeEvent evt)
{
if (selfUpdate)
return;
if (!FeatureTable.this.isVisible())
return;
if (evt.getPropertyName().equals(ViewControler.PROPERTY_HIGHLIGHT_CHANGED))
updateFeatureSelection();
}
});
// for (Dimensions d : Dimensions.values())
// model.addColumn(d + " Emb-Qual");
highlighters = new ArrayList<Highlighter>();
for (Highlighter[] hh : viewControler.getHighlighters().values())
for (Highlighter h : hh)
highlighters.add(h);
// final DoubleKeyHashMap<Dimensions, CompoundProperty, CompoundPropertyEmbedQuality> embMap = new DoubleKeyHashMap<EmbedUtil.Dimensions, CompoundProperty, EmbedUtil.CompoundPropertyEmbedQuality>();
int count = 0;
for (Highlighter h : highlighters)
{
Object o[] = new Object[11];// + Dimensions.values().length];
int i = 0;
o[i++] = ++count;
o[i++] = h;
if (h instanceof CompoundPropertyHighlighter)
{
CompoundProperty p = ((CompoundPropertyHighlighter) h).getProperty();
String map;
if (clustering.getFeatures().contains(p))
{
if (p.numDistinctValues() <= 1)
map = "ignored (single-valued)";
else if (p.getRedundantProp() != null)
map = "ignored (redundant)";
else
map = "yes";
}
else
map = "no";
o[i++] = map;
o[i++] = (p.isUndefined() ? "undef." : (p instanceof NumericProperty ? "Numeric" : "Nominal"));
o[i++] = clustering.numMissingValues(p);
o[i++] = clustering.numDistinctValues(p);
if (p instanceof NumericProperty)
{
DoubleArraySummary s = DoubleArraySummary.create(clustering.getDoubleValues((NumericProperty) p));
o[i++] = Double.isNaN(s.getMin()) ? null : s.getMin();
o[i++] = Double.isNaN(s.getMedian()) ? null : s.getMedian();
o[i++] = Double.isNaN(s.getStdev()) ? null : s.getStdev();
o[i++] = Double.isNaN(s.getMax()) ? null : s.getMax();
o[i++] = null;
}
else
{
o[i++] = null;
o[i++] = null;
o[i++] = null;
o[i++] = null;
CountedSet<String> set = CountedSet
.fromArray(clustering.getStringValues((NominalProperty) p, null));
o[i++] = set.toString();
}
// for (Dimensions d : Dimensions.values())
// {
// embMap.put(d, p, embedQuality.get(p).clone());
// o[i++] = embMap.get(d, p);
// }
}
else
{
for (; i < o.length; i++)
o[i] = null;
}
tableModel.addRow(o);
}
updateFeatureSelection();
return table;
}
@Override
protected String getShortName()
{
return "feature-table";
}
@Override
protected DefaultTableModel createTableModel()
{
DefaultTableModel model = new DefaultTableModel()
{
@Override
public Class<?> getColumnClass(int columnIndex)
{
if (columnIndex == 0)
return Integer.class;
if (columnIndex == 1)
return Highlighter.class;
if (columnIndex == 4 || columnIndex == 5)
return Integer.class;
if (columnIndex >= 6 || columnIndex <= 8)
return Double.class;
// if (columnIndex >= 5 || columnIndex <= 8)
// return CompoundPropertyEmbedQuality.class;
return String.class;
}
@Override
public boolean isCellEditable(int row, int column)
{
return false;
}
};
model.addColumn("");
model.addColumn("Feature");
model.addColumn("Used for Mapping");
model.addColumn("Type");
model.addColumn("#Missing");
model.addColumn("#Distinct");
model.addColumn("Min");
model.addColumn("Median");
model.addColumn("Stdev");
model.addColumn("Max");
model.addColumn("Values");
return model;
}
@Override
protected boolean addSpecificityInfo()
{
return false;
}
@Override
protected String getItemName()
{
return "feature";
}
private void updateFeatureSelection()
{
selfUpdate = true;
int index = sorter.convertRowIndexToView(highlighters.indexOf(viewControler.getHighlighter()));
table.setRowSelectionInterval(index, index);
selfUpdate = false;
}
}