package com.classwizard.cw;
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import org.jdesktop.swingx.JXTreeTable;
import org.jdesktop.swingx.treetable.DefaultTreeTableModel;
import org.jdesktop.swingx.treetable.MutableTreeTableNode;
/**
* @author SindyLee2 02.09.2011
*
*/
public class TreeTableSorter extends DynamicTreeTableModel implements TreeModelListener{
CustomerTreeTableNode indexes[];
Vector sortingColumns = new Vector();
boolean ascending = true;
int _column_sorted = -1;
int compares;
CustomerTreeTableNode _root = null;
CustomerTreeTableNode oldnodes[];
public TreeTableSorter(CustomerTreeTableNode root,Vector cols)
{
super(root,cols);
_root = root;
indexes = new CustomerTreeTableNode[0]; // For consistency.
oldnodes = new CustomerTreeTableNode[0]; // For consistency.
sortingColumns = cols;
}
public int getSortedColumn()
{
return(_column_sorted);
}
public boolean getAscending()
{
return(ascending);
}
public int compareRowsByColumn(CustomerTreeTableNode row1, CustomerTreeTableNode row2, int column)
{
Vector rowData1 = row1.getRowData();
Vector rowData2 = row2.getRowData();
Class type = super.getColumnClass(column);
Object o1 = rowData1.get(column);
Object o2 = rowData2.get(column);
// If both values are null return 0
if (o1 == null && o2 == null)
{
return 0;
}
else if (o1 == null) // Define null less than everything.
{
return -1;
}
else if (o2 == null)
{
return 1;
}
if (type.getSuperclass() == java.lang.Number.class)
{
Number n1 = (Number)rowData1.get(column);
double d1 = n1.doubleValue();
Number n2 = (Number)rowData2.get(column);
double d2 = n2.doubleValue();
if (d1 < d2)
return -1;
else if (d1 > d2)
return 1;
else
return 0;
}
else if (type == java.util.Date.class)
{
Date d1 = (Date)rowData1.get(column);
long n1 = d1.getTime();
Date d2 = (Date)rowData2.get(column);
long n2 = d2.getTime();
if (n1 < n2)
return -1;
else if (n1 > n2)
return 1;
else return 0;
}
else if (type == String.class)
{
String s1 = (String)rowData1.get(column);
String s2 = (String)rowData2.get(column);
int result = s1.compareTo(s2);
if (result < 0)
return -1;
else if (result > 0)
return 1;
else return 0;
}
else if (type == Boolean.class)
{
Boolean bool1 = (Boolean)rowData1.get(column);
boolean b1 = bool1.booleanValue();
Boolean bool2 = (Boolean)rowData2.get(column);
boolean b2 = bool2.booleanValue();
if (b1 == b2)
return 0;
else if (b1) // Define false < true
return 1;
else
return -1;
}
else
{
Object v1 = rowData1.get(column);
String s1 = v1.toString();
Object v2 = rowData2.get(column);
String s2 = v2.toString();
int result = s1.compareTo(s2);
if (result < 0)
return -1;
else if (result > 0)
return 1;
else return 0;
}
}
public int compare(CustomerTreeTableNode row1, CustomerTreeTableNode row2)
{
compares++;
for(int level = 0; level < sortingColumns.size(); level++)
{
Integer column = (Integer)sortingColumns.elementAt(level);
int result = compareRowsByColumn(row1, row2, column.intValue());
if (result != 0)
return ascending ? result : -result;
}
return 0;
}
public void reallocateIndexes()
{
int rowCount = super.getChildCount(_root);
indexes = new CustomerTreeTableNode[rowCount];
for(int row = 0; row < rowCount; row++)
indexes[row] = (CustomerTreeTableNode) _root.getChildAt(row);
}
public void checkModel()
{
if (indexes.length != super.getChildCount(_root))
{
reallocateIndexes();
}
}
public void sort(Object sender)
{
checkModel();
compares = 0;
// n2sort();
// qsort(0, indexes.length-1);
oldnodes = (CustomerTreeTableNode[])indexes.clone();
shuttlesort((CustomerTreeTableNode[])indexes.clone(), indexes, 0, indexes.length);
}
public void n2sort()
{
for(int i = 0; i < super.getChildCount(_root); i++)
{
for(int j = i+1; j < super.getChildCount(_root); j++)
{
if (compare(indexes[i], indexes[j]) == -1)
{
swap(i, j);
}
}
}
}
public void shuttlesort(CustomerTreeTableNode from[], CustomerTreeTableNode to[], int low, int high)
{
if (high - low < 2)
{
return;
}
int middle = (low + high)/2;
shuttlesort(to, from, low, middle);
shuttlesort(to, from, middle, high);
int p = low;
int q = middle;
if (high - low >= 4 && compare(from[middle-1], from[middle]) <= 0)
{
for (int i = low; i < high; i++)
{
to[i] = from[i];
}
return;
}
// A normal merge.
for(int i = low; i < high; i++)
{
if (q >= high || (p < middle && compare(from[p], from[q]) <= 0))
{
to[i] = from[p++];
}
else
{
to[i] = from[q++];
}
}
}
public void swap(int i, int j)
{
CustomerTreeTableNode tmp = indexes[i];
indexes[i] = indexes[j];
indexes[j] = tmp;
}
public void sortByColumn(int column, boolean ascending)
{
this.ascending = ascending;
sortingColumns.removeAllElements();
sortingColumns.addElement(new Integer(column));
sort(this);
// nodes must be new arranged to update the tree
DefaultTreeTableModel oldmodel = new DefaultTreeTableModel(_root);
for(int k=0; k<oldnodes.length;k++){
CustomerTreeTableNode oldn = oldnodes[k];
oldmodel.removeNodeFromParent(oldn);
}
DefaultTreeTableModel newmodel = new DefaultTreeTableModel(_root);
for(int i = 0; i<indexes.length;i++){
CustomerTreeTableNode sr = indexes[i];
// Vector srRowData = sr.getRowData();
// System.out.println("sorted result node: " + srRowData);
newmodel.insertNodeInto(sr, _root, i);
}
// System.out.println(_root.getChildCount());
for(int j = 0; j<indexes.length;j++){
// System.out.println(((CustomerTreeTableNode) _root.getChildAt(j)).getRowData()); //The Order is here already correct!
fireTreeStructureChanged(this, getPathToRoot((CustomerTreeTableNode) _root.getChildAt(j)), null, null); //??????? but here is lost again.....
//Die schon richtig sortierte Spalteninhalte sind wieder ducheinander!?
}
}
public void treeNodesChanged(TreeModelEvent e) {
int[] indices = e.getChildIndices();
TreePath path = e.getTreePath();
sort(e.getTreePath());
fireTreeNodesChanged(this, path.getPath(),indices,e.getChildren());
}
public void treeNodesInserted(TreeModelEvent e) {
int[] indices = e.getChildIndices();
TreePath path = e.getTreePath();
sort(e.getTreePath());
fireTreeNodesInserted(this, path.getPath(),indices,e.getChildren());
}
public void treeNodesRemoved(TreeModelEvent e) {
int[] indices = e.getChildIndices();
TreePath path = e.getTreePath();
sort(e.getTreePath());
fireTreeNodesRemoved(this, path.getPath(),indices,e.getChildren());
}
public void treeStructureChanged(TreeModelEvent e) {
reallocateIndexes();
fireTreeStructureChanged(e.getTreePath(), null, null, null);
}
public void addMouseListenerToHeaderInTable(JXTreeTable table)
{
final TreeTableSorter sorter = this;
final JTable tableView = table;
tableView.setColumnSelectionAllowed(false);
MouseAdapter listMouseListener = new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
TableColumnModel columnModel = tableView.getColumnModel();
int viewColumn = columnModel.getColumnIndexAtX(e.getX());
int column = tableView.convertColumnIndexToModel(viewColumn);
if(e.getClickCount() == 1 && column != -1)
{
// System.out.println("Sorting ..." + tableView.getValueAt(1, column));
int shiftPressed = e.getModifiers()&InputEvent.SHIFT_MASK;
boolean ascending = (shiftPressed == 0);
sorter.sortByColumn(column, ascending);
}
}
};
JTableHeader th = tableView.getTableHeader();
th.addMouseListener(listMouseListener);
}
}