1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.xnap.gui.table;
21
22 import java.awt.event.InputEvent;
23 import java.awt.event.MouseAdapter;
24 import java.awt.event.MouseEvent;
25 import java.awt.event.MouseMotionListener;
26 import java.util.Enumeration;
27
28 import javax.swing.JPopupMenu;
29 import javax.swing.JTable;
30 import javax.swing.JTree;
31 import javax.swing.table.JTableHeader;
32 import javax.swing.tree.TreePath;
33
34 import org.xnap.gui.util.GUIHelper;
35
36 /***
37 * TableHeaderHandler class handles the mouse events invoked by clicking
38 * on the header portion of the JTable.
39 */
40 public class TableHeaderHandler extends MouseAdapter
41 implements MouseMotionListener {
42
43
44
45 private JTable jta;
46 private JTableHeader header;
47 private JTree jt;
48 private JPopupMenu jpm;
49 private SortButtonRenderer renderer;
50 private SortableModel stm;
51 private TableHeaderListener thl;
52
53 private TreePath[] selectedPaths;
54 private Enumeration expandedLeafs;
55
56 /***
57 * Set to true, when the user has pressed a button but not yet
58 * dragged it.
59 */
60 private boolean sorting = false;
61
62
63
64 /***
65 *
66 */
67 public TableHeaderHandler(JTable jta, SortableModel stm, JPopupMenu jpm)
68 {
69 this.jta = jta;
70 this.header = jta.getTableHeader();
71 this.stm = stm;
72 this.jpm = jpm;
73
74 renderer = new SortButtonRenderer(header.getDefaultRenderer());
75 header.setDefaultRenderer(renderer);
76
77 header.setReorderingAllowed(true);
78 header.setResizingAllowed(true);
79 }
80
81
82
83 /***
84 * Installs a TableHeaderHandler to <code>jta</code>. The handler
85 * takes care of sorting and resizing.
86 *
87 * <p>The SortableTableModel parameter is needed for the JTreeTable,
88 * because it uses a TreeTableModelAdapter that wraps around
89 * the real TableModel.
90 */
91 public static TableHeaderHandler install(JTable jta, JPopupMenu jpm,
92 SortableModel stm)
93 {
94 JTableHeader jth = jta.getTableHeader();
95 TableHeaderHandler l = new TableHeaderHandler(jta, stm, jpm);
96 jth.addMouseListener(l);
97 jth.addMouseMotionListener(l);
98
99 return l;
100 }
101
102 public static TableHeaderHandler install(JTable jta, JPopupMenu jpm)
103 {
104 return install(jta, jpm, (SortableModel)jta.getModel());
105 }
106
107 /***
108 * Installs listener.
109 */
110 public static TableHeaderHandler install(JTable jta)
111 {
112 return install(jta, null);
113 }
114
115 public void mousePressed(MouseEvent e)
116 {
117 if (e.isPopupTrigger()) {
118 showPopupMenu(e);
119 }
120 else {
121 int col = header.columnAtPoint(e.getPoint());
122 renderer.selectColumn(col);
123 header.repaint();
124
125 sorting = true;
126 }
127
128 setAutoResizeMode(e);
129 }
130
131 public void mouseReleased(MouseEvent e)
132 {
133 if (e.isPopupTrigger()) {
134 showPopupMenu(e);
135 }
136 else if (sorting) {
137 int col = header.columnAtPoint(e.getPoint());
138 if (jta.isEditing()) {
139 jta.getCellEditor().stopCellEditing();
140 }
141 sortByColumn(col);
142
143 if (thl != null) {
144 thl.sortedColumnChanged();
145 }
146 sorting = false;
147 renderer.selectColumn(-1);
148 header.repaint();
149 }
150 else {
151 if (thl != null) {
152 thl.columnWidthChanged();
153 }
154 }
155 }
156
157 public void mouseDragged(MouseEvent e)
158 {
159 if (sorting) {
160
161 sorting = false;
162
163 renderer.selectColumn(-1);
164 header.repaint();
165 }
166
167 setAutoResizeMode(e);
168 }
169
170 public void mouseMoved(MouseEvent e)
171 {
172 }
173
174 /***
175 * Sets the auto resize mode of the table depending on a modifier key.
176 */
177 private void setAutoResizeMode(MouseEvent e)
178 {
179 if ((e.getModifiers() & InputEvent.SHIFT_MASK) != 0) {
180 jta.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
181 }
182 else if ((e.getModifiers() & InputEvent.CTRL_MASK) != 0) {
183 jta.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
184 }
185 else {
186 jta.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
187 }
188 }
189
190 public void setListener(TableHeaderListener thl)
191 {
192 this.thl = thl;
193 }
194
195 public void setTree(JTree jt)
196 {
197 this.jt = jt;
198 }
199
200 /***
201 * Displays the popup menu.
202 */
203 public void showPopupMenu(MouseEvent e)
204 {
205 if (jpm != null) {
206 header.setDraggedColumn(null);
207 header.setResizingColumn(null);
208 GUIHelper.showPopupMenu(jpm, e.getComponent(), e.getX(), e.getY());
209 }
210 }
211
212 /***
213 *
214 */
215 public void sortByColumn(int column)
216 {
217 int modelIndex = jta.convertColumnIndexToModel(column);
218
219 boolean ascending;
220 if (stm.getSortedColumn() == modelIndex) {
221
222 ascending = stm.isSortedAscending();
223 }
224 else if (stm.getColumnClass(modelIndex) == String.class) {
225
226 ascending = true;
227 }
228 else {
229
230 ascending = false;
231 }
232
233
234 boolean revert = (stm.getSortedColumn() == modelIndex);
235
236 storeSelections();
237
238 ascending = stm.sortByColumn(modelIndex, ascending, revert);
239 renderer.setSortedColumn(column, ascending);
240
241 restoreSelections();
242 }
243
244 public void storeSelections()
245 {
246 if (jt != null) {
247 selectedPaths = jt.getSelectionPaths();
248 expandedLeafs = jt.getExpandedDescendants
249 (new TreePath(jt.getModel().getRoot()));
250 }
251 }
252
253 public void restoreSelections() {
254 if (jt != null) {
255 if (expandedLeafs != null) {
256 while (expandedLeafs.hasMoreElements()) {
257 TreePath path = (TreePath)expandedLeafs.nextElement();
258 jt.expandPath(path);
259 }
260 }
261 if (selectedPaths != null) {
262 jt.addSelectionPaths(selectedPaths);
263 }
264 }
265 }
266
267 }