/plugins/XSearch/tags/release-1-0-6/XSearch/xsearch/HyperSearchResults.java

# · Java · 973 lines · 772 code · 101 blank · 100 comment · 109 complexity · 442350d91d2120b644e8eeffbe4bf660 MD5 · raw file

  1. /*
  2. * HyperSearchResults.java - HyperSearch results
  3. * :tabSize=4:indentSize=4:noTabs=false:
  4. *
  5. * Copyright (C) 1998, 1999, 2000, 2001 Slava Pestov
  6. * Portions copyright (C) 2002 Peter Cox
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21. */
  22. package xsearch;
  23. //{{{ Imports
  24. import javax.swing.*;
  25. import javax.swing.event.*;
  26. import javax.swing.tree.*;
  27. import java.awt.*;
  28. import java.awt.event.*;
  29. import java.util.*;
  30. import java.text.SimpleDateFormat;
  31. import org.gjt.sp.jedit.io.VFSManager;
  32. import org.gjt.sp.jedit.gui.DefaultFocusComponent;
  33. import org.gjt.sp.jedit.gui.RolloverButton;
  34. import org.gjt.sp.jedit.msg.*;
  35. import org.gjt.sp.jedit.textarea.*;
  36. import org.gjt.sp.jedit.*;
  37. import org.gjt.sp.util.Log;
  38. //}}}
  39. /**
  40. * HyperSearch results window.
  41. * @author Slava Pestov, adapted by Rudi Widmann
  42. * @version $Id: HyperSearchResults.java 1482 2004-09-03 20:39:01Z ruwi $
  43. */
  44. public class HyperSearchResults extends JPanel implements EBComponent,
  45. DefaultFocusComponent
  46. {
  47. public static final String NAME = "xsearch-hypersearch-results";
  48. //{{{ HyperSearchResults constructor
  49. public HyperSearchResults(View view)
  50. {
  51. super(new BorderLayout());
  52. this.view = view;
  53. caption = new JLabel();
  54. Box toolBar = new Box(BoxLayout.X_AXIS);
  55. toolBar.add(caption);
  56. toolBar.add(Box.createGlue());
  57. ActionHandler ah = new ActionHandler();
  58. clear = new RolloverButton(GUIUtilities.loadIcon("Clear.png"));
  59. clear.setToolTipText(jEdit.getProperty(
  60. "hypersearch-results.clear.label"));
  61. clear.addActionListener(ah);
  62. toolBar.add(clear);
  63. multi = new RolloverButton();
  64. multi.setToolTipText(jEdit.getProperty(
  65. "hypersearch-results.multi.label"));
  66. multi.addActionListener(ah);
  67. toolBar.add(multi);
  68. add(BorderLayout.NORTH, toolBar);
  69. resultTreeRoot = new DefaultMutableTreeNode();
  70. resultTreeModel = new DefaultTreeModel(resultTreeRoot);
  71. resultTree = new JTree(resultTreeModel);
  72. resultTree.setCellRenderer(new ResultCellRenderer());
  73. resultTree.setVisibleRowCount(16);
  74. resultTree.setRootVisible(false);
  75. resultTree.setShowsRootHandles(true);
  76. // looks bad with the OS X L&F, apparently...
  77. if(!OperatingSystem.isMacOSLF())
  78. resultTree.putClientProperty("JTree.lineStyle", "Angled");
  79. resultTree.setEditable(false);
  80. resultTree.addKeyListener(new KeyHandler());
  81. resultTree.addMouseListener(new MouseHandler());
  82. JScrollPane scrollPane = new JScrollPane(resultTree);
  83. Dimension dim = scrollPane.getPreferredSize();
  84. dim.width = 400;
  85. scrollPane.setPreferredSize(dim);
  86. add(BorderLayout.CENTER, scrollPane);
  87. } //}}}
  88. //{{{ focusOnDefaultComponent() method
  89. public void focusOnDefaultComponent()
  90. {
  91. resultTree.requestFocus();
  92. } //}}}
  93. //{{{ addNotify() method
  94. public void addNotify()
  95. {
  96. super.addNotify();
  97. EditBus.addToBus(this);
  98. multiStatus = jEdit.getBooleanProperty(
  99. "hypersearch-results.multi");
  100. updateMultiStatus();
  101. } //}}}
  102. //{{{ removeNotify() method
  103. public void removeNotify()
  104. {
  105. super.removeNotify();
  106. EditBus.removeFromBus(this);
  107. jEdit.setBooleanProperty("hypersearch-results.multi",multiStatus);
  108. } //}}}
  109. //{{{ handleMessage() method
  110. public void handleMessage(EBMessage msg)
  111. {
  112. if(msg instanceof BufferUpdate)
  113. {
  114. BufferUpdate bmsg = (BufferUpdate)msg;
  115. Buffer buffer = bmsg.getBuffer();
  116. Object what = bmsg.getWhat();
  117. if(what == BufferUpdate.LOADED ||
  118. what == BufferUpdate.CLOSED)
  119. {
  120. ResultVisitor visitor = null;
  121. if (what == BufferUpdate.LOADED)
  122. {
  123. visitor = new BufferLoadedVisitor();
  124. }
  125. else // BufferUpdate.CLOSED
  126. {
  127. visitor = new BufferClosedVisitor();
  128. }
  129. // impl note: since multiple searches now allowed,
  130. // extra level in hierarchy
  131. for(int i = resultTreeRoot.getChildCount() - 1; i >= 0; i--)
  132. {
  133. DefaultMutableTreeNode searchNode = (DefaultMutableTreeNode)
  134. resultTreeRoot.getChildAt(i);
  135. for(int j = searchNode.getChildCount() - 1;
  136. j >= 0; j--)
  137. {
  138. DefaultMutableTreeNode bufferNode = (DefaultMutableTreeNode)
  139. searchNode.getChildAt(j);
  140. for(int k = bufferNode.getChildCount() - 1;
  141. k >= 0; k--)
  142. {
  143. Object userObject =
  144. ((DefaultMutableTreeNode)bufferNode
  145. .getChildAt(k)).getUserObject();
  146. HyperSearchResult result = (HyperSearchResult)
  147. userObject;
  148. if(buffer.getPath().equals(result.path))
  149. visitor.visit(buffer,result);
  150. }
  151. }
  152. }
  153. }
  154. }
  155. } //}}}
  156. //{{{ getTreeModel() method
  157. public DefaultTreeModel getTreeModel()
  158. {
  159. return resultTreeModel;
  160. } //}}}
  161. //{{{ getTree() method
  162. /**
  163. * Returns the result tree.
  164. * @since jEdit 4.1pre9
  165. */
  166. public JTree getTree()
  167. {
  168. return resultTree;
  169. } //}}}
  170. //{{{ searchStarted() method
  171. public void searchStarted()
  172. {
  173. caption.setText(jEdit.getProperty("hypersearch-results.searching"));
  174. } //}}}
  175. //{{{ searchFailed() method
  176. public void searchFailed()
  177. {
  178. caption.setText(jEdit.getProperty("hypersearch-results.no-results"));
  179. // collapse all nodes, as suggested on user mailing list...
  180. for(int i = 0; i < resultTreeRoot.getChildCount(); i++)
  181. {
  182. DefaultMutableTreeNode node = (DefaultMutableTreeNode)
  183. resultTreeRoot.getChildAt(i);
  184. resultTree.collapsePath(new TreePath(new Object[] {
  185. resultTreeRoot, node }));
  186. }
  187. } //}}}
  188. //{{{ searchDone() method
  189. public void searchDone(final DefaultMutableTreeNode searchNode)
  190. {
  191. final int nodeCount = searchNode.getChildCount();
  192. if (nodeCount < 1)
  193. {
  194. searchFailed();
  195. return;
  196. }
  197. caption.setText(jEdit.getProperty("hypersearch-results.done"));
  198. SwingUtilities.invokeLater(new Runnable()
  199. {
  200. public void run()
  201. {
  202. if(!multiStatus)
  203. {
  204. for(int i = 0; i < resultTreeRoot.getChildCount(); i++)
  205. {
  206. resultTreeRoot.remove(0);
  207. }
  208. }
  209. resultTreeRoot.add(searchNode);
  210. resultTreeModel.reload(resultTreeRoot);
  211. TreePath lastNode = null;
  212. for(int i = 0; i < nodeCount; i++)
  213. {
  214. lastNode = new TreePath(
  215. ((DefaultMutableTreeNode)
  216. searchNode.getChildAt(i))
  217. .getPath());
  218. resultTree.expandPath(lastNode);
  219. }
  220. resultTree.scrollPathToVisible(
  221. new TreePath(new Object[] {
  222. resultTreeRoot,searchNode }));
  223. }
  224. });
  225. } //}}}
  226. //{{{ Private members
  227. private View view;
  228. private JLabel caption;
  229. private JTree resultTree;
  230. private DefaultMutableTreeNode resultTreeRoot;
  231. private DefaultTreeModel resultTreeModel;
  232. private RolloverButton clear;
  233. private RolloverButton multi;
  234. private boolean multiStatus;
  235. //{{{ updateMultiStatus() method
  236. private void updateMultiStatus()
  237. {
  238. if(multiStatus)
  239. multi.setIcon(GUIUtilities.loadIcon("MultipleResults.png"));
  240. else
  241. multi.setIcon(GUIUtilities.loadIcon("SingleResult.png"));
  242. } //}}}
  243. //{{{ goToSelectedNode() method
  244. private void goToSelectedNode()
  245. {
  246. TreePath path = resultTree.getSelectionPath();
  247. if(path == null)
  248. return;
  249. DefaultMutableTreeNode node = (DefaultMutableTreeNode)path
  250. .getLastPathComponent();
  251. Object value = node.getUserObject();
  252. if(node.getParent() == resultTreeRoot)
  253. {
  254. // do nothing if clicked "foo (showing n occurrences in m files)"
  255. }
  256. else if(value instanceof String)
  257. {
  258. Buffer buffer = jEdit.openFile(view,(String)value);
  259. if(buffer == null)
  260. return;
  261. view.goToBuffer(buffer);
  262. // fuck me dead
  263. SwingUtilities.invokeLater(new Runnable()
  264. {
  265. public void run()
  266. {
  267. resultTree.requestFocus();
  268. }
  269. });
  270. }
  271. else if (value instanceof HyperSearchResult)
  272. {
  273. ((HyperSearchResult)value).goTo(view);
  274. }
  275. } //}}}
  276. //{{{ toggleAllNodes() method
  277. private void toggleAllNodes(boolean expand)
  278. {
  279. int nodeCount = resultTreeRoot.getChildCount();
  280. if (nodeCount > 0) {
  281. DefaultMutableTreeNode childNode = (DefaultMutableTreeNode)resultTreeRoot.getFirstChild();
  282. for(int i = 0; i < nodeCount; i++)
  283. {
  284. TreePath childPath = new TreePath(childNode.getPath());
  285. if (expand)
  286. expandPath(99, childPath);
  287. else
  288. expandPath(0, childPath);
  289. childNode = childNode.getNextSibling();
  290. }
  291. }
  292. }
  293. //{{{ expandSelectedNode() method
  294. private void expandSelectedNode(int level)
  295. {
  296. expandPath(level, resultTree.getSelectionPath());
  297. }
  298. //{{{ expandSelectedNode() method
  299. private void expandPath(int level, TreePath path)
  300. {
  301. if(path == null)
  302. return;
  303. if (level > 0)
  304. resultTree.expandPath(path);
  305. else
  306. resultTree.collapsePath(path);
  307. DefaultMutableTreeNode expandNode = (DefaultMutableTreeNode)path
  308. .getLastPathComponent();
  309. int expandNodeChildCount = expandNode.getChildCount();
  310. if(expandNodeChildCount != 0) {
  311. DefaultMutableTreeNode childNode = (DefaultMutableTreeNode)expandNode.getFirstChild();
  312. for(int j = 0; j < expandNodeChildCount; j++)
  313. {
  314. TreePath childPath = new TreePath(childNode.getPath());
  315. if (level > 1)
  316. resultTree.expandPath(childPath);
  317. else if (level > 0)
  318. resultTree.collapsePath(childPath);
  319. int nextChildCount = childNode.getChildCount();
  320. if(nextChildCount != 0) {
  321. DefaultMutableTreeNode lineNode = (DefaultMutableTreeNode)childNode.getFirstChild();
  322. for(int k = 0; k < nextChildCount; k++)
  323. {
  324. TreePath linePath = new TreePath(lineNode.getPath());
  325. if (level > 2)
  326. resultTree.expandPath(linePath);
  327. else if (level > 1)
  328. resultTree.collapsePath(linePath);
  329. lineNode = lineNode.getNextSibling();
  330. }
  331. }
  332. childNode = childNode.getNextSibling();
  333. }
  334. }
  335. }
  336. //}}}
  337. private void writeNodeToBuffer(TreePath path)
  338. {
  339. DefaultMutableTreeNode startNode;
  340. int level;
  341. if (path == null)
  342. {
  343. // root
  344. startNode = resultTreeRoot;
  345. }
  346. else
  347. {
  348. startNode = (DefaultMutableTreeNode)path.getLastPathComponent();
  349. }
  350. new ResultWriter(startNode).write();
  351. }
  352. //{{{ ActionHandler class
  353. public class ActionHandler implements ActionListener
  354. {
  355. public void actionPerformed(ActionEvent evt)
  356. {
  357. Object source = evt.getSource();
  358. if(source == clear)
  359. {
  360. resultTreeRoot.removeAllChildren();
  361. resultTreeModel.reload(resultTreeRoot);
  362. }
  363. else if(source == multi)
  364. {
  365. multiStatus = !multiStatus;
  366. updateMultiStatus();
  367. if(!multiStatus)
  368. {
  369. for(int i = resultTreeRoot.getChildCount() - 2; i >= 0; i--)
  370. {
  371. resultTreeModel.removeNodeFromParent(
  372. (MutableTreeNode)resultTreeRoot
  373. .getChildAt(i));
  374. }
  375. }
  376. }
  377. }
  378. } //}}}
  379. //{{{ KeyHandler class
  380. class KeyHandler extends KeyAdapter
  381. {
  382. public void keyPressed(KeyEvent evt)
  383. {
  384. if(evt.getKeyCode() == KeyEvent.VK_ENTER)
  385. {
  386. goToSelectedNode();
  387. // fuck me dead
  388. SwingUtilities.invokeLater(new Runnable()
  389. {
  390. public void run()
  391. {
  392. resultTree.requestFocus();
  393. }
  394. });
  395. evt.consume();
  396. }
  397. }
  398. } //}}}
  399. //{{{ MouseHandler class
  400. class MouseHandler extends MouseAdapter
  401. {
  402. //{{{ mousePressed() method
  403. public void mousePressed(MouseEvent evt)
  404. {
  405. if(evt.isConsumed())
  406. return;
  407. TreePath path1 = resultTree.getPathForLocation(
  408. evt.getX(),evt.getY());
  409. if(path1 == null)
  410. return;
  411. resultTree.setSelectionPath(path1);
  412. if (GUIUtilities.isPopupTrigger(evt))
  413. showPopupMenu(evt);
  414. else
  415. {
  416. goToSelectedNode();
  417. view.toFront();
  418. view.requestFocus();
  419. view.getTextArea().requestFocus();
  420. }
  421. } //}}}
  422. //{{{ Private members
  423. private JPopupMenu popupMenu;
  424. //{{{ showPopupMenu method
  425. private void showPopupMenu(MouseEvent evt)
  426. {
  427. if (popupMenu == null)
  428. {
  429. popupMenu = new JPopupMenu();
  430. popupMenu.add(new ExpandTreeNodeAllAction());
  431. popupMenu.add(new ExpandTreeNode0Action());
  432. popupMenu.add(new ExpandTreeNode1Action());
  433. popupMenu.add(new ExpandTreeNode2Action());
  434. popupMenu.add(new ExpandAllNodesAction());
  435. popupMenu.add(new CollapseAllNodesAction());
  436. popupMenu.add(new RemoveTreeNodeAction());
  437. popupMenu.add(new WriteNodeToBufferAction());
  438. popupMenu.add(new WriteAllNodesToBufferAction());
  439. }
  440. GUIUtilities.showPopupMenu(popupMenu,evt.getComponent(),
  441. evt.getX(),evt.getY());
  442. evt.consume();
  443. } //}}}
  444. //}}}
  445. } //}}}
  446. //{{{ RemoveTreeNodeAction class
  447. class RemoveTreeNodeAction extends AbstractAction
  448. {
  449. public RemoveTreeNodeAction()
  450. {
  451. super(jEdit.getProperty("hypersearch-results.remove-node"));
  452. }
  453. public void actionPerformed(ActionEvent evt)
  454. {
  455. TreePath path = resultTree.getSelectionPath();
  456. if(path == null)
  457. return;
  458. MutableTreeNode value = (MutableTreeNode)path
  459. .getLastPathComponent();
  460. resultTreeModel.removeNodeFromParent(value);
  461. }
  462. }//}}}
  463. //{{{ ExpandTreeNodeAllAction class
  464. class ExpandTreeNodeAllAction extends AbstractAction
  465. {
  466. public ExpandTreeNodeAllAction()
  467. {
  468. super(jEdit.getProperty("xsearch-hypersearch-results.expand-node"));
  469. }
  470. public void actionPerformed(ActionEvent evt)
  471. {
  472. expandSelectedNode(99);
  473. }
  474. }//}}}
  475. //{{{ ExpandTreeNode0Action class (collapse Node)
  476. class ExpandTreeNode0Action extends AbstractAction
  477. {
  478. public ExpandTreeNode0Action()
  479. {
  480. super(jEdit.getProperty("xsearch-hypersearch-results.expand-node-0-level"));
  481. }
  482. public void actionPerformed(ActionEvent evt)
  483. {
  484. expandSelectedNode(0);
  485. }
  486. }//}}}
  487. //{{{ ExpandTreeNode1Action class
  488. class ExpandTreeNode1Action extends AbstractAction
  489. {
  490. public ExpandTreeNode1Action()
  491. {
  492. super(jEdit.getProperty("xsearch-hypersearch-results.expand-node-1-level"));
  493. }
  494. public void actionPerformed(ActionEvent evt)
  495. {
  496. expandSelectedNode(1);
  497. }
  498. }//}}}
  499. //{{{ ExpandTreeNode2Action class
  500. class ExpandTreeNode2Action extends AbstractAction
  501. {
  502. public ExpandTreeNode2Action()
  503. {
  504. super(jEdit.getProperty("xsearch-hypersearch-results.expand-node-2-level"));
  505. }
  506. public void actionPerformed(ActionEvent evt)
  507. {
  508. expandSelectedNode(2);
  509. }
  510. }//}}}
  511. //{{{ ExpandAllNodesAction class
  512. class ExpandAllNodesAction extends AbstractAction
  513. {
  514. public ExpandAllNodesAction()
  515. {
  516. super(jEdit.getProperty("xsearch-hypersearch-results.expand-all-nodes"));
  517. }
  518. public void actionPerformed(ActionEvent evt)
  519. {
  520. toggleAllNodes(true);
  521. }
  522. }//}}}
  523. //{{{ CollapseAllNodesAction class
  524. class CollapseAllNodesAction extends AbstractAction
  525. {
  526. public CollapseAllNodesAction()
  527. {
  528. super(jEdit.getProperty("xsearch-hypersearch-results.collapse-all-nodes"));
  529. }
  530. public void actionPerformed(ActionEvent evt)
  531. {
  532. toggleAllNodes(false);
  533. }
  534. }//}}}
  535. //{{{ RemoveAllTreeNodesAction class
  536. class RemoveAllTreeNodesAction extends AbstractAction
  537. {
  538. public RemoveAllTreeNodesAction()
  539. {
  540. super(jEdit.getProperty("hypersearch-results.remove-all-nodes"));
  541. }
  542. public void actionPerformed(ActionEvent evt)
  543. {
  544. resultTreeRoot = new DefaultMutableTreeNode();
  545. resultTreeModel = new DefaultTreeModel(resultTreeRoot);
  546. resultTree.setModel(resultTreeModel);
  547. }
  548. }//}}}
  549. //{{{ WriteNodeToBufferAction class
  550. class WriteNodeToBufferAction extends AbstractAction
  551. {
  552. public WriteNodeToBufferAction()
  553. {
  554. super(jEdit.getProperty("xsearch-hypersearch-results.write-node-to-buffer"));
  555. }
  556. public void actionPerformed(ActionEvent evt)
  557. {
  558. writeNodeToBuffer(resultTree.getSelectionPath());
  559. }
  560. }//}}}
  561. class WriteAllNodesToBufferAction extends AbstractAction
  562. {
  563. public WriteAllNodesToBufferAction()
  564. {
  565. super(jEdit.getProperty("xsearch-hypersearch-results.write-all-nodes-to-buffer"));
  566. }
  567. public void actionPerformed(ActionEvent evt)
  568. {
  569. writeNodeToBuffer(null);
  570. }
  571. }//}}}
  572. class ResultWriter
  573. {
  574. public ResultWriter(DefaultMutableTreeNode root) {
  575. this.root = root;
  576. this.level = root.getLevel();
  577. nodeCascade[level] = root;
  578. // fill nodeCascade with parents
  579. for (int i=level;i>0;i--) {
  580. nodeCascade[i-1] = (DefaultMutableTreeNode)nodeCascade[i].getParent();
  581. }
  582. Log.log(Log.DEBUG, BeanShell.class,"+++ HyperSearchResults.662: level = "+level);
  583. textArea = jEdit.getActiveView().getTextArea();
  584. }
  585. public void write()
  586. {
  587. /*******************************************************************
  588. * Hyper search result tree structure
  589. * root
  590. * + searchNode
  591. * + fileNode
  592. * + results
  593. * + fileNode
  594. * + results
  595. * + searchNode
  596. * + fileNode
  597. * + results
  598. * (+ result range)
  599. *******************************************************************/
  600. jEdit.newFile(view);
  601. writeHeader();
  602. int rootChildCount = (level < 1) ? root.getChildCount() : 1;
  603. if(rootChildCount == 0)
  604. {
  605. textArea.setSelectedText(
  606. "Search items not found\n\nEnd of report\n");
  607. }
  608. else
  609. {
  610. DefaultMutableTreeNode searchNode;
  611. if (level < 1)
  612. searchNode = (DefaultMutableTreeNode)root.getFirstChild();
  613. else
  614. searchNode = nodeCascade[1];
  615. for(int i = 0; i < rootChildCount; ++i)
  616. {
  617. fileCount = 0;
  618. hitCount = 0;
  619. writeSearchHeader(searchNode);
  620. if (i == rootChildCount-1)
  621. writeSearchParameters(); // write only for last result
  622. searchCount++;
  623. int searchChildCount = (level < 2) ? searchNode.getChildCount() : 1;
  624. if(searchChildCount == 0)
  625. {
  626. textArea.setSelectedText(
  627. "Search term not found\n\nEnd of report\n");
  628. }
  629. DefaultMutableTreeNode fileNode;
  630. if (level < 2)
  631. fileNode = (DefaultMutableTreeNode)searchNode.getFirstChild();
  632. else
  633. fileNode = nodeCascade[2];
  634. for(int j = 0; j < searchChildCount; ++j)
  635. {
  636. writeResultsForFile(fileNode);
  637. fileNode = fileNode.getNextSibling();
  638. }
  639. searchNode = searchNode.getNextSibling();
  640. writeFileFooter();
  641. }
  642. writeFooter();
  643. }
  644. }
  645. private void writeSearchHeader(DefaultMutableTreeNode node)
  646. {
  647. //node = (DefaultMutableTreeNode)node;
  648. if(node == null) return;
  649. int childCount = node.getChildCount();
  650. if( childCount == 0) return;
  651. sb.setLength(0);
  652. String searchHeader = "Results for search item: \""+node.getUserObject().toString()+"\"\n";
  653. StringBuffer underline = new StringBuffer();
  654. for (int i=1;i<searchHeader.length();i++) {
  655. underline.append("=");
  656. }
  657. sb.append("\t"+searchHeader + "\t"+underline.toString());
  658. sb.append("\n");
  659. textArea.setSelectedText(sb.toString());
  660. }
  661. private void writeResultsForFile(DefaultMutableTreeNode node)
  662. {
  663. //node = (DefaultMutableTreeNode)node;
  664. if(node == null) return;
  665. int childCount = node.getChildCount();
  666. if( childCount == 0) return;
  667. ++fileCount;
  668. hitCount += childCount;
  669. sb.setLength(0);
  670. sb.append("\tMatched file: \t");
  671. sb.append(node.getUserObject().toString());
  672. sb.append("\n");
  673. DefaultMutableTreeNode lineNode = (DefaultMutableTreeNode)node.getFirstChild();
  674. if(lineNode == null) return;
  675. for( int i = 0; i < childCount; ++i)
  676. {
  677. if(lineNode == null)
  678. {
  679. sb.append("\t\tNull node for i = " + String.valueOf(i));
  680. }
  681. else
  682. {
  683. sb.append("\t\tline ");
  684. sb.append(lineNode.getUserObject().toString());
  685. // check if line node has a line range
  686. int lineRangeCount = lineNode.getChildCount();
  687. if (lineRangeCount > 0)
  688. {
  689. DefaultMutableTreeNode lineRangeNode = (DefaultMutableTreeNode)lineNode.getFirstChild();
  690. sb.append("\n\t\t\tline range:");
  691. for (int lr = 0; lr < lineRangeCount; lr++)
  692. {
  693. sb.append("\n\t\t\t\t");
  694. sb.append(lineRangeNode.getUserObject().toString());
  695. lineRangeNode = lineRangeNode.getNextSibling();
  696. }
  697. }
  698. }
  699. sb.append('\n');
  700. lineNode = lineNode.getNextSibling();
  701. }
  702. sb.append("\n\tNumber of occurrences: ");
  703. sb.append(String.valueOf(childCount));
  704. sb.append("\n");
  705. textArea.setSelectedText(sb.toString());
  706. }
  707. void writeHeader()
  708. {
  709. sb.append("Hypersearch report written on ");
  710. SimpleDateFormat f = new SimpleDateFormat("EE MMM d, yyyy h:mm a z");
  711. sb.append(f.format( new Date()));
  712. sb.append("\n\n");
  713. textArea.setSelectedText(sb.toString());
  714. }
  715. void writeSearchParameters()
  716. {
  717. sb.setLength(0);
  718. sb.append("\tUsed search parameters for ");
  719. if(XSearchAndReplace.getRegexp())
  720. sb.append("regular expression: ");
  721. else
  722. sb.append("search term: ");
  723. sb.append(XSearchAndReplace.getSearchString());
  724. sb.append(" (case ");
  725. if(XSearchAndReplace.getIgnoreCase())
  726. sb.append("in");
  727. sb.append("sensitive)\n");
  728. sb.append("\tSearch file set type ");
  729. sb.append(writeSearchFileSetType());
  730. sb.append('\n');
  731. textArea.setSelectedText(sb.toString());
  732. }
  733. void writeFileFooter()
  734. {
  735. sb.setLength(0);
  736. sb.append("\tTotal of ");
  737. sb.append(String.valueOf(hitCount));
  738. sb.append(" occurrences found in ");
  739. sb.append(String.valueOf(fileCount));
  740. sb.append(" files\n\n");
  741. textArea.setSelectedText(sb.toString());
  742. }
  743. void writeFooter()
  744. {
  745. sb.setLength(0);
  746. sb.append("Total of ");
  747. sb.append(String.valueOf(searchCount));
  748. sb.append(" search results reported \n\nEnd of report\n");
  749. textArea.setSelectedText(sb.toString());
  750. }
  751. String writeSearchFileSetType()
  752. {
  753. StringBuffer result = new StringBuffer();
  754. org.gjt.sp.jedit.search.SearchFileSet fileSet = XSearchAndReplace.getSearchFileSet();
  755. if(fileSet instanceof org.gjt.sp.jedit.search.CurrentBufferSet)
  756. result.append("current buffer");
  757. else if(fileSet instanceof org.gjt.sp.jedit.search.AllBufferSet)
  758. result.append("all open buffers with file mask '")
  759. .append(((org.gjt.sp.jedit.search.AllBufferSet)fileSet).getFileFilter())
  760. .append('\'');
  761. else if(fileSet instanceof org.gjt.sp.jedit.search.DirectoryListSet)
  762. {
  763. fileSet = (org.gjt.sp.jedit.search.DirectoryListSet)fileSet;
  764. result.append("all files in \n")
  765. .append(((org.gjt.sp.jedit.search.DirectoryListSet)fileSet).getDirectory())
  766. .append('\n');
  767. if(((org.gjt.sp.jedit.search.DirectoryListSet)fileSet).isRecursive())
  768. result.append("(and subdirectories) ");
  769. result.append("with file mask '")
  770. .append(((org.gjt.sp.jedit.search.DirectoryListSet)fileSet).getFileFilter())
  771. .append('\'');
  772. }
  773. else
  774. result.append("unknown file set");
  775. return result.toString();
  776. }
  777. private JEditTextArea textArea;
  778. private DefaultMutableTreeNode root;
  779. private DefaultMutableTreeNode[] nodeCascade = new DefaultMutableTreeNode[5];
  780. private int level;
  781. private StringBuffer sb = new StringBuffer();
  782. private int searchCount = 0;
  783. private int fileCount = 0;
  784. private int hitCount = 0;
  785. }
  786. //{{{ ResultCellRenderer class
  787. class ResultCellRenderer extends DefaultTreeCellRenderer
  788. {
  789. Font plainFont, boldFont;
  790. //{{{ ResultCellRenderer constructor
  791. ResultCellRenderer()
  792. {
  793. plainFont = UIManager.getFont("Tree.font");
  794. if(plainFont == null)
  795. plainFont = jEdit.getFontProperty("metal.secondary.font");
  796. boldFont = new Font(plainFont.getName(),Font.BOLD,
  797. plainFont.getSize());
  798. } //}}}
  799. //{{{ getTreeCellRendererComponent() method
  800. public Component getTreeCellRendererComponent(JTree tree,
  801. Object value, boolean sel, boolean expanded,
  802. boolean leaf, int row, boolean hasFocus)
  803. {
  804. Component comp = super.getTreeCellRendererComponent(tree,value,sel,
  805. expanded,leaf,row,hasFocus);
  806. setIcon(null);
  807. DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
  808. if (node.getParent() == resultTreeRoot)
  809. {
  810. ResultCellRenderer.this.setFont(boldFont);
  811. int bufferCount = node.getChildCount();
  812. int resultCount = 0;
  813. for (int i = 0; i < bufferCount; i++)
  814. {
  815. resultCount += node.getChildAt(i).getChildCount();
  816. }
  817. Object[] pp = { node.toString(), new Integer(resultCount), new Integer(bufferCount) };
  818. setText(jEdit.getProperty("hypersearch-results.result-caption",pp));
  819. }
  820. else if(node.getUserObject() instanceof String)
  821. {
  822. // file name
  823. ResultCellRenderer.this.setFont(boldFont);
  824. int count = node.getChildCount();
  825. if(count == 1)
  826. {
  827. setText(jEdit.getProperty("hypersearch-results"
  828. + ".file-caption1",new Object[] {
  829. node.getUserObject()
  830. }));
  831. }
  832. else
  833. {
  834. setText(jEdit.getProperty("hypersearch-results"
  835. + ".file-caption",new Object[] {
  836. node.getUserObject(),
  837. new Integer(count)
  838. }));
  839. }
  840. }
  841. else
  842. {
  843. ResultCellRenderer.this.setFont(plainFont);
  844. }
  845. return this;
  846. } //}}}
  847. } //}}}
  848. // these are used to eliminate code duplication. i don't normally use
  849. // the visitor or "template method" pattern, but this code was contributed
  850. // by Peter Cox and i don't feel like changing it around too much.
  851. //{{{ ResultVisitor interface
  852. interface ResultVisitor
  853. {
  854. public void visit(Buffer buffer, HyperSearchResult result);
  855. } //}}}
  856. //{{{ BufferLoadedVisitor class
  857. class BufferLoadedVisitor implements ResultVisitor
  858. {
  859. public void visit(Buffer buffer, HyperSearchResult result)
  860. {
  861. result.bufferOpened(buffer);
  862. }
  863. } //}}}
  864. //{{{ BufferClosedVisitor class
  865. class BufferClosedVisitor implements ResultVisitor
  866. {
  867. public void visit(Buffer buffer, HyperSearchResult result)
  868. {
  869. result.bufferClosed();
  870. }
  871. } //}}}
  872. }