/* * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.tools.jconsole.inspector; import java.util.*; import java.awt.event.*; import javax.swing.table.*; import javax.swing.event.*; // Imports for picking up mouse events from the JTable. import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.InputEvent; import javax.swing.JTable; import javax.swing.table.JTableHeader; import javax.swing.table.TableColumnModel; @SuppressWarnings("serial") public class TableSorter extends DefaultTableModel implements MouseListener { private boolean ascending = true; private TableColumnModel columnModel; private JTable tableView; private Vector<TableModelListener> listenerList; private int sortColumn = 0; private int[] invertedIndex; public TableSorter() { super(); listenerList = new Vector<TableModelListener>(); } public TableSorter(Object[] columnNames, int numRows) { super(columnNames,numRows); listenerList = new Vector<TableModelListener>(); } public void newDataAvailable(TableModelEvent e) { super.newDataAvailable(e); invertedIndex = new int[getRowCount()]; for (int i=0;i<invertedIndex.length;i++) { invertedIndex[i] = i; } sort(this.sortColumn); } public void addTableModelListener(TableModelListener l) { listenerList.add(l); super.addTableModelListener(l); } public void removeTableModelListener(TableModelListener l) { listenerList.remove(l); super.removeTableModelListener(l); } private void removeListeners() { for(TableModelListener tnl : listenerList) super.removeTableModelListener(tnl); } private void restoreListeners() { for(TableModelListener tnl : listenerList) super.addTableModelListener(tnl); } @SuppressWarnings("unchecked") public int compare(Object o1, Object o2) { if (o1==null) return 1; if (o2==null) return -1; //two object of the same class and that are comparable else if ((o1.getClass().equals(o2.getClass())) && (o1 instanceof Comparable)) { return (((Comparable) o1).compareTo(o2)); } else { return o1.toString().compareTo(o2.toString()); } } public void sort(int column) { // remove registered listeners removeListeners(); // do the sort //n2sort(column); quickSort(0,getRowCount()-1,column); // restore registered listeners restoreListeners(); this.sortColumn = column; // update row heights in XMBeanAttributes (required by expandable cells) if (tableView instanceof XMBeanAttributes) { XMBeanAttributes attrs = (XMBeanAttributes) tableView; for (int i = 0; i < getRowCount(); i++) { Vector data = (Vector) dataVector.elementAt(i); attrs.updateRowHeight(data.elementAt(1), i); } } } private synchronized boolean compareS(Object s1, Object s2) { if (ascending) return (compare(s1,s2) > 0); else return (compare(s1,s2) < 0); } private synchronized boolean compareG(Object s1, Object s2) { if (ascending) return (compare(s1,s2) < 0); else return (compare(s1,s2) > 0); } private synchronized void quickSort(int lo0,int hi0, int key) { int lo = lo0; int hi = hi0; Object mid; if ( hi0 > lo0) { mid = getValueAt( ( lo0 + hi0 ) / 2 , key); while( lo <= hi ) { /* find the first element that is greater than * or equal to the partition element starting * from the left Index. */ while( ( lo < hi0 ) && ( compareS(mid,getValueAt(lo,key)) )) ++lo; /* find an element that is smaller than or equal to * the partition element starting from the right Index. */ while( ( hi > lo0 ) && ( compareG(mid,getValueAt(hi,key)) )) --hi; // if the indexes have not crossed, swap if( lo <= hi ) { swap(lo, hi, key); ++lo; --hi; } } /* If the right index has not reached the * left side of array * must now sort the left partition. */ if( lo0 < hi ) quickSort(lo0, hi , key); /* If the left index has not reached the right * side of array * must now sort the right partition. */ if( lo <= hi0 ) quickSort(lo, hi0 , key); } } public void n2sort(int column) { for (int i = 0; i < getRowCount(); i++) { for (int j = i+1; j < getRowCount(); j++) { if (compare(getValueAt(i,column),getValueAt(j,column)) == -1) { swap(i, j, column); } } } } private Vector getRow(int row) { return (Vector) dataVector.elementAt(row); } @SuppressWarnings("unchecked") private void setRow(Vector data, int row) { dataVector.setElementAt(data,row); } public void swap(int i, int j, int column) { Vector data = getRow(i); setRow(getRow(j),i); setRow(data,j); int a = invertedIndex[i]; invertedIndex[i] = invertedIndex[j]; invertedIndex[j] = a; } public void sortByColumn(int column) { sortByColumn(column, !ascending); } public void sortByColumn(int column, boolean ascending) { this.ascending = ascending; sort(column); } public int[] getInvertedIndex() { return invertedIndex; } // Add a mouse listener to the Table to trigger a table sort // when a column heading is clicked in the JTable. public void addMouseListenerToHeaderInTable(JTable table) { tableView = table; columnModel = tableView.getColumnModel(); JTableHeader th = tableView.getTableHeader(); th.addMouseListener(this); } public void mouseClicked(MouseEvent e) { int viewColumn = columnModel.getColumnIndexAtX(e.getX()); int column = tableView.convertColumnIndexToModel(viewColumn); if (e.getClickCount() == 1 && column != -1) { tableView.invalidate(); sortByColumn(column); tableView.validate(); tableView.repaint(); } } public void mousePressed(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } }