| 1 7 8 package javax.swing.tree; 9 10 import java.beans.PropertyChangeListener ; 11 import java.io.*; 12 import java.util.BitSet ; 13 import java.util.Enumeration ; 14 import java.util.EventListener ; 15 import java.util.Hashtable ; 16 import java.util.Vector ; 17 import javax.swing.event.*; 18 import javax.swing.DefaultListSelectionModel ; 19 20 47 public class DefaultTreeSelectionModel extends Object implements Cloneable , Serializable, TreeSelectionModel  48 { 49 50 public static final String SELECTION_MODE_PROPERTY = "selectionMode"; 51 52 53 protected SwingPropertyChangeSupport changeSupport; 54 55 57 protected TreePath [] selection; 58 59 60 protected EventListenerList listenerList = new EventListenerList(); 61 62 63 transient protected RowMapper rowMapper; 64 65 67 protected DefaultListSelectionModel listSelectionModel; 68 69 72 protected int selectionMode; 73 74 75 protected TreePath leadPath; 76 77 protected int leadIndex; 78 79 protected int leadRow; 80 81 84 private Hashtable uniquePaths; 85 private Hashtable lastPaths; 86 private TreePath [] tempPaths; 87 88 89 93 public DefaultTreeSelectionModel() { 94 listSelectionModel = new DefaultListSelectionModel (); 95 selectionMode = DISCONTIGUOUS_TREE_SELECTION; 96 leadIndex = leadRow = -1; 97 uniquePaths = new Hashtable (); 98 lastPaths = new Hashtable (); 99 tempPaths = new TreePath [1]; 100 } 101 102 106 public void setRowMapper(RowMapper newMapper) { 107 rowMapper = newMapper; 108 resetRowSelection(); 109 } 110 111 115 public RowMapper getRowMapper() { 116 return rowMapper; 117 } 118 119 133 public void setSelectionMode(int mode) { 134 int oldMode = selectionMode; 135 136 selectionMode = mode; 137 if(selectionMode != TreeSelectionModel.SINGLE_TREE_SELECTION && 138 selectionMode != TreeSelectionModel.CONTIGUOUS_TREE_SELECTION && 139 selectionMode != TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION) 140 selectionMode = TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION; 141 if(oldMode != selectionMode && changeSupport != null) 142 changeSupport.firePropertyChange(SELECTION_MODE_PROPERTY, 143 new Integer (oldMode), 144 new Integer (selectionMode)); 145 } 146 147 152 public int getSelectionMode() { 153 return selectionMode; 154 } 155 156 163 public void setSelectionPath(TreePath path) { 164 if(path == null) 165 setSelectionPaths(null); 166 else { 167 TreePath [] newPaths = new TreePath [1]; 168 169 newPaths[0] = path; 170 setSelectionPaths(newPaths); 171 } 172 } 173 174 188 public void setSelectionPaths(TreePath [] pPaths) { 189 int newCount, newCounter, oldCount, oldCounter; 190 TreePath [] paths = pPaths; 191 192 if(paths == null) 193 newCount = 0; 194 else 195 newCount = paths.length; 196 if(selection == null) 197 oldCount = 0; 198 else 199 oldCount = selection.length; 200 if((newCount + oldCount) != 0) { 201 if(selectionMode == TreeSelectionModel.SINGLE_TREE_SELECTION) { 202 204 if(newCount > 1) { 205 paths = new TreePath [1]; 206 paths[0] = pPaths[0]; 207 newCount = 1; 208 } 209 } 210 else if(selectionMode == 211 TreeSelectionModel.CONTIGUOUS_TREE_SELECTION) { 212 214 if(newCount > 0 && !arePathsContiguous(paths)) { 215 paths = new TreePath [1]; 216 paths[0] = pPaths[0]; 217 newCount = 1; 218 } 219 } 220 221 int validCount = 0; 222 TreePath beginLeadPath = leadPath; 223 Vector cPaths = new Vector (newCount + oldCount); 224 225 lastPaths.clear(); 226 leadPath = null; 227 228 for(newCounter = 0; newCounter < newCount; newCounter++) { 229 if(paths[newCounter] != null && 230 lastPaths.get(paths[newCounter]) == null) { 231 validCount++; 232 lastPaths.put(paths[newCounter], Boolean.TRUE); 233 if (uniquePaths.get(paths[newCounter]) == null) { 234 cPaths.addElement(new PathPlaceHolder 235 (paths[newCounter], true)); 236 } 237 leadPath = paths[newCounter]; 238 } 239 } 240 241 244 TreePath [] newSelection; 245 246 if(validCount == 0) { 247 newSelection = null; 248 } 249 else if (validCount != newCount) { 250 Enumeration keys = lastPaths.keys(); 251 252 newSelection = new TreePath [validCount]; 253 validCount = 0; 254 while (keys.hasMoreElements()) { 255 newSelection[validCount++] = (TreePath )keys.nextElement(); 256 } 257 } 258 else { 259 newSelection = new TreePath [paths.length]; 260 System.arraycopy(paths, 0, newSelection, 0, paths.length); 261 } 262 263 264 for(oldCounter = 0; oldCounter < oldCount; oldCounter++) 265 if(selection[oldCounter] != null && 266 lastPaths.get(selection[oldCounter]) == null) 267 cPaths.addElement(new PathPlaceHolder 268 (selection[oldCounter], false)); 269 270 selection = newSelection; 271 272 Hashtable tempHT = uniquePaths; 273 274 uniquePaths = lastPaths; 275 lastPaths = tempHT; 276 lastPaths.clear(); 277 278 if(selection != null) 280 insureUniqueness(); 281 282 updateLeadIndex(); 283 284 resetRowSelection(); 285 286 if(cPaths.size() > 0) 287 notifyPathChange(cPaths, beginLeadPath); 288 } 289 } 290 291 298 public void addSelectionPath(TreePath path) { 299 if(path != null) { 300 TreePath [] toAdd = new TreePath [1]; 301 302 toAdd[0] = path; 303 addSelectionPaths(toAdd); 304 } 305 } 306 307 322 public void addSelectionPaths(TreePath [] paths) { 323 int newPathLength = ((paths == null) ? 0 : paths.length); 324 325 if(newPathLength > 0) { 326 if(selectionMode == TreeSelectionModel.SINGLE_TREE_SELECTION) { 327 setSelectionPaths(paths); 328 } 329 else if(selectionMode == TreeSelectionModel. 330 CONTIGUOUS_TREE_SELECTION && !canPathsBeAdded(paths)) { 331 if(arePathsContiguous(paths)) { 332 setSelectionPaths(paths); 333 } 334 else { 335 TreePath [] newPaths = new TreePath [1]; 336 337 newPaths[0] = paths[0]; 338 setSelectionPaths(newPaths); 339 } 340 } 341 else { 342 int counter, validCount; 343 int oldCount; 344 TreePath beginLeadPath = leadPath; 345 Vector cPaths = null; 346 347 if(selection == null) 348 oldCount = 0; 349 else 350 oldCount = selection.length; 351 353 lastPaths.clear(); 354 for(counter = 0, validCount = 0; counter < newPathLength; 355 counter++) { 356 if(paths[counter] != null) { 357 if (uniquePaths.get(paths[counter]) == null) { 358 validCount++; 359 if(cPaths == null) 360 cPaths = new Vector (); 361 cPaths.addElement(new PathPlaceHolder 362 (paths[counter], true)); 363 uniquePaths.put(paths[counter], Boolean.TRUE); 364 lastPaths.put(paths[counter], Boolean.TRUE); 365 } 366 leadPath = paths[counter]; 367 } 368 } 369 370 if(leadPath == null) { 371 leadPath = beginLeadPath; 372 } 373 374 if(validCount > 0) { 375 TreePath newSelection[] = new TreePath [oldCount + 376 validCount]; 377 378 379 if(oldCount > 0) 380 System.arraycopy(selection, 0, newSelection, 0, 381 oldCount); 382 if(validCount != paths.length) { 383 385 Enumeration newPaths = lastPaths.keys(); 386 387 counter = oldCount; 388 while (newPaths.hasMoreElements()) { 389 newSelection[counter++] = (TreePath )newPaths. 390 nextElement(); 391 } 392 } 393 else { 394 System.arraycopy(paths, 0, newSelection, oldCount, 395 validCount); 396 } 397 398 selection = newSelection; 399 400 insureUniqueness(); 401 402 updateLeadIndex(); 403 404 resetRowSelection(); 405 406 notifyPathChange(cPaths, beginLeadPath); 407 } 408 else 409 leadPath = beginLeadPath; 410 lastPaths.clear(); 411 } 412 } 413 } 414 415 422 public void removeSelectionPath(TreePath path) { 423 if(path != null) { 424 TreePath [] rPath = new TreePath [1]; 425 426 rPath[0] = path; 427 removeSelectionPaths(rPath); 428 } 429 } 430 431 438 public void removeSelectionPaths(TreePath [] paths) { 439 if (paths != null && selection != null && paths.length > 0) { 440 if(!canPathsBeRemoved(paths)) { 441 442 clearSelection(); 443 } 444 else { 445 Vector pathsToRemove = null; 446 447 448 for (int removeCounter = paths.length - 1; removeCounter >= 0; 449 removeCounter--) { 450 if(paths[removeCounter] != null) { 451 if (uniquePaths.get(paths[removeCounter]) != null) { 452 if(pathsToRemove == null) 453 pathsToRemove = new Vector (paths.length); 454 uniquePaths.remove(paths[removeCounter]); 455 pathsToRemove.addElement(new PathPlaceHolder 456 (paths[removeCounter], false)); 457 } 458 } 459 } 460 if(pathsToRemove != null) { 461 int removeCount = pathsToRemove.size(); 462 TreePath beginLeadPath = leadPath; 463 464 if(removeCount == selection.length) { 465 selection = null; 466 } 467 else { 468 Enumeration pEnum = uniquePaths.keys(); 469 int validCount = 0; 470 471 selection = new TreePath [selection.length - 472 removeCount]; 473 while (pEnum.hasMoreElements()) { 474 selection[validCount++] = (TreePath )pEnum. 475 nextElement(); 476 } 477 } 478 if (leadPath != null && 479 uniquePaths.get(leadPath) == null) { 480 if (selection != null) { 481 leadPath = selection[selection.length - 1]; 482 } 483 else { 484 leadPath = null; 485 } 486 } 487 else if (selection != null) { 488 leadPath = selection[selection.length - 1]; 489 } 490 else { 491 leadPath = null; 492 } 493 updateLeadIndex(); 494 495 resetRowSelection(); 496 497 notifyPathChange(pathsToRemove, beginLeadPath); 498 } 499 } 500 } 501 } 502 503 507 public TreePath getSelectionPath() { 508 if(selection != null) 509 return selection[0]; 510 return null; 511 } 512 513 517 public TreePath [] getSelectionPaths() { 518 if(selection != null) { 519 int pathSize = selection.length; 520 TreePath [] result = new TreePath [pathSize]; 521 522 System.arraycopy(selection, 0, result, 0, pathSize); 523 return result; 524 } 525 return null; 526 } 527 528 531 public int getSelectionCount() { 532 return (selection == null) ? 0 : selection.length; 533 } 534 535 539 public boolean isPathSelected(TreePath path) { 540 return (path != null) ? (uniquePaths.get(path) != null) : false; 541 } 542 543 546 public boolean isSelectionEmpty() { 547 return (selection == null); 548 } 549 550 554 public void clearSelection() { 555 if(selection != null) { 556 int selSize = selection.length; 557 boolean[] newness = new boolean[selSize]; 558 559 for(int counter = 0; counter < selSize; counter++) 560 newness[counter] = false; 561 562 TreeSelectionEvent event = new TreeSelectionEvent 563 (this, selection, newness, leadPath, null); 564 565 leadPath = null; 566 leadIndex = leadRow = -1; 567 uniquePaths.clear(); 568 selection = null; 569 resetRowSelection(); 570 fireValueChanged(event); 571 } 572 } 573 574 580 public void addTreeSelectionListener(TreeSelectionListener x) { 581 listenerList.add(TreeSelectionListener.class, x); 582 } 583 584 590 public void removeTreeSelectionListener(TreeSelectionListener x) { 591 listenerList.remove(TreeSelectionListener.class, x); 592 } 593 594 607 public TreeSelectionListener[] getTreeSelectionListeners() { 608 return (TreeSelectionListener[])listenerList.getListeners( 609 TreeSelectionListener.class); 610 } 611 612 618 protected void fireValueChanged(TreeSelectionEvent e) { 619 Object [] listeners = listenerList.getListenerList(); 621 for (int i = listeners.length-2; i>=0; i-=2) { 625 if (listeners[i]==TreeSelectionListener.class) { 626 ((TreeSelectionListener)listeners[i+1]).valueChanged(e); 630 } 631 } 632 } 633 634 671 public <T extends EventListener > T[] getListeners(Class <T> listenerType) { 672 return listenerList.getListeners(listenerType); 673 } 674 675 683 public int[] getSelectionRows() { 684 if(rowMapper != null && selection != null) { 687 int[] rows = rowMapper.getRowsForPaths(selection); 688 689 if (rows != null) { 690 int invisCount = 0; 691 692 for (int counter = rows.length - 1; counter >= 0; counter--) { 693 if (rows[counter] == -1) { 694 invisCount++; 695 } 696 } 697 if (invisCount > 0) { 698 if (invisCount == rows.length) { 699 rows = null; 700 } 701 else { 702 int[] tempRows = new int[rows.length - invisCount]; 703 704 for (int counter = rows.length - 1, visCounter = 0; 705 counter >= 0; counter--) { 706 if (rows[counter] != -1) { 707 tempRows[visCounter++] = rows[counter]; 708 } 709 } 710 rows = tempRows; 711 } 712 } 713 } 714 return rows; 715 } 716 return null; 717 } 718 719 724 public int getMinSelectionRow() { 725 return listSelectionModel.getMinSelectionIndex(); 726 } 727 728 733 public int getMaxSelectionRow() { 734 return listSelectionModel.getMaxSelectionIndex(); 735 } 736 737 740 public boolean isRowSelected(int row) { 741 return listSelectionModel.isSelectedIndex(row); 742 } 743 744 755 public void resetRowSelection() { 756 listSelectionModel.clearSelection(); 757 if(selection != null && rowMapper != null) { 758 int aRow; 759 int validCount = 0; 760 int[] rows = rowMapper.getRowsForPaths(selection); 761 762 for(int counter = 0, maxCounter = selection.length; 763 counter < maxCounter; counter++) { 764 aRow = rows[counter]; 765 if(aRow != -1) { 766 listSelectionModel.addSelectionInterval(aRow, aRow); 767 } 768 } 769 if(leadIndex != -1 && rows != null) { 770 leadRow = rows[leadIndex]; 771 } 772 else if (leadPath != null) { 773 tempPaths[0] = leadPath; 775 rows = rowMapper.getRowsForPaths(tempPaths); 776 leadRow = (rows != null) ? rows[0] : -1; 777 } 778 else { 779 leadRow = -1; 780 } 781 insureRowContinuity(); 782 783 } 784 else 785 leadRow = -1; 786 } 787 788 792 public int getLeadSelectionRow() { 793 return leadRow; 794 } 795 796 800 public TreePath getLeadSelectionPath() { 801 return leadPath; 802 } 803 804 813 public synchronized void addPropertyChangeListener( 814 PropertyChangeListener listener) { 815 if (changeSupport == null) { 816 changeSupport = new SwingPropertyChangeSupport(this); 817 } 818 changeSupport.addPropertyChangeListener(listener); 819 } 820 821 828 829 public synchronized void removePropertyChangeListener( 830 PropertyChangeListener listener) { 831 if (changeSupport == null) { 832 return; 833 } 834 changeSupport.removePropertyChangeListener(listener); 835 } 836 837 850 public PropertyChangeListener [] getPropertyChangeListeners() { 851 if (changeSupport == null) { 852 return new PropertyChangeListener [0]; 853 } 854 return changeSupport.getPropertyChangeListeners(); 855 } 856 857 871 protected void insureRowContinuity() { 872 if(selectionMode == TreeSelectionModel.CONTIGUOUS_TREE_SELECTION && 873 selection != null && rowMapper != null) { 874 DefaultListSelectionModel lModel = listSelectionModel; 875 int min = lModel.getMinSelectionIndex(); 876 877 if(min != -1) { 878 for(int counter = min, 879 maxCounter = lModel.getMaxSelectionIndex(); 880 counter <= maxCounter; counter++) { 881 if(!lModel.isSelectedIndex(counter)) { 882 if(counter == min) { 883 clearSelection(); 884 } 885 else { 886 TreePath [] newSel = new TreePath [counter - min]; 887 int selectionIndex[] = rowMapper.getRowsForPaths(selection); 888 for (int i = 0; i < selectionIndex.length; i++) { 891 if (selectionIndex[i]<counter) { 892 newSel[selectionIndex[i]-min] = selection[i]; 893 } 894 } 895 setSelectionPaths(newSel); 896 break; 897 &n
|