1
2 package org.lcsim.plugin.browser.sort;
3
4 import java.awt.Component;
5 import java.awt.Graphics;
6 import java.beans.PropertyChangeEvent;
7 import java.beans.PropertyChangeListener;
8
9 import javax.swing.Icon;
10 import javax.swing.JLabel;
11 import javax.swing.JTable;
12 import javax.swing.table.JTableHeader;
13 import javax.swing.table.TableModel;
14 import org.freehep.swing.table.TableColumnHeaderListener;
15 import org.freehep.swing.table.TableHeaderCellRenderer;
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 public class TableSorter
33 {
34 private static Icon downTriangle = new Triangle(false);
35 private static Icon upTriangle = new Triangle(true);
36
37 private SortableTableModel model;
38 private JTableHeader header;
39
40
41
42
43
44 public TableSorter(JTable table)
45 {
46 table.addPropertyChangeListener("model",new ModelChangeListener());
47 modelChanged(table.getModel());
48 header = table.getTableHeader();
49 header.addMouseListener(new HeaderListener());
50 header.setDefaultRenderer(new HeaderRenderer());
51 }
52
53
54
55
56
57
58 public TableSorter(JTable table, int column)
59 {
60 this(table, column, true);
61 }
62
63
64
65
66
67
68
69 public TableSorter(JTable table, int column, boolean ascending)
70 {
71 this(table);
72 sort(column,ascending);
73 }
74
75
76
77
78
79 public int getSortOnColumn()
80 {
81 return model == null ? SortableTableModel.UNSORTED : model.getSortOnColumn();
82 }
83
84
85
86
87
88 public void setSortOnColumn(int column)
89 {
90 if (model != null) model.sort(column,true);
91 }
92
93
94
95
96
97 public boolean isSortAscending()
98 {
99 return model == null ? true : model.isSortAscending();
100 }
101
102
103
104
105
106 public void setSortAscending(boolean ascending)
107 {
108 if (model != null) model.sort(model.getSortOnColumn(),ascending);
109 }
110
111 private void sort(int sortOnColumn, boolean sortAscending)
112 {
113 if (model != null)
114 {
115 model.sort(sortOnColumn, sortAscending);
116 header.resizeAndRepaint();
117 }
118 }
119 private void modelChanged(TableModel model)
120 {
121 this.model = model instanceof SortableTableModel ? (SortableTableModel) model : null;
122 }
123 private class ModelChangeListener implements PropertyChangeListener
124 {
125 public void propertyChange(PropertyChangeEvent evt)
126 {
127 modelChanged((TableModel) evt.getNewValue());
128 }
129 }
130 private class HeaderListener extends TableColumnHeaderListener
131 {
132
133 public void headerClicked(JTable table, int col)
134 {
135 if (model != null)
136 {
137 if (col != model.getSortOnColumn())
138 {
139 sort(col, true);
140 }
141 else
142 {
143 sort(model.getSortOnColumn(), !model.isSortAscending());
144 }
145 }
146 }
147 }
148
149 private class HeaderRenderer extends TableHeaderCellRenderer
150 {
151
152 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col)
153 {
154 JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
155 if (model != null && table.convertColumnIndexToModel(col) == model.getSortOnColumn())
156 {
157 label.setIcon(model.isSortAscending() ? downTriangle : upTriangle);
158 }
159 else
160 {
161 label.setIcon(null);
162 }
163 return label;
164 }
165 }
166 private static class Triangle implements Icon
167 {
168 private boolean up;
169 private static final int size = 16;
170 private static final int[] xxdown = { 3 , 12, 7 };
171 private static final int[] yydown = { 5 , 5, 10 };
172 private static final int[] xxup = { 2 , 12, 7 };
173 private static final int[] yyup = { 10 , 10, 4 };
174 Triangle(boolean up)
175 {
176 this.up = up;
177 }
178
179 public int getIconHeight()
180 {
181 return size;
182 }
183
184 public int getIconWidth()
185 {
186 return size;
187 }
188
189 public void paintIcon(Component c, Graphics g, int x, int y)
190 {
191 int[] xp = new int[3];
192 int[] yp = new int[3];
193 for (int i=0; i<3; i++)
194 {
195 xp[i] = x + (up ? xxup[i] : xxdown[i]);
196 yp[i] = y + (up ? yyup[i] : yydown[i]);
197 }
198 g.setColor(c.getForeground());
199 g.fillPolygon(xp,yp,3);
200 }
201 }
202 }