| 1 7 8 package javax.swing.plaf.basic; 9 10 import java.awt.*; 11 import java.awt.datatransfer.*; 12 import java.awt.dnd.*; 13 import java.awt.event.*; 14 import java.util.Enumeration ; 15 import java.util.EventObject ; 16 import java.util.Hashtable ; 17 import java.util.TooManyListenersException ; 18 import javax.swing.*; 19 import javax.swing.event.*; 20 import javax.swing.plaf.*; 21 import javax.swing.text.*; 22 import javax.swing.table.*; 23 import javax.swing.plaf.basic.DragRecognitionSupport.BeforeDrag ; 24 import com.sun.java.swing.SwingUtilities2; 25 import static com.sun.java.swing.SwingUtilities2.DRAG_FIX; 26 27 28 import java.beans.PropertyChangeEvent ; 29 import java.beans.PropertyChangeListener ; 30 31 import sun.swing.DefaultLookup; 32 import sun.swing.UIAction; 33 34 41 public class BasicTableUI extends TableUI 42 { 43 44 48 protected JTable table; 50 protected CellRendererPane rendererPane; 51 52 protected KeyListener keyListener; 54 protected FocusListener focusListener; 55 protected MouseInputListener mouseInputListener; 56 57 private Handler handler; 58 59 62 private boolean isFileList = false; 63 64 68 private static class Actions extends UIAction { 69 private static final String CANCEL_EDITING = "cancel"; 70 private static final String SELECT_ALL = "selectAll"; 71 private static final String CLEAR_SELECTION = "clearSelection"; 72 private static final String START_EDITING = "startEditing"; 73 74 private static final String NEXT_ROW = "selectNextRow"; 75 private static final String NEXT_ROW_CELL = "selectNextRowCell"; 76 private static final String NEXT_ROW_EXTEND_SELECTION = 77 "selectNextRowExtendSelection"; 78 private static final String NEXT_ROW_CHANGE_LEAD = 79 "selectNextRowChangeLead"; 80 private static final String PREVIOUS_ROW = "selectPreviousRow"; 81 private static final String PREVIOUS_ROW_CELL = "selectPreviousRowCell"; 82 private static final String PREVIOUS_ROW_EXTEND_SELECTION = 83 "selectPreviousRowExtendSelection"; 84 private static final String PREVIOUS_ROW_CHANGE_LEAD = 85 "selectPreviousRowChangeLead"; 86 87 private static final String NEXT_COLUMN = "selectNextColumn"; 88 private static final String NEXT_COLUMN_CELL = "selectNextColumnCell"; 89 private static final String NEXT_COLUMN_EXTEND_SELECTION = 90 "selectNextColumnExtendSelection"; 91 private static final String NEXT_COLUMN_CHANGE_LEAD = 92 "selectNextColumnChangeLead"; 93 private static final String PREVIOUS_COLUMN = "selectPreviousColumn"; 94 private static final String PREVIOUS_COLUMN_CELL = 95 "selectPreviousColumnCell"; 96 private static final String PREVIOUS_COLUMN_EXTEND_SELECTION = 97 "selectPreviousColumnExtendSelection"; 98 private static final String PREVIOUS_COLUMN_CHANGE_LEAD = 99 "selectPreviousColumnChangeLead"; 100 101 private static final String SCROLL_LEFT_CHANGE_SELECTION = 102 "scrollLeftChangeSelection"; 103 private static final String SCROLL_LEFT_EXTEND_SELECTION = 104 "scrollLeftExtendSelection"; 105 private static final String SCROLL_RIGHT_CHANGE_SELECTION = 106 "scrollRightChangeSelection"; 107 private static final String SCROLL_RIGHT_EXTEND_SELECTION = 108 "scrollRightExtendSelection"; 109 110 private static final String SCROLL_UP_CHANGE_SELECTION = 111 "scrollUpChangeSelection"; 112 private static final String SCROLL_UP_EXTEND_SELECTION = 113 "scrollUpExtendSelection"; 114 private static final String SCROLL_DOWN_CHANGE_SELECTION = 115 "scrollDownChangeSelection"; 116 private static final String SCROLL_DOWN_EXTEND_SELECTION = 117 "scrollDownExtendSelection"; 118 119 private static final String FIRST_COLUMN = 120 "selectFirstColumn"; 121 private static final String FIRST_COLUMN_EXTEND_SELECTION = 122 "selectFirstColumnExtendSelection"; 123 private static final String LAST_COLUMN = 124 "selectLastColumn"; 125 private static final String LAST_COLUMN_EXTEND_SELECTION = 126 "selectLastColumnExtendSelection"; 127 128 private static final String FIRST_ROW = 129 "selectFirstRow"; 130 private static final String FIRST_ROW_EXTEND_SELECTION = 131 "selectFirstRowExtendSelection"; 132 private static final String LAST_ROW = 133 "selectLastRow"; 134 private static final String LAST_ROW_EXTEND_SELECTION = 135 "selectLastRowExtendSelection"; 136 137 private static final String ADD_TO_SELECTION = "addToSelection"; 139 140 private static final String TOGGLE_AND_ANCHOR = "toggleAndAnchor"; 142 143 private static final String EXTEND_TO = "extendTo"; 145 146 private static final String MOVE_SELECTION_TO = "moveSelectionTo"; 148 149 protected int dx; 150 protected int dy; 151 protected boolean extend; 152 protected boolean inSelection; 153 protected boolean forwards; 154 protected boolean vertically; 155 protected boolean toLimit; 156 157 protected int leadRow; 158 protected int leadColumn; 159 160 Actions(String name) { 161 super(name); 162 } 163 164 Actions(String name, int dx, int dy, boolean extend, 165 boolean inSelection) { 166 super(name); 167 168 if (inSelection) { 175 this.inSelection = true; 176 177 dx = sign(dx); 179 dy = sign(dy); 180 181 assert (dx == 0 || dy == 0) && !(dx == 0 && dy == 0); 183 } 184 185 this.dx = dx; 186 this.dy = dy; 187 this.extend = extend; 188 } 189 190 Actions(String name, boolean extend, boolean forwards, 191 boolean vertically, boolean toLimit) { 192 this(name, 0, 0, extend, false); 193 this.forwards = forwards; 194 this.vertically = vertically; 195 this.toLimit = toLimit; 196 } 197 198 private static int clipToRange(int i, int a, int b) { 199 return Math.min(Math.max(i, a), b-1); 200 } 201 202 private void moveWithinTableRange(JTable table, int dx, int dy) { 203 leadRow = clipToRange(leadRow+dy, 0, table.getRowCount()); 204 leadColumn = clipToRange(leadColumn+dx, 0, table.getColumnCount()); 205 } 206 207 private static int sign(int num) { 208 return (num < 0) ? -1 : ((num == 0) ? 0 : 1); 209 } 210 211 223 private boolean moveWithinSelectedRange(JTable table, int dx, int dy, 224 ListSelectionModel rsm, ListSelectionModel csm) { 225 226 229 int totalCount; 232 int minX, maxX, minY, maxY; 233 234 boolean rs = table.getRowSelectionAllowed(); 235 boolean cs = table.getColumnSelectionAllowed(); 236 237 if (rs && cs) { 239 totalCount = table.getSelectedRowCount() * table.getSelectedColumnCount(); 240 minX = csm.getMinSelectionIndex(); 241 maxX = csm.getMaxSelectionIndex(); 242 minY = rsm.getMinSelectionIndex(); 243 maxY = rsm.getMaxSelectionIndex(); 244 } else if (rs) { 246 totalCount = table.getSelectedRowCount(); 247 minX = 0; 248 maxX = table.getColumnCount() - 1; 249 minY = rsm.getMinSelectionIndex(); 250 maxY = rsm.getMaxSelectionIndex(); 251 } else if (cs) { 253 totalCount = table.getSelectedColumnCount(); 254 minX = csm.getMinSelectionIndex(); 255 maxX = csm.getMaxSelectionIndex(); 256 minY = 0; 257 maxY = table.getRowCount() - 1; 258 } else { 260 totalCount = 0; 261 minX = maxX = minY = maxY = 0; 265 } 266 267 boolean stayInSelection; 271 272 if (totalCount == 0 || 274 (totalCount == 1 && table.isCellSelected(leadRow, leadColumn))) { 276 277 stayInSelection = false; 278 279 maxX = table.getColumnCount() - 1; 280 maxY = table.getRowCount() - 1; 281 282 minX = Math.min(0, maxX); 284 minY = Math.min(0, maxY); 285 } else { 286 stayInSelection = true; 287 } 288 289 if (dy == 1 && leadColumn == -1) { 292 leadColumn = minX; 293 leadRow = -1; 294 } else if (dx == 1 && leadRow == -1) { 295 leadRow = minY; 296 leadColumn = -1; 297 } else if (dy == -1 && leadColumn == -1) { 298 leadColumn = maxX; 299 leadRow = maxY + 1; 300 } else if (dx == -1 && leadRow == -1) { 301 leadRow = maxY; 302 leadColumn = maxX + 1; 303 } 304 305 leadRow = Math.min(Math.max(leadRow, minY - 1), maxY + 1); 309 leadColumn = Math.min(Math.max(leadColumn, minX - 1), maxX + 1); 310 311 do { 313 calcNextPos(dx, minX, maxX, dy, minY, maxY); 314 } while (stayInSelection && !table.isCellSelected(leadRow, leadColumn)); 315 316 return stayInSelection; 317 } 318 319 323 private void calcNextPos(int dx, int minX, int maxX, 324 int dy, int minY, int maxY) { 325 326 if (dx != 0) { 327 leadColumn += dx; 328 if (leadColumn > maxX) { 329 leadColumn = minX; 330 leadRow++; 331 if (leadRow > maxY) { 332 leadRow = minY; 333 } 334 } else if (leadColumn < minX) { 335 leadColumn = maxX; 336 leadRow--; 337 if (leadRow < minY) { 338 leadRow = maxY; 339 } 340 } 341 } else { 342 leadRow += dy; 343 if (leadRow > maxY) { 344 leadRow = minY; 345 leadColumn++; 346 if (leadColumn > maxX) { 347 leadColumn = minX; 348 } 349 } else if (leadRow < minY) { 350 leadRow = maxY; 351 leadColumn--; 352 if (leadColumn < minX) { 353 leadColumn = maxX; 354 } 355 } 356 } 357 } 358 359 public void actionPerformed(ActionEvent e) { 360 String key = getName(); 361 JTable table = (JTable)e.getSource(); 362 363 ListSelectionModel rsm = table.getSelectionModel(); 364 leadRow = getAdjustedLead(table, true, rsm); 365 366 ListSelectionModel csm = table.getColumnModel().getSelectionModel(); 367 leadColumn = getAdjustedLead(table, false, csm); 368 369 if (!table.getComponentOrientation().isLeftToRight()) { 370 if (key == SCROLL_LEFT_CHANGE_SELECTION || 371 key == SCROLL_LEFT_EXTEND_SELECTION) { 372 forwards = true; 373 } else if (key == SCROLL_RIGHT_CHANGE_SELECTION || 374 key == SCROLL_RIGHT_EXTEND_SELECTION) { 375 forwards = false; 376 } 377 } 378 379 if (key == SCROLL_LEFT_CHANGE_SELECTION || key == SCROLL_LEFT_EXTEND_SELECTION || 381 key == SCROLL_RIGHT_CHANGE_SELECTION || 382 key == SCROLL_RIGHT_EXTEND_SELECTION || 383 key == SCROLL_UP_CHANGE_SELECTION || 384 key == SCROLL_UP_EXTEND_SELECTION || 385 key == SCROLL_DOWN_CHANGE_SELECTION || 386 key == SCROLL_DOWN_EXTEND_SELECTION || 387 key == FIRST_COLUMN || 388 key == FIRST_COLUMN_EXTEND_SELECTION || 389 key == FIRST_ROW || 390 key == FIRST_ROW_EXTEND_SELECTION || 391 key == LAST_COLUMN || 392 key == LAST_COLUMN_EXTEND_SELECTION || 393 key == LAST_ROW || 394 key == LAST_ROW_EXTEND_SELECTION) { 395 if (toLimit) { 396 if (vertically) { 397 int rowCount = table.getRowCount(); 398 this.dx = 0; 399 this.dy = forwards ? rowCount : -rowCount; 400 } 401 else { 402 int colCount = table.getColumnCount(); 403 this.dx = forwards ? colCount : -colCount; 404 this.dy = 0; 405 } 406 } 407 else { 408 if (!(table.getParent().getParent() instanceof 409 JScrollPane)) { 410 return; 411 } 412 413 Dimension delta = table.getParent().getSize(); 414 415 if (vertically) { 416 Rectangle r = table.getCellRect(leadRow, 0, true); 417 r.y += forwards ? delta.height : -delta.height; 418 this.dx = 0; 419 int newRow = table.rowAtPoint(r.getLocation()); 420 if (newRow == -1 && forwards) { 421 newRow = table.getRowCount(); 422 } 423 this.dy = newRow - leadRow; 424 } 425 else { 426 Rectangle r = table.getCellRect(0, leadColumn, true); 427 r.x += forwards ? delta.width : -delta.width; 428 int newColumn = table.columnAtPoint(r.getLocation()); 429 if (newColumn == -1 && forwards) { 430 newColumn = table.getColumnCount(); 431 } 432 this.dx = newColumn - leadColumn; 433 this.dy = 0; 434 } 435 } 436 } 437 if (key == NEXT_ROW || key == NEXT_ROW_CELL || 439 key == NEXT_ROW_EXTEND_SELECTION || 440 key == NEXT_ROW_CHANGE_LEAD || 441 key == NEXT_COLUMN || 442 key == NEXT_COLUMN_CELL || 443 key == NEXT_COLUMN_EXTEND_SELECTION || 444 key == NEXT_COLUMN_CHANGE_LEAD || 445 key == PREVIOUS_ROW || 446 key == PREVIOUS_ROW_CELL || 447 key == PREVIOUS_ROW_EXTEND_SELECTION || 448 key == PREVIOUS_ROW_CHANGE_LEAD || 449 key == PREVIOUS_COLUMN || 450 key == PREVIOUS_COLUMN_CELL || 451 key == PREVIOUS_COLUMN_EXTEND_SELECTION || 452 key == PREVIOUS_COLUMN_CHANGE_LEAD || 453 key == SCROLL_LEFT_CHANGE_SELECTION || 455 key == SCROLL_LEFT_EXTEND_SELECTION || 456 key == SCROLL_RIGHT_CHANGE_SELECTION || 457 key == SCROLL_RIGHT_EXTEND_SELECTION || 458 key == SCROLL_UP_CHANGE_SELECTION || 459 key == SCROLL_UP_EXTEND_SELECTION || 460 key == SCROLL_DOWN_CHANGE_SELECTION || 461 key == SCROLL_DOWN_EXTEND_SELECTION || 462 key == FIRST_COLUMN || 463 key == FIRST_COLUMN_EXTEND_SELECTION || 464 key == FIRST_ROW || 465 key == FIRST_ROW_EXTEND_SELECTION || 466 key == LAST_COLUMN || 467 key == LAST_COLUMN_EXTEND_SELECTION || 468 key == LAST_ROW || 469 key == LAST_ROW_EXTEND_SELECTION) { 470 471 if (table.isEditing() && 472 !table.getCellEditor().stopCellEditing()) { 473 return; 474 } 475 476 488 491 boolean changeLead = false; 492 if (key == NEXT_ROW_CHANGE_LEAD || key == PREVIOUS_ROW_CHANGE_LEAD) { 493 changeLead = (rsm.getSelectionMode() 494 == ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); 495 } else if (key == NEXT_COLUMN_CHANGE_LEAD || key == PREVIOUS_COLUMN_CHANGE_LEAD) { 496 changeLead = (csm.getSelectionMode() 497 == ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); 498 } 499 500 if (changeLead) { 501 moveWithinTableRange(table, dx, dy); 502 if (dy != 0) { 503 ((DefaultListSelectionModel)rsm).moveLeadSelectionIndex(leadRow); 506 if (getAdjustedLead(table, false, csm) == -1 507 && table.getColumnCount() > 0) { 508 509 ((DefaultListSelectionModel)csm).moveLeadSelectionIndex(0); 510 } 511 } else { 512 ((DefaultListSelectionModel)csm).moveLeadSelectionIndex(leadColumn); 515 if (getAdjustedLead(table, true, rsm) == -1 516 && table.getRowCount() > 0) { 517 518 ((DefaultListSelectionModel)rsm).moveLeadSelectionIndex(0); 519 } 520 } 521 522 Rectangle cellRect = table.getCellRect(leadRow, leadColumn, false); 523 if (cellRect != null) { 524 table.scrollRectToVisible(cellRect); 525 } 526 } else if (!inSelection) { 527 moveWithinTableRange(table, dx, dy); 528 table.changeSelection(leadRow, leadColumn, false, extend); 529 } 530 else { 531 if (table.getRowCount() <= 0 || table.getColumnCount() <= 0) { 532 return; 534 } 535 536 if (moveWithinSelectedRange(table, dx, dy, rsm, csm)) { 537 if (rsm.isSelectedIndex(leadRow)) { 540 rsm.addSelectionInterval(leadRow, leadRow); 541 } else { 542 rsm.removeSelectionInterval(leadRow, leadRow); 543 } 544 545 if (csm.isSelectedIndex(leadColumn)) { 546 csm.addSelectionInterval(leadColumn, leadColumn); 547 } else { 548 csm.removeSelectionInterval(leadColumn, leadColumn); 549 } 550 551 Rectangle cellRect = table.getCellRect(leadRow, leadColumn, false); 552 if (cellRect != null) { 553 table.scrollRectToVisible(cellRect); 554 } 555 } 556 else { 557 table.changeSelection(leadRow, leadColumn, 558 false, false); 559 } 560 } 561 562 575 } else if (key == CANCEL_EDITING) { 576 table.removeEditor(); 577 } else if (key == SELECT_ALL) { 578 table.selectAll(); 579 } else if (key == CLEAR_SELECTION) { 580 table.clearSelection(); 581 } else if (key == START_EDITING) { 582 if (!table.hasFocus()) { 583 CellEditor cellEditor = table.getCellEditor(); 584 if (cellEditor != null && !cellEditor.stopCellEditing()) { 585 return; 586 } 587 table.requestFocus(); 588 return; 589 } 590 table.editCellAt(leadRow, leadColumn); 591 Component editorComp = table.getEditorComponent(); 592 if (editorComp != null) { 593 editorComp.requestFocus(); 594 } 595 } else if (key == ADD_TO_SELECTION) { 596 if (!table.isCellSelected(leadRow, leadColumn)) { 597 int oldAnchorRow = rsm.getAnchorSelectionIndex(); 598 int oldAnchorColumn = csm.getAnchorSelectionIndex(); 599 rsm.setValueIsAdjusting(true); 600 csm.setValueIsAdjusting(true); 601 table.changeSelection(leadRow, leadColumn, true, false); 602 rsm.setAnchorSelectionIndex(oldAnchorRow); 603 csm.setAnchorSelectionIndex(oldAnchorColumn); 604 rsm.setValueIsAdjusting(false); 605 csm.setValueIsAdjusting(false); 606 } 607 } else if (key == TOGGLE_AND_ANCHOR) { 608 table.changeSelection(leadRow, leadColumn, true, false); 609 } else if (key == EXTEND_TO) { 610 table.changeSelection(leadRow, leadColumn, false, true); 611 } else if (key == MOVE_SELECTION_TO) { 612 table.changeSelection(leadRow, leadColumn, false, false); 613 } 614 } 615 616 public boolean isEnabled(Object sender) { 617 String key = getName(); 618 619 if (sender instanceof JTable && 620 Boolean.TRUE.equals(((JTable)sender).getClientProperty("Table.isFileList"))) { 621 if (key == NEXT_COLUMN || 622 key == NEXT_COLUMN_CELL || 623 key == NEXT_COLUMN_EXTEND_SELECTION || 624 key == NEXT_COLUMN_CHANGE_LEAD || 625 key == PREVIOUS_COLUMN || 626 key == PREVIOUS_COLUMN_CELL || 627 key == PREVIOUS_COLUMN_EXTEND_SELECTION || 628 key == PREVIOUS_COLUMN_CHANGE_LEAD || 629 key == SCROLL_LEFT_CHANGE_SELECTION || 630 key == SCROLL_LEFT_EXTEND_SELECTION || 631 key == SCROLL_RIGHT_CHANGE_SELECTION || 632 key == SCROLL_RIGHT_EXTEND_SELECTION || 633 key == FIRST_COLUMN || 634 key == FIRST_COLUMN_EXTEND_SELECTION || 635 key == LAST_COLUMN || 636 key == LAST_COLUMN_EXTEND_SELECTION || 637 key == NEXT_ROW_CELL || 638 key == PREVIOUS_ROW_CELL) { 639 640 return false; 641 } 642 } 643 644 if (key == CANCEL_EDITING && sender instanceof JTable) { 645 return ((JTable)sender).isEditing(); 646 } else if (key == NEXT_ROW_CHANGE_LEAD || 647 key == PREVIOUS_ROW_CHANGE_LEAD) { 648 return sender != null && 651 ((JTable)sender).getSelectionModel() 652 instanceof DefaultListSelectionModel; 653 } else if (key == NEXT_COLUMN_CHANGE_LEAD || 654 key == PREVIOUS_COLUMN_CHANGE_LEAD) { 655 return sender != null && 658 ((JTable)sender).getColumnModel().getSelectionModel() 659 instanceof DefaultListSelectionModel; 660 } else if (key == ADD_TO_SELECTION && sender instanceof JTable) { 661 JTable table = (JTable)sender; 669 int leadRow = getAdjustedLead(table, true); 670 int leadCol = getAdjustedLead(table, false); 671 return !(table.isEditing() || table.isCellSelected(leadRow, leadCol)); 672 } 673 674 return true; 675 } 676 } 677 678 679 683 692 public class KeyHandler implements KeyListener { 693 |