1 23 24 package org.gjt.sp.jedit.search; 25 26 import javax.swing.*; 28 import javax.swing.tree.*; 29 30 import java.awt.*; 31 import java.awt.event.*; 32 import java.util.*; 33 import org.gjt.sp.jedit.gui.DefaultFocusComponent; 34 import org.gjt.sp.jedit.gui.RolloverButton; 35 import org.gjt.sp.jedit.msg.*; 36 import org.gjt.sp.jedit.*; 37 39 44 public class HyperSearchResults extends JPanel implements EBComponent, 45 DefaultFocusComponent 46 { 47 public static final String NAME = "hypersearch-results"; 48 49 public HyperSearchResults(View view) 51 { 52 super(new BorderLayout()); 53 54 this.view = view; 55 56 caption = new JLabel(); 57 58 Box toolBar = new Box(BoxLayout.X_AXIS); 59 toolBar.add(caption); 60 toolBar.add(Box.createGlue()); 61 62 ActionHandler ah = new ActionHandler(); 63 64 clear = new RolloverButton(GUIUtilities.loadIcon("Clear.png")); 65 clear.setToolTipText(jEdit.getProperty( 66 "hypersearch-results.clear.label")); 67 clear.addActionListener(ah); 68 toolBar.add(clear); 69 70 multi = new RolloverButton(); 71 multi.setToolTipText(jEdit.getProperty( 72 "hypersearch-results.multi.label")); 73 multi.addActionListener(ah); 74 toolBar.add(multi); 75 76 add(BorderLayout.NORTH, toolBar); 77 78 resultTreeRoot = new DefaultMutableTreeNode(); 79 resultTreeModel = new DefaultTreeModel(resultTreeRoot); 80 resultTree = new JTree(resultTreeModel); 81 resultTree.setToolTipText(""); 82 resultTree.setCellRenderer(new ResultCellRenderer()); 83 resultTree.setVisibleRowCount(16); 84 resultTree.setRootVisible(false); 85 resultTree.setShowsRootHandles(true); 86 87 if(!OperatingSystem.isMacOSLF()) 89 resultTree.putClientProperty("JTree.lineStyle", "Angled"); 90 91 resultTree.setEditable(false); 92 93 resultTree.addKeyListener(new KeyHandler()); 94 resultTree.addMouseListener(new MouseHandler()); 95 96 JScrollPane scrollPane = new JScrollPane(resultTree); 97 Dimension dim = scrollPane.getPreferredSize(); 98 dim.width = 400; 99 scrollPane.setPreferredSize(dim); 100 add(BorderLayout.CENTER, scrollPane); 101 } 103 public void focusOnDefaultComponent() 105 { 106 resultTree.requestFocus(); 107 } 109 public void addNotify() 111 { 112 super.addNotify(); 113 EditBus.addToBus(this); 114 multiStatus = jEdit.getBooleanProperty( 115 "hypersearch-results.multi"); 116 updateMultiStatus(); 117 } 119 public void removeNotify() 121 { 122 super.removeNotify(); 123 EditBus.removeFromBus(this); 124 jEdit.setBooleanProperty("hypersearch-results.multi",multiStatus); 125 } 127 private void visitBuffers(final ResultVisitor visitor, final Buffer buffer) 129 { 130 traverseNodes(resultTreeRoot, new TreeNodeCallbackAdapter() { 133 public boolean processNode(DefaultMutableTreeNode node) { 134 Object userObject = node.getUserObject(); 135 if (!(userObject instanceof HyperSearchResult)) 136 return true; 137 HyperSearchResult result = (HyperSearchResult) userObject; 138 if (result.pathEquals(buffer.getSymlinkPath())) 139 visitor.visit(buffer, result); 140 return true; 141 } 142 }); 143 } 145 public void handleMessage(EBMessage msg) 147 { 148 if(msg instanceof BufferUpdate) 149 { 150 BufferUpdate bmsg = (BufferUpdate)msg; 151 Buffer buffer = bmsg.getBuffer(); 152 Object what = bmsg.getWhat(); 153 if(what == BufferUpdate.LOADED) 154 visitBuffers(new BufferLoadedVisitor(),buffer); 155 else if(what == BufferUpdate.CLOSED) 156 visitBuffers(new BufferClosedVisitor(),buffer); 157 } 158 } 160 public static boolean traverseNodes(DefaultMutableTreeNode node, 162 HyperSearchTreeNodeCallback callbackInterface) 163 { 164 if (!callbackInterface.processNode(node)) 165 return false; 166 for (Enumeration e = node.children(); e.hasMoreElements();) 167 { 168 DefaultMutableTreeNode childNode = (DefaultMutableTreeNode)e.nextElement(); 169 if (!traverseNodes(childNode, callbackInterface)) 170 return false; 171 } 172 return true; 173 } 175 public DefaultTreeModel getTreeModel() 177 { 178 return resultTreeModel; 179 } 181 186 public JTree getTree() 187 { 188 return resultTree; 189 } 191 public void searchStarted() 193 { 194 caption.setText(jEdit.getProperty("hypersearch-results.searching")); 195 } 197 public void setSearchStatus(String status) 199 { 200 caption.setText(status); 201 } 203 public void searchFailed() 205 { 206 caption.setText(jEdit.getProperty("hypersearch-results.no-results")); 207 208 for(int i = 0; i < resultTreeRoot.getChildCount(); i++) 210 { 211 DefaultMutableTreeNode node = (DefaultMutableTreeNode) 212 resultTreeRoot.getChildAt(i); 213 resultTree.collapsePath(new TreePath(new Object [] { 214 resultTreeRoot, node })); 215 } 216 } 218 public void searchDone(final DefaultMutableTreeNode searchNode) 220 { 221 final int nodeCount = searchNode.getChildCount(); 222 if (nodeCount < 1) 223 { 224 searchFailed(); 225 return; 226 } 227 228 caption.setText(jEdit.getProperty("hypersearch-results.done")); 229 230 SwingUtilities.invokeLater(new Runnable () 231 { 232 public void run() 233 { 234 if(!multiStatus) 235 { 236 for(int i = 0; i < resultTreeRoot.getChildCount(); i++) 237 { 238 resultTreeRoot.remove(0); 239 } 240 } 241 242 resultTreeRoot.add(searchNode); 243 resultTreeModel.reload(resultTreeRoot); 244 245 TreePath lastNode = null; 246 247 for(int i = 0; i < nodeCount; i++) 248 { 249 lastNode = new TreePath( 250 ((DefaultMutableTreeNode) 251 searchNode.getChildAt(i)) 252 .getPath()); 253 254 resultTree.expandPath(lastNode); 255 } 256 257 resultTree.scrollPathToVisible( 258 new TreePath(new Object [] { 259 resultTreeRoot,searchNode })); 260 } 261 }); 262 } 264 private View view; 266 267 private JLabel caption; 268 private JTree resultTree; 269 private DefaultMutableTreeNode resultTreeRoot; 270 private DefaultTreeModel resultTreeModel; 271 272 private RolloverButton clear; 273 private RolloverButton multi; 274 private boolean multiStatus; 275 276 private void updateMultiStatus() 278 { 279 if(multiStatus) 280 multi.setIcon(GUIUtilities.loadIcon("MultipleResults.png")); 281 else 282 multi.setIcon(GUIUtilities.loadIcon("SingleResult.png")); 283 } 285 public static final int M_OPEN = 0; 287 public static final int M_OPEN_NEW_VIEW = 1; 288 public static final int M_OPEN_NEW_PLAIN_VIEW = 2; 289 public static final int M_OPEN_NEW_SPLIT = 3; 290 291 private void goToSelectedNode(int mode) 292 { 293 TreePath path = resultTree.getSelectionPath(); 294 if(path == null) 295 return; 296 297 DefaultMutableTreeNode node = (DefaultMutableTreeNode)path 298 .getLastPathComponent(); 299 Object value = node.getUserObject(); 300 301 if(node.getParent() != resultTreeRoot && value instanceof HyperSearchNode) 303 { 304 HyperSearchNode n = (HyperSearchNode)value; 305 Buffer buffer = n.getBuffer(); 306 if(buffer == null) 307 return; 308 309 EditPane pane; 310 311 switch(mode) 312 { 313 case M_OPEN: 314 pane = view.goToBuffer(buffer); 315 break; 316 case M_OPEN_NEW_VIEW: 317 pane = jEdit.newView(view,buffer,false).getEditPane(); 318 break; 319 case M_OPEN_NEW_PLAIN_VIEW: 320 pane = jEdit.newView(view,buffer,true).getEditPane(); 321 break; 322 case M_OPEN_NEW_SPLIT: 323 pane = view.splitHorizontally(); 324 break; 325 default: 326 throw new IllegalArgumentException ("Bad mode: " + mode); 327 } 328 329 ((HyperSearchNode)value).goTo(pane); 330 } 331 } 333 335 public class ActionHandler implements ActionListener 337 { 338 public void actionPerformed(ActionEvent evt) 339 { 340 Object source = evt.getSource(); 341 if(source == clear) 342 { 343 resultTreeRoot.removeAllChildren(); 344 resultTreeModel.reload(resultTreeRoot); 345 } 346 else if(source == multi) 347 { 348 multiStatus = !multiStatus; 349 updateMultiStatus(); 350 351 if(!multiStatus) 352 { 353 for(int i = resultTreeRoot.getChildCount() - 2; i >= 0; i--) 354 { 355 resultTreeModel.removeNodeFromParent( 356 (MutableTreeNode)resultTreeRoot 357 .getChildAt(i)); 358 } 359 } 360 } 361 } 362 } 364 class KeyHandler extends KeyAdapter 366 { 367 public void keyPressed(KeyEvent evt) 368 { 369 if(evt.getKeyCode() == KeyEvent.VK_ENTER) 370 { 371 goToSelectedNode(M_OPEN); 372 373 SwingUtilities.invokeLater(new Runnable () 375 { 376 public void run() 377 { 378 resultTree.requestFocus(); 379 } 380 }); 381 382 evt.consume(); 383 } 384 } 385 } 387 class MouseHandler extends MouseAdapter 389 { 390 public void mousePressed(MouseEvent evt) 392 { 393 if(evt.isConsumed()) 394 return; 395 396 TreePath path1 = resultTree.getPathForLocation( 397 evt.getX(),evt.getY()); 398 if(path1 == null) 399 return; 400 401 resultTree.setSelectionPath(path1); 402 if (GUIUtilities.isPopupTrigger(evt)) 403 showPopupMenu(evt); 404 else 405 { 406 goToSelectedNode(M_OPEN); 407 408 view.toFront(); 409 view.requestFocus(); 410 view.getTextArea().requestFocus(); 411 } 412 } 414 private JPopupMenu popupMenu; 416 417 private void showPopupMenu(MouseEvent evt) 419 { 420 TreePath path = resultTree.getSelectionPath(); 421 DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent(); 422 423 popupMenu = new JPopupMenu(); 424 Object userObj = node.getUserObject(); 425 if (userObj instanceof HyperSearchFileNode 426 || userObj instanceof HyperSearchResult) 427 { 428 popupMenu.add(new GoToNodeAction( 429 "hypersearch-results.open", 430 M_OPEN)); 431 popupMenu.add(new GoToNodeAction( 432 "hypersearch-results.open-view", 433 M_OPEN_NEW_VIEW)); 434 popupMenu.add(new GoToNodeAction( 435 "hypersearch-results.open-plain-view", 436 M_OPEN_NEW_PLAIN_VIEW)); 437 popupMenu.add(new GoToNodeAction( 438 "hypersearch-results.open-split", 439 M_OPEN_NEW_SPLIT)); 440 } 441 if (!(userObj instanceof HyperSearchFolderNode)) 442 popupMenu.add(new RemoveTreeNodeAction()); 443 popupMenu.add(new ExpandChildTreeNodesAction()); 444 if (userObj instanceof HyperSearchFolderNode 445 || userObj instanceof HyperSearchOperationNode) 446 { 447 popupMenu.add(new CollapseChildTreeNodesAction()); 448 if (userObj instanceof HyperSearchFolderNode) 449 popupMenu.add(new NewSearchAction()); 450 } 451 if (userObj instanceof HyperSearchOperationNode) 452 { 453 popupMenu.add(new JPopupMenu.Separator()); 454 HyperSearchOperationNode resultNode = (HyperSearchOperationNode)userObj; 455 JCheckBoxMenuItem chkItem = 456 new JCheckBoxMenuItem(jEdit.getProperty("hypersearch-results.tree-view"), 457 resultNode.isTreeViewDisplayed()); 458 chkItem.addActionListener(new TreeDisplayAction()); 459 popupMenu.add(chkItem); 460 } 461 462 GUIUtilities.showPopupMenu(popupMenu,evt.getComponent(), 463 evt.getX(),evt.getY()); 464 evt.consume(); 465 } 467 } 470 class RemoveTreeNodeAction extends AbstractAction 472 { 473 RemoveTreeNodeAction() 474 { 475 super(jEdit.getProperty("hypersearch-results.remove-node")); 476 } 477 478 public void actionPerformed(ActionEvent evt) 479 { 480 TreePath path = resultTree.getSelectionPath(); 481 if(path == null) 482 return; 483 484 MutableTreeNode value = (MutableTreeNode)path 485 .getLastPathComponent(); 486 HyperSearchOperationNode.removeNodeFromCache(value); 487 resultTreeModel.removeNodeFromParent(value); 488 } 489 } 491 class RemoveAllTreeNodesAction extends AbstractAction 493 { 494 RemoveAllTreeNodesAction() 495 { 496 super(jEdit.getProperty("hypersearch-results.remove-all-nodes")); 497 } 498 499 public void actionPerformed(ActionEvent evt) 500 { 501 resultTreeRoot = new DefaultMutableTreeNode(); 502 resultTreeModel = new DefaultTreeModel(resultTreeRoot); 503 resultTree.setModel(resultTreeModel); 504 } 505 } 507 class NewSearchAction extends AbstractAction 509 { 510 NewSearchAction() 511 { 512 super(jEdit.getProperty("hypersearch-results.new-search")); 513 } 514 515 public void actionPerformed(ActionEvent evt) 516 { 517 TreePath path = resultTree.getSelectionPath(); 518 DefaultMutableTreeNode operNode = (DefaultMutableTreeNode)path.getLastPathComponent(); 519 HyperSearchFolderNode nodeObj = (HyperSearchFolderNode)operNode.getUserObject(); 520 521 String glob = "*"; 522 SearchFileSet dirList = SearchAndReplace.getSearchFileSet(); 523 if (dirList instanceof DirectoryListSet) 524 glob = ((DirectoryListSet)dirList).getFileFilter(); 525 SearchAndReplace.setSearchFileSet(new DirectoryListSet( 526 nodeObj.getNodeFile().getAbsolutePath(),glob,true)); 527 SearchDialog.showSearchDialog(view,null,SearchDialog.DIRECTORY); 528 } 529 } 531 532 class ExpandChildTreeNodesAction extends AbstractAction 534 { 535 ExpandChildTreeNodesAction() 536 { 537 super(jEdit.getProperty("hypersearch-results.expand-child-nodes")); 538 } 539 540 public void actionPerformed(ActionEvent evt) 541 { 542 TreePath path = resultTree.getSelectionPath(); 543 DefaultMutableTreeNode operNode = (DefaultMutableTreeNode)path.getLastPathComponent(); 544 expandAllNodes(operNode); 545 } 546 } 548 class CollapseChildTreeNodesAction extends AbstractAction 550 { 551 CollapseChildTreeNodesAction() 552 { 553 super(jEdit.getProperty("hypersearch-results.collapse-child-nodes")); 554 } 555 556 public void actionPerformed(ActionEvent evt) 557 { 558 TreePath path = resultTree.getSelectionPath(); 559 DefaultMutableTreeNode operNode = (DefaultMutableTreeNode)path.getLastPathComponent(); 560 for (Enumeration e = operNode.children(); e.hasMoreElements();) 561 { 562 DefaultMutableTreeNode node = (DefaultMutableTreeNode)e.nextElement(); 563 resultTree.collapsePath(new TreePath(node.getPath())); 564 } 565 resultTree.scrollPathToVisible( 566 new TreePath(operNode.getPath())); 567 } 568 } 570 class TreeDisplayAction extends AbstractAction 572 { 573 public void actionPerformed(ActionEvent evt) 575 { 576 JCheckBoxMenuItem menuItem = (JCheckBoxMenuItem) evt.getSource(); 577 boolean curState = menuItem.isSelected(); 578 579 TreePath path = resultTree.getSelectionPath(); 580 DefaultMutableTreeNode operNode = (DefaultMutableTreeNode)path.getLastPathComponent(); 581 582 HyperSearchOperationNode operNodeObj = (HyperSearchOperationNode)operNode.getUserObject(); 583 if (curState) 584 operNodeObj.cacheResultNodes(operNode); 585 operNode.removeAllChildren(); 586 Exception excp = null; 587 if (curState) 588 { 589 try 590 { 591 operNodeObj.insertTreeNodes(resultTree, operNode); 592 } 593 catch (Exception ex) 594 { 595 operNodeObj.restoreFlatNodes(resultTree, operNode); 596 menuItem.setSelected(false); 597 excp = ex; 598 } 599 finally 600 { 601 ((DefaultTreeModel)resultTree.getModel()).nodeStructureChanged(operNode); 602 expandAllNodes(operNode); 603 resultTree.scrollPathToVisible( 604 new TreePath(operNode.getPath())); 605 } 606 if (excp != null) 607 throw new RuntimeException (excp); 608 } 609 else 610 operNodeObj.restoreFlatNodes(resultTree, operNode); 611 612 operNodeObj.setTreeViewDisplayed(menuItem.isSelected()); 613 } 614 } 616 public void expandAllNodes(DefaultMutableTreeNode node) 617 { 618 619 traverseNodes(node, new TreeNodeCallbackAdapter() 620 { 621 public boolean processNode(DefaultMutableTreeNode node) { 622 resultTree.expandPath(new TreePath(node.getPath())); 623 return true; 624 } 625 }); 626 } 627 628 class GoToNodeAction extends AbstractAction 630 { 631 private int mode; 632 633 GoToNodeAction(String labelProp, int mode) 634 { 635 super(jEdit.getProperty(labelProp)); 636 this.mode = mode; 637 } 638 639 public void actionPerformed(ActionEvent evt) 640 { 641 goToSelectedNode(mode); 642 } 643 } 645 class ResultCellRenderer extends DefaultTreeCellRenderer 647 { 648 Font plainFont, boldFont; 649 650 ResultCellRenderer() 652 { 653 plainFont = UIManager.getFont("Tree.font"); 654 if(plainFont == null) 655 plainFont = jEdit.getFontProperty("metal.secondary.font"); 656 boldFont = new Font(plainFont.getName(),Font.BOLD, 657 plainFont.getSize()); 658 } 660 public Component getTreeCellRendererComponent(JTree tree, 662 Object value, boolean sel, boolean expanded, 663 boolean leaf, int row, boolean hasFocus) 664 { 665 super.getTreeCellRendererComponent(tree,value,sel, 666 expanded,leaf,row,hasFocus); 667 setIcon(null); 668 DefaultMutableTreeNode node = (DefaultMutableTreeNode)value; 669 670 if (node.getUserObject() instanceof HyperSearchOperationNode) 671 { 672 setFont(boldFont); 673 674 675 CountNodes countNodes = new CountNodes(); 676 traverseNodes(node, countNodes); 677 678 String property = "hypersearch-results.result-caption"; 679 if (countNodes.bufferCount == 1) 680 { 681 property += countNodes.resultCount == 1 ? "1" : "2"; 682 } 683 684 Object [] pp = { node.toString(), Integer.valueOf(countNodes.resultCount), 685 Integer.valueOf(countNodes.bufferCount)}; 686 setText(jEdit.getProperty(property,pp)); 687 } 688 else if(node.getUserObject() instanceof HyperSearchFolderNode) 689 { 690 setFont(plainFont); 691 setText(node.toString() + " (" + node.getChildCount() + " files/folders)"); 692 } 693 else if(node.getUserObject() instanceof HyperSearchFileNode) 694 { 695 setFont(boldFont); 697 int count = node.getChildCount(); 698 HyperSearchFileNode hyperSearchFileNode = (HyperSearchFileNode) node.getUserObject(); 699 if(count == 1) 700 { 701 if (hyperSearchFileNode.getCount() == 1) 702 { 703 setText(jEdit.getProperty("hypersearch-results" 704 + ".file-caption1",new Object [] { 705 hyperSearchFileNode 706 })); 707 } 708 else 709 { 710 setText(jEdit.getProperty("hypersearch-results" 711 + ".file-caption2",new Object [] { 712 hyperSearchFileNode, 713 Integer.valueOf(hyperSearchFileNode.getCount()) 714 })); 715 } 716 } 717 else 718 { 719 setText(jEdit.getProperty("hypersearch-results" 720 + ".file-caption",new Object [] { 721 hyperSearchFileNode, 722 Integer.valueOf(hyperSearchFileNode.getCount()), 723 Integer.valueOf(count) 724 })); 725 } 726 } 727 else 728 { 729 setFont(plainFont); 730 } 731 732 return this; 733 } 735 class CountNodes implements HyperSearchTreeNodeCallback 737 { 738 int bufferCount; 739 int resultCount; 740 public boolean processNode(DefaultMutableTreeNode node) 741 { 742 Object userObject = node.getUserObject(); 743 if (userObject instanceof HyperSearchFileNode) 744 { 745 resultCount += ((HyperSearchFileNode)userObject).getCount(); 746 bufferCount++; 747 } 748 return true; 749 } 750 } } 753 757 interface ResultVisitor 759 { 760 void visit(Buffer buffer, HyperSearchResult result); 761 } 763 static class BufferLoadedVisitor implements ResultVisitor 765 { 766 public void visit(Buffer buffer, HyperSearchResult result) 767 { 768 result.bufferOpened(buffer); 769 } 770 } 772 static class BufferClosedVisitor implements ResultVisitor 774 { 775 public void visit(Buffer buffer, HyperSearchResult result) 776 { 777 result.bufferClosed(); 778 } 779 } 781 static class TreeNodeCallbackAdapter implements HyperSearchTreeNodeCallback 783 { 784 public boolean processNode(DefaultMutableTreeNode node) { 785 return false; 786 } 787 788 } } 790 | Popular Tags |