GNU Classpath (0.20) | |
Frames | No Frames |
1: /* DefaultTreeSelectionModel.java 2: Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: package javax.swing.tree; 39: 40: import java.beans.PropertyChangeListener; 41: import java.io.IOException; 42: import java.io.ObjectInputStream; 43: import java.io.ObjectOutputStream; 44: import java.io.Serializable; 45: import java.util.EventListener; 46: import java.util.Vector; 47: 48: import javax.swing.DefaultListSelectionModel; 49: import javax.swing.event.EventListenerList; 50: import javax.swing.event.SwingPropertyChangeSupport; 51: import javax.swing.event.TreeSelectionEvent; 52: import javax.swing.event.TreeSelectionListener; 53: 54: /** 55: * DefaultTreeSelectionModel 56: * 57: * @author Andrew Selkirk 58: */ 59: public class DefaultTreeSelectionModel 60: implements Cloneable, Serializable, TreeSelectionModel 61: { 62: static final long serialVersionUID = 3288129636638950196L; 63: 64: /** 65: * SELECTION_MODE_PROPERTY 66: */ 67: public static final String SELECTION_MODE_PROPERTY = "selectionMode"; 68: 69: /** 70: * Our Swing property change support. 71: */ 72: protected SwingPropertyChangeSupport changeSupport; 73: 74: /** 75: * The current selection. 76: */ 77: protected TreePath[] selection; 78: 79: /** 80: * Our TreeSelectionListeners. 81: */ 82: protected EventListenerList listenerList; 83: 84: /** 85: * The current RowMapper. 86: */ 87: protected transient RowMapper rowMapper; 88: 89: /** 90: * The current listSelectionModel. 91: */ 92: protected DefaultListSelectionModel listSelectionModel; 93: 94: /** 95: * The current selection mode. 96: */ 97: protected int selectionMode; 98: 99: /** 100: * The path that has been added last. 101: */ 102: protected TreePath leadPath; 103: 104: /** 105: * The index of the last added path. 106: */ 107: protected int leadIndex; 108: 109: /** 110: * The row of the last added path according to the RowMapper. 111: */ 112: protected int leadRow; 113: 114: /** 115: * Constructs a new DefaultTreeSelectionModel. 116: */ 117: public DefaultTreeSelectionModel() 118: { 119: setSelectionMode(DISCONTIGUOUS_TREE_SELECTION); 120: listenerList = new EventListenerList(); 121: } 122: 123: /** 124: * Creates a clone of this DefaultTreeSelectionModel with the same 125: * selection. 126: * 127: * @exception CloneNotSupportedException should not be thrown here 128: * 129: * @return a clone of this DefaultTreeSelectionModel 130: */ 131: public Object clone() throws CloneNotSupportedException 132: { 133: return null; // TODO 134: } 135: 136: /** 137: * Returns a string that shows this object's properties. 138: * 139: * @return a string that shows this object's properties 140: */ 141: public String toString() 142: { 143: return null; // TODO 144: } 145: 146: /** 147: * writeObject 148: * 149: * @param value0 TODO 150: * @exception IOException TODO 151: */ 152: private void writeObject(ObjectOutputStream value0) throws IOException 153: { 154: // TODO 155: } 156: 157: /** 158: * readObject 159: * 160: * @param value0 TODO 161: * @exception IOException TODO 162: * @exception ClassNotFoundException TODO 163: */ 164: private void readObject(ObjectInputStream value0) throws IOException, 165: ClassNotFoundException 166: { 167: // TODO 168: } 169: 170: /** 171: * Sets the RowMapper that should be used to map between paths and their 172: * rows. 173: * 174: * @param rowMapper the RowMapper to set 175: * 176: * @see RowMapper 177: */ 178: public void setRowMapper(RowMapper rowMapper) 179: { 180: // TODO 181: } 182: 183: /** 184: * Returns the RowMapper that is currently used to map between paths and 185: * their rows. 186: * 187: * @return the current RowMapper 188: * 189: * @see RowMapper 190: */ 191: public RowMapper getRowMapper() 192: { 193: return rowMapper; 194: } 195: 196: /** 197: * Sets the current selection mode. Possible values are 198: * {@link #SINGLE_TREE_SELECTION}, {@link #CONTIGUOUS_TREE_SELECTION} and 199: * {@link #DISCONTIGUOUS_TREE_SELECTION}. 200: * 201: * @param mode the selection mode to be set 202: * 203: * @see #getSelectionMode 204: * @see #SINGLE_TREE_SELECTION 205: * @see #CONTIGUOUS_TREE_SELECTION 206: * @see #DISCONTIGUOUS_TREE_SELECTION 207: */ 208: public void setSelectionMode(int mode) 209: { 210: selectionMode = mode; 211: } 212: 213: /** 214: * Returns the current selection mode. 215: * 216: * @return the current selection mode 217: * 218: * @see #setSelectionMode 219: * @see #SINGLE_TREE_SELECTION 220: * @see #CONTIGUOUS_TREE_SELECTION 221: * @see #DISCONTIGUOUS_TREE_SELECTION 222: */ 223: public int getSelectionMode() 224: { 225: return selectionMode; 226: } 227: 228: /** 229: * Sets this path as the only selection. 230: * 231: * If this changes the selection the registered TreeSelectionListeners are 232: * notified. 233: * 234: * @param path the path to set as selection 235: */ 236: public void setSelectionPath(TreePath path) 237: { 238: selection = new TreePath[] { 239: path }; 240: } 241: 242: /** 243: * Sets the paths as selection. This method checks for duplicates and 244: * removes them. 245: * 246: * If this changes the selection the registered TreeSelectionListeners are 247: * notified. 248: * 249: * @param paths the paths to set as selection 250: */ 251: public void setSelectionPaths(TreePath[] paths) 252: { 253: // TODO 254: } 255: 256: /** 257: * Adds a path to the list of selected paths. This method checks if the path 258: * is already selected and doesn't add the same path twice. 259: * 260: * If this changes the selection the registered TreeSelectionListeners are 261: * notified. 262: * 263: * @param path the path to add to the selection 264: */ 265: public void addSelectionPath(TreePath path) 266: { 267: if (!isPathSelected(path)) 268: { 269: if (isSelectionEmpty()) 270: setSelectionPath(path); 271: else 272: { 273: TreePath[] temp = new TreePath[selection.length + 1]; 274: System.arraycopy(selection, 0, temp, 0, selection.length); 275: temp[temp.length - 1] = path; 276: selection = new TreePath[temp.length]; 277: System.arraycopy(temp, 0, selection, 0, temp.length); 278: } 279: leadPath = path; 280: fireValueChanged(new TreeSelectionEvent(this, path, true, 281: leadPath, path)); 282: } 283: } 284: 285: /** 286: * Adds the paths to the list of selected paths. This method checks if the 287: * paths are already selected and doesn't add the same path twice. 288: * 289: * If this changes the selection the registered TreeSelectionListeners are 290: * notified. 291: * 292: * @param paths the paths to add to the selection 293: */ 294: public void addSelectionPaths(TreePath[] paths) 295: { 296: if (paths != null) 297: { 298: TreePath v0 = null; 299: for (int i = 0; i < paths.length; i++) 300: { 301: v0 = paths[i]; 302: if (!isPathSelected(v0)) 303: { 304: if (isSelectionEmpty()) 305: setSelectionPath(v0); 306: else 307: { 308: TreePath[] temp = new TreePath[selection.length + 1]; 309: System.arraycopy(selection, 0, temp, 0, 310: selection.length); 311: temp[temp.length - 1] = v0; 312: selection = new TreePath[temp.length]; 313: System.arraycopy(temp, 0, selection, 0, temp.length); 314: } 315: leadPath = paths[paths.length - 1]; 316: fireValueChanged(new TreeSelectionEvent(this, v0, true, 317: leadPath, paths[0])); 318: } 319: } 320: } 321: } 322: 323: /** 324: * Removes the path from the selection. 325: * 326: * If this changes the selection the registered TreeSelectionListeners are 327: * notified. 328: * 329: * @param path the path to remove 330: */ 331: public void removeSelectionPath(TreePath path) 332: { 333: int index = -1; 334: if (isPathSelected(path)) 335: { 336: for (int i = 0; i < selection.length; i++) 337: { 338: if (selection[i].equals(path)) 339: { 340: index = i; 341: break; 342: } 343: } 344: TreePath[] temp = new TreePath[selection.length - 1]; 345: System.arraycopy(selection, 0, temp, 0, index); 346: System.arraycopy(selection, index + 1, temp, index, 347: selection.length - index - 1); 348: selection = new TreePath[temp.length]; 349: System.arraycopy(temp, 0, selection, 0, temp.length); 350: 351: fireValueChanged(new TreeSelectionEvent(this, path, false, 352: leadPath, path)); 353: } 354: } 355: 356: /** 357: * Removes the paths from the selection. 358: * 359: * If this changes the selection the registered TreeSelectionListeners are 360: * notified. 361: * 362: * @param paths the paths to remove 363: */ 364: public void removeSelectionPaths(TreePath[] paths) 365: { 366: if (paths != null) 367: { 368: int index = -1; 369: TreePath v0 = null; 370: for (int i = 0; i < paths.length; i++) 371: { 372: v0 = paths[i]; 373: if (isPathSelected(v0)) 374: { 375: for (int x = 0; x < selection.length; x++) 376: { 377: if (selection[i].equals(v0)) 378: { 379: index = x; 380: break; 381: } 382: } 383: TreePath[] temp = new TreePath[selection.length - 1]; 384: System.arraycopy(selection, 0, temp, 0, index); 385: System.arraycopy(selection, index + 1, temp, index, 386: selection.length - index - 1); 387: selection = new TreePath[temp.length]; 388: System.arraycopy(temp, 0, selection, 0, temp.length); 389: 390: fireValueChanged(new TreeSelectionEvent(this, v0, false, 391: leadPath, paths[0])); 392: } 393: } 394: } 395: } 396: 397: /** 398: * Returns the first path in the selection. This is especially useful when 399: * the selectionMode is {@link #SINGLE_TREE_SELECTION}. 400: * 401: * @return the first path in the selection 402: */ 403: public TreePath getSelectionPath() 404: { 405: if ((selection == null) || (selection.length == 0)) 406: return null; 407: else 408: return selection[0]; 409: } 410: 411: /** 412: * Returns the complete selection. 413: * 414: * @return the complete selection 415: */ 416: public TreePath[] getSelectionPaths() 417: { 418: return selection; 419: } 420: 421: /** 422: * Returns the number of paths in the selection. 423: * 424: * @return the number of paths in the selection 425: */ 426: public int getSelectionCount() 427: { 428: if (selection == null) 429: return 0; 430: else 431: return selection.length; 432: } 433: 434: /** 435: * Checks if a given path is in the selection. 436: * 437: * @param path the path to check 438: * 439: * @return <code>true</code> if the path is in the selection, 440: * <code>false</code> otherwise 441: */ 442: public boolean isPathSelected(TreePath path) 443: { 444: if (selection == null) 445: return false; 446: 447: for (int i = 0; i < selection.length; i++) 448: { 449: if (selection[i].equals(path)) 450: return true; 451: } 452: return false; 453: } 454: 455: /** 456: * Checks if the selection is empty. 457: * 458: * @return <code>true</code> if the selection is empty, <code>false</code> 459: * otherwise 460: */ 461: public boolean isSelectionEmpty() 462: { 463: return ((selection == null) || (selection.length == 0)); 464: } 465: 466: /** 467: * Removes all paths from the selection. 468: */ 469: public void clearSelection() 470: { 471: leadPath = null; 472: selection = null; 473: } 474: 475: /** 476: * Adds a <code>TreeSelectionListener</code> object to this model. 477: * 478: * @param listener the listener to add 479: */ 480: public void addTreeSelectionListener(TreeSelectionListener listener) 481: { 482: listenerList.add(TreeSelectionListener.class, listener); 483: } 484: 485: /** 486: * Removes a <code>TreeSelectionListener</code> object from this model. 487: * 488: * @param listener the listener to remove 489: */ 490: public void removeTreeSelectionListener(TreeSelectionListener listener) 491: { 492: listenerList.remove(TreeSelectionListener.class, listener); 493: } 494: 495: /** 496: * Returns all <code>TreeSelectionListener</code> added to this model. 497: * 498: * @return an array of listeners 499: * 500: * @since 1.4 501: */ 502: public TreeSelectionListener[] getTreeSelectionListeners() 503: { 504: return (TreeSelectionListener[]) 505: getListeners(TreeSelectionListener.class); 506: } 507: 508: /** 509: * fireValueChanged 510: * 511: * @param event the event to fire. 512: */ 513: protected void fireValueChanged(TreeSelectionEvent event) 514: { 515: TreeSelectionListener[] listeners = getTreeSelectionListeners(); 516: 517: for (int i = 0; i < listeners.length; ++i) 518: listeners[i].valueChanged(event); 519: } 520: 521: /** 522: * Returns all added listeners of a special type. 523: * 524: * @param listenerType the listener type 525: * 526: * @return an array of listeners 527: * 528: * @since 1.3 529: */ 530: public EventListener[] getListeners(Class listenerType) 531: { 532: return listenerList.getListeners(listenerType); 533: } 534: 535: /** 536: * Returns the currently selected rows. 537: * 538: * @return the currently selected rows 539: */ 540: public int[] getSelectionRows() 541: { 542: if (rowMapper == null) 543: return null; 544: else 545: return rowMapper.getRowsForPaths(selection); 546: } 547: 548: /** 549: * Returns the smallest row index from the selection. 550: * 551: * @return the smallest row index from the selection 552: */ 553: public int getMinSelectionRow() 554: { 555: if ((rowMapper == null) || (selection == null) 556: || (selection.length == 0)) 557: return -1; 558: else 559: { 560: int[] rows = rowMapper.getRowsForPaths(selection); 561: int minRow = Integer.MAX_VALUE; 562: for (int index = 0; index < rows.length; index++) 563: minRow = Math.min(minRow, rows[index]); 564: return minRow; 565: } 566: } 567: 568: /** 569: * Returns the largest row index from the selection. 570: * 571: * @return the largest row index from the selection 572: */ 573: public int getMaxSelectionRow() 574: { 575: if ((rowMapper == null) || (selection == null) 576: || (selection.length == 0)) 577: return -1; 578: else 579: { 580: int[] rows = rowMapper.getRowsForPaths(selection); 581: int maxRow = -1; 582: for (int index = 0; index < rows.length; index++) 583: maxRow = Math.max(maxRow, rows[index]); 584: return maxRow; 585: } 586: } 587: 588: /** 589: * Checks if a particular row is selected. 590: * 591: * @param row the index of the row to check 592: * 593: * @return <code>true</code> if the row is in this selection, 594: * <code>false</code> otherwise 595: */ 596: public boolean isRowSelected(int row) 597: { 598: return false; // TODO 599: } 600: 601: /** 602: * Updates the mappings from TreePaths to row indices. 603: */ 604: public void resetRowSelection() 605: { 606: // TODO 607: } 608: 609: /** 610: * getLeadSelectionRow 611: * 612: * @return int 613: */ 614: public int getLeadSelectionRow() 615: { 616: if ((rowMapper == null) || (leadPath == null)) 617: return -1; 618: else 619: return rowMapper.getRowsForPaths(new TreePath[] { 620: leadPath })[0]; 621: } 622: 623: /** 624: * getLeadSelectionPath 625: * 626: * @return TreePath 627: */ 628: public TreePath getLeadSelectionPath() 629: { 630: return leadPath; 631: } 632: 633: /** 634: * Adds a <code>PropertyChangeListener</code> object to this model. 635: * 636: * @param listener the listener to add. 637: */ 638: public void addPropertyChangeListener(PropertyChangeListener listener) 639: { 640: changeSupport.addPropertyChangeListener(listener); 641: } 642: 643: /** 644: * Removes a <code>PropertyChangeListener</code> object from this model. 645: * 646: * @param listener the listener to remove. 647: */ 648: public void removePropertyChangeListener(PropertyChangeListener listener) 649: { 650: changeSupport.removePropertyChangeListener(listener); 651: } 652: 653: /** 654: * Returns all added <code>PropertyChangeListener</code> objects. 655: * 656: * @return an array of listeners. 657: * 658: * @since 1.4 659: */ 660: public PropertyChangeListener[] getPropertyChangeListeners() 661: { 662: return changeSupport.getPropertyChangeListeners(); 663: } 664: 665: /** 666: * Makes sure the currently selected paths are valid according to the 667: * current selectionMode. 668: * 669: * If the selectionMode is set to {@link #CONTIGUOUS_TREE_SELECTION} and the 670: * selection isn't contiguous then the selection is reset to the first set 671: * of contguous paths. 672: * 673: * If the selectionMode is set to {@link #SINGLE_TREE_SELECTION} and the 674: * selection has more than one path, the selection is reset to the contain 675: * only the first path. 676: */ 677: protected void insureRowContinuity() 678: { 679: // TODO 680: } 681: 682: /** 683: * Returns <code>true</code> if the paths are contiguous or we have no 684: * RowMapper assigned. 685: * 686: * @param paths the paths to check for continuity 687: * @return <code>true</code> if the paths are contiguous or we have no 688: * RowMapper assigned 689: */ 690: protected boolean arePathsContiguous(TreePath[] paths) 691: { 692: return false; // TODO 693: } 694: 695: /** 696: * Checks if the paths can be added. This returns <code>true</code> if: 697: * <ul> 698: * <li><code>paths</code> is <code>null</code> or empty</li> 699: * <li>we have no RowMapper assigned</li> 700: * <li>nothing is currently selected</li> 701: * <li>selectionMode is {@link #DISCONTIGUOUS_TREE_SELECTION}</li> 702: * <li>adding the paths to the selection still results in a contiguous set 703: * of paths</li> 704: * 705: * @param paths the paths to check 706: * 707: * @return <code>true</code> if the paths can be added with respect to the 708: * selectionMode 709: */ 710: protected boolean canPathsBeAdded(TreePath[] paths) 711: { 712: return false; // TODO 713: } 714: 715: /** 716: * Checks if the paths can be removed without breaking the continuity of the 717: * selection according to selectionMode. 718: * 719: * @param paths the paths to check 720: * @return <code>true</code> if the paths can be removed with respect to 721: * the selectionMode 722: */ 723: protected boolean canPathsBeRemoved(TreePath[] paths) 724: { 725: return false; // TODO 726: } 727: 728: /** 729: * notifyPathChange 730: * 731: * @param value0 TODO 732: * @param value1 TODO 733: */ 734: protected void notifyPathChange(Vector value0, TreePath value1) 735: { 736: // TODO 737: } 738: 739: /** 740: * Updates the lead index instance field. 741: */ 742: protected void updateLeadIndex() 743: { 744: // TODO 745: } 746: 747: /** 748: * Deprecated and not used. 749: */ 750: protected void insureUniqueness() 751: { 752: // TODO 753: } 754: }
GNU Classpath (0.20) |