1 21 package net.mlw.vlh.swing.support; 22 23 import java.awt.Color ; 24 import java.awt.Component ; 25 import java.awt.Graphics ; 26 import java.awt.event.ActionEvent ; 27 import java.awt.event.ActionListener ; 28 import java.awt.event.MouseAdapter ; 29 import java.awt.event.MouseEvent ; 30 import java.awt.event.MouseListener ; 31 import java.util.ArrayList ; 32 import java.util.List ; 33 34 import javax.swing.Icon ; 35 import javax.swing.JLabel ; 36 import javax.swing.JTable ; 37 import javax.swing.event.TableModelEvent ; 38 import javax.swing.event.TableModelListener ; 39 import javax.swing.table.AbstractTableModel ; 40 import javax.swing.table.JTableHeader ; 41 import javax.swing.table.TableCellRenderer ; 42 import javax.swing.table.TableColumnModel ; 43 import javax.swing.table.TableModel ; 44 45 49 public class DelegateToServiceTableSorter extends AbstractTableModel 50 { 51 protected TableModel tableModel; 52 53 public static final int DESCENDING = -1; 54 55 public static final int NOT_SORTED = 0; 56 57 public static final int ASCENDING = 1; 58 59 private static Directive EMPTY_DIRECTIVE = new Directive(-1, NOT_SORTED); 60 61 private JTableHeader tableHeader; 62 63 private MouseListener mouseListener; 64 65 private TableModelListener tableModelListener; 66 67 private List sortingColumns = new ArrayList (); 68 69 public DelegateToServiceTableSorter() 70 { 71 this.mouseListener = new MouseHandler(); 72 this.tableModelListener = new TableModelHandler(); 73 } 74 75 public DelegateToServiceTableSorter(TableModel tableModel) 76 { 77 this(); 78 setTableModel(tableModel); 79 } 80 81 public DelegateToServiceTableSorter(TableModel tableModel, JTableHeader tableHeader) 82 { 83 this(); 84 setTableHeader(tableHeader); 85 setTableModel(tableModel); 86 } 87 88 private void clearSortingState() 89 { 90 } 91 92 public TableModel getTableModel() 93 { 94 return tableModel; 95 } 96 97 public void setTableModel(TableModel tableModel) 98 { 99 if (this.tableModel != null) 100 { 101 this.tableModel.removeTableModelListener(tableModelListener); 102 } 103 104 this.tableModel = tableModel; 105 if (this.tableModel != null) 106 { 107 this.tableModel.addTableModelListener(tableModelListener); 108 } 109 110 clearSortingState(); 111 fireTableStructureChanged(); 112 } 113 114 public JTableHeader getTableHeader() 115 { 116 return tableHeader; 117 } 118 119 public void setTableHeader(JTableHeader tableHeader) 120 { 121 if (this.tableHeader != null) 122 { 123 this.tableHeader.removeMouseListener(mouseListener); 124 TableCellRenderer defaultRenderer = this.tableHeader.getDefaultRenderer(); 125 if (defaultRenderer instanceof SortableHeaderRenderer) 126 { 127 this.tableHeader.setDefaultRenderer(((SortableHeaderRenderer) defaultRenderer).tableCellRenderer); 128 } 129 } 130 this.tableHeader = tableHeader; 131 if (this.tableHeader != null) 132 { 133 this.tableHeader.addMouseListener(mouseListener); 134 this.tableHeader.setDefaultRenderer(new SortableHeaderRenderer(this.tableHeader.getDefaultRenderer())); 135 } 136 } 137 138 public boolean isSorting() 139 { 140 return sortingColumns.size() != 0; 141 } 142 143 private Directive getDirective(int column) 144 { 145 for (int i = 0; i < sortingColumns.size(); i++) 146 { 147 Directive directive = (Directive) sortingColumns.get(i); 148 if (directive.column == column) 149 { 150 return directive; 151 } 152 } 153 return EMPTY_DIRECTIVE; 154 } 155 156 public int getSortingStatus(int column) 157 { 158 return getDirective(column).direction; 159 } 160 161 private void sortingStatusChanged() 162 { 163 clearSortingState(); 164 fireTableDataChanged(); 165 if (tableHeader != null) 166 { 167 tableHeader.repaint(); 168 } 169 } 170 171 public void setSortingStatus(int column, int status) 172 { 173 Directive directive = getDirective(column); 174 if (directive != EMPTY_DIRECTIVE) 175 { 176 sortingColumns.remove(directive); 177 } 178 if (status != NOT_SORTED) 179 { 180 sortingColumns.add(new Directive(column, status)); 181 } 182 sortingStatusChanged(); 183 } 184 185 protected Icon getHeaderRendererIcon(int column, int size) 186 { 187 Directive directive = getDirective(column); 188 if (directive == EMPTY_DIRECTIVE) 189 { 190 return null; 191 } 192 return new Arrow(directive.direction == DESCENDING, size, sortingColumns.indexOf(directive)); 193 } 194 195 private void cancelSorting() 196 { 197 sortingColumns.clear(); 198 sortingStatusChanged(); 199 } 200 201 203 public int getRowCount() 204 { 205 return (tableModel == null) ? 0 : tableModel.getRowCount(); 206 } 207 208 public int getColumnCount() 209 { 210 return (tableModel == null) ? 0 : tableModel.getColumnCount(); 211 } 212 213 public String getColumnName(int column) 214 { 215 return tableModel.getColumnName(column); 216 } 217 218 public Class getColumnClass(int column) 219 { 220 return tableModel.getColumnClass(column); 221 } 222 223 public boolean isCellEditable(int row, int column) 224 { 225 return tableModel.isCellEditable(row, column); 226 } 227 228 public Object getValueAt(int row, int column) 229 { 230 return tableModel.getValueAt(row, column); 231 } 232 233 public void setValueAt(Object aValue, int row, int column) 234 { 235 tableModel.setValueAt(aValue, row, column); 236 } 237 238 private ActionListener actionListener; 239 240 public void addActionListener(ActionListener actionListener) 241 { 242 this.actionListener = actionListener; 243 } 244 245 248 public List getSortingColumns() 249 { 250 return sortingColumns; 251 } 252 253 255 private class TableModelHandler implements TableModelListener 256 { 257 public void tableChanged(TableModelEvent e) 258 { 259 if (!isSorting()) 261 { 262 clearSortingState(); 263 fireTableChanged(e); 264 return; 265 } 266 267 if (e.getFirstRow() == TableModelEvent.HEADER_ROW) 271 { 272 cancelSorting(); 273 fireTableChanged(e); 274 return; 275 } 276 277 clearSortingState(); 279 fireTableDataChanged(); 280 return; 281 } 282 } 283 284 private class MouseHandler extends MouseAdapter 285 { 286 public void mouseClicked(MouseEvent e) 287 { 288 JTableHeader h = (JTableHeader ) e.getSource(); 289 TableColumnModel columnModel = h.getColumnModel(); 290 int viewColumn = columnModel.getColumnIndexAtX(e.getX()); 291 int column = columnModel.getColumn(viewColumn).getModelIndex(); 292 if (column != -1) 293 { 294 int status = getSortingStatus(column); 295 if (!e.isControlDown()) 296 { 297 cancelSorting(); 298 } 299 status = status + (e.isShiftDown() ? -1 : 1); 302 status = (status + 4) % 3 - 1; setSortingStatus(column, status); 304 if (actionListener != null) 305 { 306 actionListener.actionPerformed(new ActionEvent (e.getSource(), e.getID(), "sort", e.getModifiers())); 307 } 308 } 309 } 310 } 311 312 private static class Arrow implements Icon 313 { 314 private boolean descending; 315 316 private int size; 317 318 private int priority; 319 320 public Arrow(boolean descending, int size, int priority) 321 { 322 this.descending = descending; 323 this.size = size; 324 this.priority = priority; 325 } 326 327 public void paintIcon(Component c, Graphics g, int x, int y) 328 { 329 Color color = c == null ? Color.GRAY : c.getBackground(); 330 int dx = (int) (size / 2 * Math.pow(0.8, priority)); 333 int dy = descending ? dx : -dx; 334 y = y + 5 * size / 6 + (descending ? -dy : 0); 336 int shift = descending ? 1 : -1; 337 g.translate(x, y); 338 339 g.setColor(color.darker()); 341 g.drawLine(dx / 2, dy, 0, 0); 342 g.drawLine(dx / 2, dy + shift, 0, shift); 343 344 g.setColor(color.brighter()); 346 g.drawLine(dx / 2, dy, dx, 0); 347 g.drawLine(dx / 2, dy + shift, dx, shift); 348 349 if (descending) 351 { 352 g.setColor(color.darker().darker()); 353 } 354 else 355 { 356 g.setColor(color.brighter().brighter()); 357 } 358 g.drawLine(dx, 0, 0, 0); 359 360 g.setColor(color); 361 g.translate(-x, -y); 362 } 363 364 public int getIconWidth() 365 { 366 return size; 367 } 368 369 public int getIconHeight() 370 { 371 return size; 372 } 373 } 374 375 private class SortableHeaderRenderer implements TableCellRenderer 376 { 377 private TableCellRenderer tableCellRenderer; 378 379 public SortableHeaderRenderer(TableCellRenderer tableCellRenderer) 380 { 381 this.tableCellRenderer = tableCellRenderer; 382 } 383 384 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, 385 int row, int column) 386 { 387 Component c = tableCellRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); 388 if (c instanceof JLabel ) 389 { 390 JLabel l = (JLabel ) c; 391 l.setHorizontalTextPosition(JLabel.LEFT); 392 int modelColumn = table.convertColumnIndexToModel(column); 393 l.setIcon(getHeaderRendererIcon(modelColumn, l.getFont().getSize())); 394 } 395 return c; 396 } 397 } 398 399 public static class Directive 400 { 401 private int column; 402 403 private int direction; 404 405 public Directive(int column, int direction) 406 { 407 this.column = column; 408 this.direction = direction; 409 } 410 411 414 public int getColumn() 415 { 416 return column; 417 } 418 419 422 public int getDirection() 423 { 424 return direction; 425 } 426 } 427 } | Popular Tags |