blob: 886b11c57f0e8822d872fd9c08626824953107dd [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2004-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25package sun.tools.jconsole.inspector;
26
27import java.util.*;
28import java.awt.event.*;
29import javax.swing.table.*;
30import javax.swing.event.*;
31
32// Imports for picking up mouse events from the JTable.
33
34import java.awt.event.MouseAdapter;
35import java.awt.event.MouseEvent;
36import java.awt.event.InputEvent;
37import javax.swing.JTable;
38import javax.swing.table.JTableHeader;
39import javax.swing.table.TableColumnModel;
40
41@SuppressWarnings("serial")
42public class TableSorter extends DefaultTableModel implements MouseListener {
43 private boolean ascending = true;
44 private TableColumnModel columnModel;
45 private JTable tableView;
46 private Vector<TableModelListener> listenerList;
47 private int sortColumn = 0;
48
49 private int[] invertedIndex;
50
51 public TableSorter() {
52 super();
53 listenerList = new Vector<TableModelListener>();
54 }
55
56 public TableSorter(Object[] columnNames, int numRows) {
57 super(columnNames,numRows);
58 listenerList = new Vector<TableModelListener>();
59 }
60
61 public void newDataAvailable(TableModelEvent e) {
62 super.newDataAvailable(e);
63 invertedIndex = new int[getRowCount()];
64 for (int i=0;i<invertedIndex.length;i++) {
65 invertedIndex[i] = i;
66 }
67 sort(this.sortColumn);
68 }
69
70 public void addTableModelListener(TableModelListener l) {
71 listenerList.add(l);
72 super.addTableModelListener(l);
73 }
74
75 public void removeTableModelListener(TableModelListener l) {
76 listenerList.remove(l);
77 super.removeTableModelListener(l);
78 }
79
80 private void removeListeners() {
81 for(TableModelListener tnl : listenerList)
82 super.removeTableModelListener(tnl);
83 }
84
85 private void restoreListeners() {
86 for(TableModelListener tnl : listenerList)
87 super.addTableModelListener(tnl);
88 }
89
90 @SuppressWarnings("unchecked")
91 public int compare(Object o1, Object o2) {
92 if (o1==null)
93 return 1;
94 if (o2==null)
95 return -1;
96 //two object of the same class and that are comparable
97 else if ((o1.getClass().equals(o2.getClass())) &&
98 (o1 instanceof Comparable)) {
99 return (((Comparable) o1).compareTo(o2));
100 }
101 else {
102 return o1.toString().compareTo(o2.toString());
103 }
104 }
105
106 public void sort(int column) {
107 // remove registered listeners
108 removeListeners();
109 // do the sort
110 //n2sort(column);
111 quickSort(0,getRowCount()-1,column);
112 // restore registered listeners
113 restoreListeners();
114 this.sortColumn = column;
115 // update row heights in XMBeanAttributes (required by expandable cells)
116 if (tableView instanceof XMBeanAttributes) {
117 XMBeanAttributes attrs = (XMBeanAttributes) tableView;
118 for (int i = 0; i < getRowCount(); i++) {
119 Vector data = (Vector) dataVector.elementAt(i);
120 attrs.updateRowHeight(data.elementAt(1), i);
121 }
122 }
123 }
124
125 private synchronized boolean compareS(Object s1, Object s2) {
126 if (ascending)
127 return (compare(s1,s2) > 0);
128 else
129 return (compare(s1,s2) < 0);
130 }
131
132 private synchronized boolean compareG(Object s1, Object s2) {
133 if (ascending)
134 return (compare(s1,s2) < 0);
135 else
136 return (compare(s1,s2) > 0);
137 }
138
139 private synchronized void quickSort(int lo0,int hi0, int key) {
140 int lo = lo0;
141 int hi = hi0;
142 Object mid;
143
144 if ( hi0 > lo0)
145 {
146 mid = getValueAt( ( lo0 + hi0 ) / 2 , key);
147
148 while( lo <= hi )
149 {
150 /* find the first element that is greater than
151 * or equal to the partition element starting
152 * from the left Index.
153 */
154 while( ( lo < hi0 ) &&
155 ( compareS(mid,getValueAt(lo,key)) ))
156 ++lo;
157
158 /* find an element that is smaller than or equal to
159 * the partition element starting from the right Index.
160 */
161 while( ( hi > lo0 ) &&
162 ( compareG(mid,getValueAt(hi,key)) ))
163 --hi;
164
165 // if the indexes have not crossed, swap
166 if( lo <= hi )
167 {
168 swap(lo, hi, key);
169 ++lo;
170 --hi;
171 }
172 }
173
174 /* If the right index has not reached the
175 * left side of array
176 * must now sort the left partition.
177 */
178 if( lo0 < hi )
179 quickSort(lo0, hi , key);
180
181 /* If the left index has not reached the right
182 * side of array
183 * must now sort the right partition.
184 */
185 if( lo <= hi0 )
186 quickSort(lo, hi0 , key);
187 }
188 }
189
190 public void n2sort(int column) {
191 for (int i = 0; i < getRowCount(); i++) {
192 for (int j = i+1; j < getRowCount(); j++) {
193 if (compare(getValueAt(i,column),getValueAt(j,column)) == -1) {
194 swap(i, j, column);
195 }
196 }
197 }
198 }
199
200 private Vector getRow(int row) {
201 return (Vector) dataVector.elementAt(row);
202 }
203
204 @SuppressWarnings("unchecked")
205 private void setRow(Vector data, int row) {
206 dataVector.setElementAt(data,row);
207 }
208
209 public void swap(int i, int j, int column) {
210 Vector data = getRow(i);
211 setRow(getRow(j),i);
212 setRow(data,j);
213
214 int a = invertedIndex[i];
215 invertedIndex[i] = invertedIndex[j];
216 invertedIndex[j] = a;
217 }
218
219 public void sortByColumn(int column) {
220 sortByColumn(column, !ascending);
221 }
222
223 public void sortByColumn(int column, boolean ascending) {
224 this.ascending = ascending;
225 sort(column);
226 }
227
228 public int[] getInvertedIndex() {
229 return invertedIndex;
230 }
231
232 // Add a mouse listener to the Table to trigger a table sort
233 // when a column heading is clicked in the JTable.
234 public void addMouseListenerToHeaderInTable(JTable table) {
235 tableView = table;
236 columnModel = tableView.getColumnModel();
237 JTableHeader th = tableView.getTableHeader();
238 th.addMouseListener(this);
239 }
240
241 public void mouseClicked(MouseEvent e) {
242 int viewColumn = columnModel.getColumnIndexAtX(e.getX());
243 int column = tableView.convertColumnIndexToModel(viewColumn);
244 if (e.getClickCount() == 1 && column != -1) {
245 tableView.invalidate();
246 sortByColumn(column);
247 tableView.validate();
248 tableView.repaint();
249 }
250 }
251
252 public void mousePressed(MouseEvent e) {
253 }
254
255 public void mouseEntered(MouseEvent e) {
256 }
257
258 public void mouseExited(MouseEvent e) {
259 }
260
261 public void mouseReleased(MouseEvent e) {
262 }
263}