1 6 21 22 package de.schlichtherle.io.swing.tree; 23 24 import java.io.FileFilter ; 25 import java.io.IOException ; 26 import java.io.InputStream ; 27 import java.text.Collator ; 28 import java.util.Arrays ; 29 import java.util.Comparator ; 30 import java.util.EventListener ; 31 import java.util.HashMap ; 32 import java.util.Map ; 33 34 import javax.swing.event.EventListenerList ; 35 import javax.swing.event.TreeModelEvent ; 36 import javax.swing.event.TreeModelListener ; 37 import javax.swing.tree.TreeModel ; 38 import javax.swing.tree.TreePath ; 39 40 52 public class FileTreeModel implements TreeModel { 53 54 58 private static final Collator collator = Collator.getInstance(); 59 static { 60 collator.setDecomposition(Collator.NO_DECOMPOSITION); 62 collator.setStrength(java.io.File.separatorChar == '\\' 63 ? Collator.SECONDARY 64 : Collator.TERTIARY); 65 } 66 67 68 public static final Comparator FILE_NAME_COMPARATOR = new Comparator () { 69 public final int compare(Object o1, Object o2) { 70 return compare((java.io.File ) o1, (java.io.File ) o2); 71 } 72 73 public int compare(java.io.File f1, java.io.File f2) { 74 if (f1.isDirectory()) 75 if (f2.isDirectory()) 76 return collator.compare(f1.getName(), f2.getName()); 77 else 78 return -1; 79 else 80 if (f2.isDirectory()) 81 return 1; 82 else 83 return collator.compare(f1.getName(), f2.getName()); 84 } 85 }; 86 87 91 private transient final Map cache = new HashMap (); 93 94 private final java.io.File root; 95 96 private final FileFilter filter; 97 98 103 public FileTreeModel() { 104 this.root = null; 105 this.filter = null; 106 } 107 108 117 public FileTreeModel(java.io.File root) { 118 this.root = root; 119 this.filter = null; 120 } 121 122 133 public FileTreeModel(java.io.File root, FileFilter filter) { 134 this.root = root; 135 this.filter = filter; 136 } 137 138 142 151 public Object getRoot() { 152 return root; 153 } 154 155 public Object getChild(Object parent, int index) { 156 final java.io.File [] children = getChildren((java.io.File ) parent); 157 return children != null ? children[index] : null; 158 } 159 160 public int getChildCount(Object parent) { 161 final java.io.File [] children = getChildren((java.io.File ) parent); 162 return children != null ? children.length : 0; 163 } 164 165 public boolean isLeaf(Object node) { 166 return !((java.io.File ) node).isDirectory(); 167 } 168 169 public void valueForPathChanged(TreePath path, Object newValue) { 170 } 171 172 public int getIndexOfChild(Object parent, Object child) { 173 if (parent == null || child == null) 174 return -1; 175 final java.io.File [] children = getChildren((java.io.File ) parent); 176 if (children == null) 177 return -1; 178 179 for (int i = 0, l = children.length; i < l; i++) 180 if (children[i].equals(child)) 181 return i; 182 183 return -1; 184 } 185 186 private java.io.File [] getChildren(final java.io.File parent) { 187 assert parent != null; 188 189 java.io.File [] children = (java.io.File []) cache.get(parent); 190 if (children == null) { 191 if (cache.containsKey(parent)) 192 return null; children = parent.listFiles(filter); 194 195 cache.put(parent, children); 204 if (children != null) 205 Arrays.sort(children, FILE_NAME_COMPARATOR); 206 } 207 208 return children; 209 } 210 211 215 219 public TreePath getTreePath(java.io.File node) { 220 java.io.File [] elements = getPath(node); 221 return elements != null ? new TreePath (elements) : null; 222 } 223 224 233 private java.io.File [] getPath(java.io.File node) { 234 if (root == null ) 235 return null; 236 237 242 243 return getPath(node, 1); 244 } 245 246 private java.io.File [] getPath(final java.io.File node, int level) { 247 final java.io.File [] path; 248 249 if ( root.equals(node)) { 250 path = new java.io.File [level]; 251 path[0] = root; 252 } else if (node != null) { 253 path = getPath(node.getParentFile(), level + 1); 254 if (path != null) 255 path[path.length - level] = node; 256 } else { 257 path = null; 258 } 259 260 return path; 261 } 262 263 267 278 public boolean createNewFile(final java.io.File node) 279 throws IOException { 280 if (!node.createNewFile()) 281 return false; 282 283 nodeInserted(node); 284 285 return true; 286 } 287 288 297 public boolean mkdir(final java.io.File node) { 298 if (!node.mkdir()) 299 return false; 300 301 nodeInserted(node); 302 303 return true; 304 } 305 306 315 public boolean mkdirs(final java.io.File node) { 316 if (!node.mkdirs()) 317 return false; 318 319 nodeInserted(node); 320 321 return true; 322 } 323 324 334 public boolean copyFrom(final de.schlichtherle.io.File node, final InputStream in) { 335 if (!node.copyFrom(in)) 336 return false; 337 338 nodeInsertedOrStructureChanged(node); 339 340 return true; 341 } 342 343 350 public boolean copyTo(final de.schlichtherle.io.File oldNode, final java.io.File node) { 351 if (!oldNode.copyTo(node)) 352 return false; 353 354 nodeInsertedOrStructureChanged(node); 355 356 return true; 357 } 358 359 366 public boolean copyAllTo(final de.schlichtherle.io.File oldNode, final java.io.File node) { 367 final boolean ok = oldNode.copyAllTo(node); 368 nodeInsertedOrStructureChanged(node); 369 return ok; 370 } 371 372 380 public boolean archiveCopyTo(final de.schlichtherle.io.File oldNode, final java.io.File node) { 381 if (!oldNode.archiveCopyTo(node)) 382 return false; 383 384 nodeInsertedOrStructureChanged(node); 385 386 return true; 387 } 388 389 397 public boolean archiveCopyAllTo(final de.schlichtherle.io.File oldNode, final java.io.File node) { 398 final boolean ok = oldNode.archiveCopyAllTo(node); 399 nodeInsertedOrStructureChanged(node); 400 return ok; 401 } 402 403 410 public boolean renameTo(final java.io.File oldNode, final java.io.File node) { 411 if (!oldNode.renameTo(node)) 412 return false; 413 414 nodeRemoved(oldNode); 415 nodeInserted(node); 416 417 return true; 418 } 419 420 429 public boolean delete(final java.io.File node) { 430 if (!node.delete()) 431 return false; 432 433 nodeRemoved(node); 434 435 return true; 436 } 437 438 447 public boolean deleteAll(final de.schlichtherle.io.File node) { 448 if (!node.deleteAll()) 449 return false; 450 451 nodeRemoved(node); 452 453 return true; 454 } 455 456 460 466 public void nodeInsertedOrStructureChanged(final java.io.File node) { 467 if (node == null) 468 throw new NullPointerException (); 469 470 if (cache.containsKey(node)) 471 structureChanged(node); 472 else 473 nodeInserted(node); 474 } 475 476 482 public void nodeInserted(final java.io.File node) { 483 if (cache.containsKey(node)) 484 return; 485 final java.io.File parent = node.getParentFile(); 486 assert parent != null; 487 forget(parent, false); 488 final int index = getIndexOfChild(parent, node); 489 if (index == -1) 490 return; 491 fireTreeNodesInserted(new TreeModelEvent ( 492 this, getTreePath(parent), 493 new int[] { index }, new java.io.File [] { node })); 494 } 495 496 501 public void nodeChanged(final java.io.File node) { 502 final java.io.File parent = node.getParentFile(); 503 assert parent != null; 504 final int index = getIndexOfChild(parent, node); 505 if (index == -1) 506 return; 507 fireTreeNodesChanged(new TreeModelEvent ( 508 this, getTreePath(parent), 509 new int[] { index }, new java.io.File [] { node })); 510 } 511 512 517 public void nodeRemoved(final java.io.File node) { 518 final java.io.File parent = node.getParentFile(); 519 assert parent != null; 520 if (!cache.containsKey(parent)) 521 return; 522 final int index = getIndexOfChild(parent, node); 523 if (index == -1) 524 return; 525 forget(node); 526 forget(parent, false); 527 fireTreeNodesRemoved(new TreeModelEvent ( 528 this, getTreePath(parent), 529 new int[] { index }, new java.io.File [] { node })); 530 } 531 532 537 public void refresh() { 538 cache.clear(); 539 if (root != null) 540 fireTreeStructureChanged( 541 new TreeModelEvent (this, getTreePath(root), null, null)); 542 } 543 544 545 public final void refresh(final java.io.File node) { 546 structureChanged(node); 547 } 548 549 554 public void structureChanged(final java.io.File node) { 555 if (node == null) 556 throw new NullPointerException (); 557 558 forget(node); 559 fireTreeStructureChanged( 560 new TreeModelEvent (this, getTreePath(node), null, null)); 561 } 562 563 568 public final void forget(final java.io.File node) { 573 forget(node, true); 574 } 575 576 588 private void forget(final java.io.File node, final boolean childrenToo) { 589 final java.io.File [] children = (java.io.File []) cache.remove(node); 590 if (children != null && childrenToo) 591 for (int i = 0, l = children.length; i < l; i++) 592 forget(children[i], childrenToo); 593 } 594 595 599 private transient final EventListenerList listeners = new EventListenerList (); 600 601 606 public void addTreeModelListener(TreeModelListener l) { 607 listeners.add(TreeModelListener .class, l); 608 } 609 610 615 public void removeTreeModelListener(TreeModelListener l) { 616 listeners.remove(TreeModelListener .class, l); 617 } 618 619 624 protected void fireTreeNodesChanged(final TreeModelEvent evt) { 625 final EventListener [] l = listeners.getListeners(TreeModelListener .class); 626 for (int i = 0, ll = l.length; i < ll; i++) 627 ((TreeModelListener ) l[i]).treeNodesChanged(evt); 628 } 629 630 635 protected void fireTreeNodesInserted(final TreeModelEvent evt) { 636 final EventListener [] l = listeners.getListeners(TreeModelListener .class); 637 for (int i = 0, ll = l.length; i < ll; i++) 638 ((TreeModelListener ) l[i]).treeNodesInserted(evt); 639 } 640 641 646 protected void fireTreeNodesRemoved(final TreeModelEvent evt) { 647 final EventListener [] l = listeners.getListeners(TreeModelListener .class); 648 for (int i = 0, ll = l.length; i < ll; i++) 649 ((TreeModelListener ) l[i]).treeNodesRemoved(evt); 650 } 651 652 657 protected void fireTreeStructureChanged(final TreeModelEvent evt) { 658 final EventListener [] l = listeners.getListeners(TreeModelListener .class); 659 for (int i = 0, ll = l.length; i < ll; i++) 660 ((TreeModelListener ) l[i]).treeStructureChanged(evt); 661 } 662 } 663 | Popular Tags |