1 6 21 22 package de.schlichtherle.io.swing; 23 24 import de.schlichtherle.io.swing.tree.FileTreeModel; 25 import de.schlichtherle.io.swing.tree.FileTreeCellRenderer; 26 27 import java.awt.Toolkit ; 28 import java.io.IOException ; 29 import java.io.InputStream ; 30 import java.util.Enumeration ; 31 import java.util.LinkedList ; 32 import java.util.List ; 33 34 import javax.swing.CellEditor ; 35 import javax.swing.JTree ; 36 import javax.swing.event.CellEditorListener ; 37 import javax.swing.event.ChangeEvent ; 38 import javax.swing.event.TreeExpansionEvent ; 39 import javax.swing.event.TreeExpansionListener ; 40 import javax.swing.tree.TreeCellEditor ; 41 import javax.swing.tree.TreeCellRenderer ; 42 import javax.swing.tree.TreeModel ; 43 import javax.swing.tree.TreePath ; 44 45 57 public class JFileTree extends JTree { 58 59 60 private static final String PROPERTY_DISPLAYING_SUFFIXES = "displayingSuffixes"; 61 62 63 private static final String PROPERTY_EDITING_SUFFIXES = "editingSuffixes"; 64 65 66 private static final String PROPERTY_DEFAULT_SUFFIX = "defaultSuffix"; 67 68 private final TreeExpansionListener tel = new TreeExpansionListener () { 69 public void treeCollapsed(TreeExpansionEvent evt) { 70 ((FileTreeModel) getModel()).forget( 71 (java.io.File ) evt.getPath().getLastPathComponent()); 72 } 73 74 public void treeExpanded(TreeExpansionEvent evt) { 75 } 76 }; 77 78 83 public JFileTree() { 84 this(new FileTreeModel()); 85 } 86 87 96 public JFileTree(java.io.File root) { 97 this(new FileTreeModel(root)); 98 } 99 100 104 public JFileTree(FileTreeModel model) { 105 super(model); 106 107 setCellRenderer(createTreeCellRenderer()); 108 addTreeExpansionListener(tel); 109 } 110 111 protected TreeCellRenderer createTreeCellRenderer() { 112 return new FileTreeCellRenderer(this); 113 } 114 115 119 123 public void setModel(TreeModel model) { 124 super.setModel((FileTreeModel) model); 125 } 126 127 public void setEditable(final boolean editable) { 128 if (editable) { 129 super.setEditable(true); 130 getCellEditor().addCellEditorListener(cel); 131 } else { 132 final CellEditor ce = getCellEditor(); 133 if (ce != null) 134 ce.removeCellEditorListener(cel); 135 super.setEditable(false); 136 } 137 } 138 139 private final CellEditorListener cel = new CellEditorListener () { 140 public void editingCanceled(ChangeEvent evt) { 141 } 142 143 public void editingStopped(ChangeEvent evt) { 144 onEditingStopped(evt); 145 } 146 }; 147 148 151 private boolean displayingSuffixes = true; 152 153 158 public boolean isDisplayingSuffixes() { 159 return this.displayingSuffixes; 160 } 161 162 171 public void setDisplayingSuffixes(boolean displayingSuffixes) { 172 boolean oldDisplayingSuffixes = this.displayingSuffixes; 173 this.displayingSuffixes = displayingSuffixes; 174 firePropertyChange(PROPERTY_DISPLAYING_SUFFIXES, 175 oldDisplayingSuffixes, displayingSuffixes); 176 } 177 178 181 private boolean editingSuffixes = true; 182 183 188 public boolean isEditingSuffixes() { 189 return this.editingSuffixes; 190 } 191 192 200 public void setEditingSuffixes(boolean editingSuffixes) { 201 boolean oldEditingSuffixes = this.editingSuffixes; 202 this.editingSuffixes = editingSuffixes; 203 firePropertyChange(PROPERTY_EDITING_SUFFIXES, 204 oldEditingSuffixes, editingSuffixes); 205 } 206 207 210 private String defaultSuffix; 211 212 217 public String getDefaultSuffix() { 218 return this.defaultSuffix; 219 } 220 221 233 public void setDefaultSuffix(String defaultSuffix) { 234 final String oldDefaultSuffix = this.defaultSuffix; 235 if (defaultSuffix != null) { 236 defaultSuffix = defaultSuffix.trim(); 237 if (defaultSuffix.length() <= 0) 238 defaultSuffix = null; 239 else if (defaultSuffix.charAt(0) != '.') 240 defaultSuffix = "." + defaultSuffix; 241 } 242 this.defaultSuffix = defaultSuffix; 243 firePropertyChange(PROPERTY_DEFAULT_SUFFIX, 244 oldDefaultSuffix, defaultSuffix); 245 } 246 247 251 private java.io.File editedNode; 252 253 257 public java.io.File getEditedNode() { 258 return editedNode; 259 } 260 261 public boolean isEditing() { 262 return editedNode != null; 263 } 264 265 public void startEditingAtPath(TreePath path) { 266 editedNode = (java.io.File ) path.getLastPathComponent(); 267 super.startEditingAtPath(path); 268 } 269 270 public void cancelEditing() { 271 editedNode = null; 272 super.cancelEditing(); 273 } 274 275 public boolean stopEditing() { 276 final boolean stop = super.stopEditing(); 277 if (stop) 278 editedNode = null; 279 return stop; 280 } 281 282 291 protected void onEditingStopped(final ChangeEvent evt) { 292 final TreeCellEditor tce = (TreeCellEditor ) evt.getSource(); 293 String base = tce.getCellEditorValue().toString().trim(); 294 final java.io.File oldNode 295 = (java.io.File ) getLeadSelectionPath().getLastPathComponent(); 296 final java.io.File parent = oldNode.getParentFile(); 297 assert parent != null; 298 if (!oldNode.isDirectory()) { 299 if (isDisplayingSuffixes() && isEditingSuffixes()) { 300 final String suffix = getSuffix(base); 301 if (suffix == null) { 302 final String defaultSuffix = getDefaultSuffix(); 303 if (defaultSuffix != null) 304 base += defaultSuffix; 305 } 306 } else { 307 final String suffix = getSuffix(oldNode.getName()); 308 if (suffix != null) 309 base += suffix; 310 } 311 } 312 final java.io.File node = new de.schlichtherle.io.File(parent, base); 313 314 if (!renameTo(oldNode, node)) 315 Toolkit.getDefaultToolkit().beep(); 316 } 317 318 private String getSuffix(final String base) { 319 final int i = base.lastIndexOf('.'); 320 return i != -1 ? base.substring(i) : null; 321 } 322 323 327 public String convertValueToText( 328 final Object value, 329 final boolean selected, 330 final boolean expanded, 331 final boolean leaf, 332 final int row, 333 final boolean hasFocus) { 334 final java.io.File node = (java.io.File ) value; 335 final java.io.File editedNode = getEditedNode(); 336 if (node != editedNode && !node.exists()) { 337 return "?"; 342 } 343 344 final String base = node.getName(); 345 if (base.length() <= 0) 346 return node.getPath(); if (node.isDirectory() || 348 isDisplayingSuffixes() 349 && (!node.equals(editedNode) || isEditingSuffixes())) 350 return base; 351 final int i = base.lastIndexOf('.'); 352 return i != -1 ? base.substring(0, i) : base; 353 } 354 355 359 364 public void refresh() { 365 final FileTreeModel ftm = (FileTreeModel) getModel(); 366 final TreePath path = ftm.getTreePath((java.io.File ) ftm.getRoot()); 367 if (path != null) 368 refresh(new TreePath [] { path }); 369 } 370 371 380 public void refresh(final java.io.File node) { 381 if (node == null) 382 throw new NullPointerException (); 383 384 final FileTreeModel ftm = (FileTreeModel) getModel(); 385 final TreePath path = ftm.getTreePath(node); 386 if (path != null) 387 refresh(new TreePath [] { path }); 388 } 389 390 398 public void refresh(final TreePath paths[]) { 399 if (paths == null || paths.length <= 0) 400 return; 401 402 final FileTreeModel ftm = (FileTreeModel) getModel(); 403 404 final TreePath lead = getLeadSelectionPath(); 405 final TreePath anchor = getAnchorSelectionPath(); 406 final TreePath [] selections = getSelectionPaths(); 407 408 for (int i = 0, l = paths.length; i < l; i++) { 409 final TreePath path = paths[i]; 410 final Enumeration expansions = getExpandedDescendants(path); 411 ftm.refresh((java.io.File ) path.getLastPathComponent()); 412 setExpandedDescendants(expansions); 413 } 414 415 setSelectionPaths(selections); 416 setAnchorSelectionPath(anchor); 417 setLeadSelectionPath(lead); 418 scrollPathToVisible(lead); 419 } 420 421 private void setExpandedDescendants(final Enumeration expansions) { 422 if (expansions == null) 423 return; 424 while (expansions.hasMoreElements()) 425 setExpandedState((TreePath ) expansions.nextElement(), true); 426 } 427 428 432 439 public boolean createNewFile(final java.io.File node) throws IOException { 440 final FileTreeModel ftm = (FileTreeModel) getModel(); 441 final TreePath path = ftm.getTreePath(node); 442 if (path == null) 443 return false; 444 445 if (!ftm.createNewFile(node)) 446 return false; 447 448 setSelectionPath(path); 449 scrollPathToVisible(path); 450 451 return true; 452 } 453 454 459 public boolean mkdir(final java.io.File node) { 460 final FileTreeModel ftm = (FileTreeModel) getModel(); 461 final TreePath path = ftm.getTreePath(node); 462 if (path == null) 463 return false; 464 465 if (!ftm.mkdir(node)) 466 return false; 467 468 setSelectionPath(path); 469 scrollPathToVisible(path); 470 471 return true; 472 } 473 474 479 public boolean mkdirs(final java.io.File node) { 480 final FileTreeModel ftm = (FileTreeModel) getModel(); 481 final TreePath path = ftm.getTreePath(node); 482 if (path == null) 483 return false; 484 485 if (!ftm.mkdirs(node)) 486 return false; 487 488 setSelectionPath(path); 489 scrollPathToVisible(path); 490 491 return true; 492 } 493 494 499 public boolean copyFrom(final de.schlichtherle.io.File node, final InputStream in) { 500 final FileTreeModel ftm = (FileTreeModel) getModel(); 501 final TreePath path = ftm.getTreePath(node); 502 if (path == null) 503 return false; 504 505 if (!ftm.copyFrom(node, in)) 506 return false; 507 508 setSelectionPath(path); 509 scrollPathToVisible(path); 510 511 return true; 512 } 513 514 519 public boolean copyTo(final de.schlichtherle.io.File oldNode, final java.io.File node) { 520 final FileTreeModel ftm = (FileTreeModel) getModel(); 521 final TreePath path = ftm.getTreePath(node); 522 if (path == null) 523 return false; 524 525 if (!ftm.copyTo(oldNode, node)) 526 return false; 527 528 setSelectionPath(path); 529 scrollPathToVisible(path); 530 531 return true; 532 } 533 534 539 public boolean copyAllTo(final de.schlichtherle.io.File oldNode, final java.io.File node) { 540 final FileTreeModel ftm = (FileTreeModel) getModel(); 541 final TreePath path = ftm.getTreePath(node); 542 if (path == null) 543 return false; 544 545 if (!ftm.copyAllTo(oldNode, node)) 546 return false; 547 548 setSelectionPath(path); 549 scrollPathToVisible(path); 550 551 return true; 552 } 553 554 559 public boolean archiveCopyTo(final de.schlichtherle.io.File oldNode, final java.io.File node) { 560 final FileTreeModel ftm = (FileTreeModel) getModel(); 561 final TreePath path = ftm.getTreePath(node); 562 if (path == null) 563 return false; 564 565 if (!ftm.archiveCopyTo(oldNode, node)) 566 return false; 567 568 setSelectionPath(path); 569 scrollPathToVisible(path); 570 571 return true; 572 } 573 574 579 public boolean archiveCopyAllTo(final de.schlichtherle.io.File oldNode, final java.io.File node) { 580 final FileTreeModel ftm = (FileTreeModel) getModel(); 581 final TreePath path = ftm.getTreePath(node); 582 if (path == null) 583 return false; 584 585 if (!ftm.archiveCopyAllTo(oldNode, node)) 586 return false; 587 588 setSelectionPath(path); 589 scrollPathToVisible(path); 590 591 return true; 592 } 593 594 599 public boolean renameTo(final java.io.File oldNode, final java.io.File node) { 600 final FileTreeModel ftm = (FileTreeModel) getModel(); 601 final TreePath path = ftm.getTreePath(node); 602 if (path == null) 603 return false; 604 605 final Enumeration expansions; 606 final TreePath oldPath = ftm.getTreePath(oldNode); 607 if (oldPath != null) 608 expansions = getExpandedDescendants(oldPath); 609 else 610 expansions = null; 611 612 if (!ftm.renameTo(oldNode, node)) 613 return false; 614 615 if (expansions != null) 616 while (expansions.hasMoreElements()) 617 setExpandedState( 618 substPath((TreePath ) expansions.nextElement(), 619 oldPath, path), 620 true); 621 setSelectionPath(path); 622 scrollPathToVisible(path); 623 624 return true; 625 } 626 627 private TreePath substPath( 628 final TreePath tp, 629 final TreePath oldPath, 630 final TreePath path) { 631 final java.io.File file = (java.io.File ) tp.getLastPathComponent(); 632 if (file.equals(oldPath.getLastPathComponent())) { 633 return path; 634 } else { 635 final TreePath parent = substPath(tp.getParentPath(), oldPath, path); 636 return parent.pathByAddingChild( 637 new de.schlichtherle.io.File((java.io.File ) parent.getLastPathComponent(), 638 file.getName())); 639 } 640 } 641 642 647 public boolean delete(final java.io.File node) { 648 final FileTreeModel ftm = (FileTreeModel) getModel(); 649 final TreePath path = ftm.getTreePath(node); 650 if (path == null) 651 return false; 652 scrollPathToVisible(path); 653 final int row = getRowForPath(path); 654 655 if (!ftm.delete(node)) 656 return false; 657 658 setSelectionRow(row); 659 660 return true; 661 } 662 663 668 public boolean deleteAll(final de.schlichtherle.io.File node) { 669 final FileTreeModel ftm = (FileTreeModel) getModel(); 670 final TreePath path = ftm.getTreePath(node); 671 if (path == null) 672 return false; 673 scrollPathToVisible(path); 674 final int row = getRowForPath(path); 675 676 if (!ftm.deleteAll(node)) 677 return false; 678 679 setSelectionRow(row); 680 681 return true; 682 } 683 684 public void setSelectionNode(final java.io.File node) { 685 final FileTreeModel ftm = (FileTreeModel) getModel(); 686 final TreePath path = ftm.getTreePath(node); 687 if (path != null) { 688 setSelectionPath(path); 689 } 690 } 691 692 public void setSelectionNodes(final java.io.File [] nodes) { 693 final FileTreeModel ftm = (FileTreeModel) getModel(); 694 695 final List list = new LinkedList (); 696 TreePath lastPath = null; 697 for (int i = 0, l = nodes.length; i < l; i++) { 698 lastPath = ftm.getTreePath(nodes[i]); 699 if (lastPath != null) 700 list.add(lastPath); 701 } 702 703 final int size = list.size(); 704 if (size > 0) { 705 final TreePath [] paths = new TreePath [size]; 706 list.toArray(paths); 707 setSelectionPaths(paths); 708 } 709 } 710 711 public void scrollNodeToVisible(final java.io.File node) { 712 final FileTreeModel ftm = (FileTreeModel) getModel(); 713 final TreePath path = ftm.getTreePath(node); 714 if (path != null) { 715 scrollPathToVisible(path); 716 } 717 } 718 } 719 | Popular Tags |