001: /*
002: * HyperSearchResults.java - HyperSearch results
003: * :tabSize=8:indentSize=8:noTabs=false:
004: * :folding=explicit:collapseFolds=1:
005: *
006: * Copyright (C) 1998, 1999, 2000, 2001 Slava Pestov
007: * Portions copyright (C) 2002 Peter Cox
008: *
009: * This program is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU General Public License
011: * as published by the Free Software Foundation; either version 2
012: * of the License, or any later version.
013: *
014: * This program is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
017: * GNU General Public License for more details.
018: *
019: * You should have received a copy of the GNU General Public License
020: * along with this program; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
022: */
023:
024: package org.gjt.sp.jedit.search;
025:
026: //{{{ Imports
027: import javax.swing.*;
028: import javax.swing.tree.*;
029:
030: import java.awt.*;
031: import java.awt.event.*;
032: import java.util.*;
033: import org.gjt.sp.jedit.gui.DefaultFocusComponent;
034: import org.gjt.sp.jedit.gui.RolloverButton;
035: import org.gjt.sp.jedit.msg.*;
036: import org.gjt.sp.jedit.*;
037:
038: //}}}
039:
040: /**
041: * HyperSearch results window.
042: * @author Slava Pestov
043: * @version $Id: HyperSearchResults.java 10823 2007-10-06 10:52:17Z k_satoda $
044: */
045: public class HyperSearchResults extends JPanel implements EBComponent,
046: DefaultFocusComponent {
047: public static final String NAME = "hypersearch-results";
048:
049: //{{{ HyperSearchResults constructor
050: public HyperSearchResults(View view) {
051: super (new BorderLayout());
052:
053: this .view = view;
054:
055: caption = new JLabel();
056:
057: Box toolBar = new Box(BoxLayout.X_AXIS);
058: toolBar.add(caption);
059: toolBar.add(Box.createGlue());
060:
061: ActionHandler ah = new ActionHandler();
062:
063: clear = new RolloverButton(GUIUtilities.loadIcon("Clear.png"));
064: clear.setToolTipText(jEdit
065: .getProperty("hypersearch-results.clear.label"));
066: clear.addActionListener(ah);
067: toolBar.add(clear);
068:
069: multi = new RolloverButton();
070: multi.setToolTipText(jEdit
071: .getProperty("hypersearch-results.multi.label"));
072: multi.addActionListener(ah);
073: toolBar.add(multi);
074:
075: add(BorderLayout.NORTH, toolBar);
076:
077: resultTreeRoot = new DefaultMutableTreeNode();
078: resultTreeModel = new DefaultTreeModel(resultTreeRoot);
079: resultTree = new JTree(resultTreeModel);
080: resultTree.setToolTipText("");
081: resultTree.setCellRenderer(new ResultCellRenderer());
082: resultTree.setVisibleRowCount(16);
083: resultTree.setRootVisible(false);
084: resultTree.setShowsRootHandles(true);
085:
086: // looks bad with the OS X L&F, apparently...
087: if (!OperatingSystem.isMacOSLF())
088: resultTree.putClientProperty("JTree.lineStyle", "Angled");
089:
090: resultTree.setEditable(false);
091:
092: resultTree.addKeyListener(new KeyHandler());
093: resultTree.addMouseListener(new MouseHandler());
094:
095: JScrollPane scrollPane = new JScrollPane(resultTree);
096: Dimension dim = scrollPane.getPreferredSize();
097: dim.width = 400;
098: scrollPane.setPreferredSize(dim);
099: add(BorderLayout.CENTER, scrollPane);
100: } //}}}
101:
102: //{{{ focusOnDefaultComponent() method
103: public void focusOnDefaultComponent() {
104: resultTree.requestFocus();
105: } //}}}
106:
107: //{{{ addNotify() method
108: public void addNotify() {
109: super .addNotify();
110: EditBus.addToBus(this );
111: multiStatus = jEdit
112: .getBooleanProperty("hypersearch-results.multi");
113: updateMultiStatus();
114: } //}}}
115:
116: //{{{ removeNotify() method
117: public void removeNotify() {
118: super .removeNotify();
119: EditBus.removeFromBus(this );
120: jEdit.setBooleanProperty("hypersearch-results.multi",
121: multiStatus);
122: } //}}}
123:
124: //{{{ visitBuffers() method
125: private void visitBuffers(final ResultVisitor visitor,
126: final Buffer buffer) {
127: // impl note: since multi-level hierarchies now allowed,
128: // use traverseNodes to process HyperSearchResult nodes
129: traverseNodes(resultTreeRoot, new TreeNodeCallbackAdapter() {
130: public boolean processNode(DefaultMutableTreeNode node) {
131: Object userObject = node.getUserObject();
132: if (!(userObject instanceof HyperSearchResult))
133: return true;
134: HyperSearchResult result = (HyperSearchResult) userObject;
135: if (result.pathEquals(buffer.getSymlinkPath()))
136: visitor.visit(buffer, result);
137: return true;
138: }
139: });
140: } //}}}
141:
142: //{{{ handleMessage() method
143: public void handleMessage(EBMessage msg) {
144: if (msg instanceof BufferUpdate) {
145: BufferUpdate bmsg = (BufferUpdate) msg;
146: Buffer buffer = bmsg.getBuffer();
147: Object what = bmsg.getWhat();
148: if (what == BufferUpdate.LOADED)
149: visitBuffers(new BufferLoadedVisitor(), buffer);
150: else if (what == BufferUpdate.CLOSED)
151: visitBuffers(new BufferClosedVisitor(), buffer);
152: }
153: } //}}}
154:
155: //{{{ traverseNodes() method
156: public static boolean traverseNodes(DefaultMutableTreeNode node,
157: HyperSearchTreeNodeCallback callbackInterface) {
158: if (!callbackInterface.processNode(node))
159: return false;
160: for (Enumeration e = node.children(); e.hasMoreElements();) {
161: DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) e
162: .nextElement();
163: if (!traverseNodes(childNode, callbackInterface))
164: return false;
165: }
166: return true;
167: } //}}}
168:
169: //{{{ getTreeModel() method
170: public DefaultTreeModel getTreeModel() {
171: return resultTreeModel;
172: } //}}}
173:
174: //{{{ getTree() method
175: /**
176: * Returns the result tree.
177: *
178: * @return the result tree
179: * @since jEdit 4.1pre9
180: */
181: public JTree getTree() {
182: return resultTree;
183: } //}}}
184:
185: //{{{ searchStarted() method
186: public void searchStarted() {
187: caption.setText(jEdit
188: .getProperty("hypersearch-results.searching"));
189: } //}}}
190:
191: //{{{ setSearchStatus() method
192: public void setSearchStatus(String status) {
193: caption.setText(status);
194: } //}}}
195:
196: //{{{ searchFailed() method
197: public void searchFailed() {
198: caption.setText(jEdit
199: .getProperty("hypersearch-results.no-results"));
200:
201: // collapse all nodes, as suggested on user mailing list...
202: for (int i = 0; i < resultTreeRoot.getChildCount(); i++) {
203: DefaultMutableTreeNode node = (DefaultMutableTreeNode) resultTreeRoot
204: .getChildAt(i);
205: resultTree.collapsePath(new TreePath(new Object[] {
206: resultTreeRoot, node }));
207: }
208: } //}}}
209:
210: //{{{ searchDone() method
211: /**
212: * @param searchNode the result node
213: * @param selectNode the node that must be selected, or null
214: * @since jEdit 4.3pre12
215: */
216: public void searchDone(final DefaultMutableTreeNode searchNode,
217: final DefaultMutableTreeNode selectNode) {
218: final int nodeCount = searchNode.getChildCount();
219: if (nodeCount < 1) {
220: searchFailed();
221: return;
222: }
223:
224: caption.setText(jEdit.getProperty("hypersearch-results.done"));
225:
226: SwingUtilities.invokeLater(new Runnable() {
227: public void run() {
228: if (!multiStatus) {
229: for (int i = 0; i < resultTreeRoot.getChildCount(); i++) {
230: resultTreeRoot.remove(0);
231: }
232: }
233:
234: resultTreeRoot.add(searchNode);
235: resultTreeModel.reload(resultTreeRoot);
236:
237: for (int i = 0; i < nodeCount; i++) {
238: TreePath lastNode = new TreePath(
239: ((DefaultMutableTreeNode) searchNode
240: .getChildAt(i)).getPath());
241:
242: resultTree.expandPath(lastNode);
243: }
244: TreePath treePath;
245: if (selectNode == null) {
246: treePath = new TreePath(new Object[] {
247: resultTreeRoot, searchNode });
248: } else {
249: treePath = new TreePath(selectNode.getPath());
250: }
251: resultTree.setSelectionPath(treePath);
252: resultTree.scrollPathToVisible(treePath);
253: }
254: });
255: } //}}}
256:
257: //{{{ searchDone() method
258: public void searchDone(final DefaultMutableTreeNode searchNode) {
259: searchDone(searchNode, null);
260: } //}}}
261:
262: //{{{ Private members
263: private View view;
264:
265: private JLabel caption;
266: private final JTree resultTree;
267: private DefaultMutableTreeNode resultTreeRoot;
268: private DefaultTreeModel resultTreeModel;
269:
270: private RolloverButton clear;
271: private RolloverButton multi;
272: private boolean multiStatus;
273:
274: //{{{ updateMultiStatus() method
275: private void updateMultiStatus() {
276: if (multiStatus)
277: multi.setIcon(GUIUtilities.loadIcon("MultipleResults.png"));
278: else
279: multi.setIcon(GUIUtilities.loadIcon("SingleResult.png"));
280: } //}}}
281:
282: //{{{ goToSelectedNode() method
283: public static final int M_OPEN = 0;
284: public static final int M_OPEN_NEW_VIEW = 1;
285: public static final int M_OPEN_NEW_PLAIN_VIEW = 2;
286: public static final int M_OPEN_NEW_SPLIT = 3;
287:
288: private void goToSelectedNode(int mode) {
289: TreePath path = resultTree.getSelectionPath();
290: if (path == null)
291: return;
292:
293: DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
294: .getLastPathComponent();
295: Object value = node.getUserObject();
296:
297: // do nothing if clicked "foo (showing n occurrences in m files)"
298: if (node.getParent() != resultTreeRoot
299: && value instanceof HyperSearchNode) {
300: HyperSearchNode n = (HyperSearchNode) value;
301: Buffer buffer = n.getBuffer(view);
302: if (buffer == null)
303: return;
304:
305: EditPane pane;
306:
307: switch (mode) {
308: case M_OPEN:
309: pane = view.goToBuffer(buffer);
310: break;
311: case M_OPEN_NEW_VIEW:
312: pane = jEdit.newView(view, buffer, false).getEditPane();
313: break;
314: case M_OPEN_NEW_PLAIN_VIEW:
315: pane = jEdit.newView(view, buffer, true).getEditPane();
316: break;
317: case M_OPEN_NEW_SPLIT:
318: pane = view.splitHorizontally();
319: break;
320: default:
321: throw new IllegalArgumentException("Bad mode: " + mode);
322: }
323:
324: n.goTo(pane);
325: }
326: } //}}}
327:
328: //{{{ removeSelectedNode() method
329: private void removeSelectedNode() {
330: TreePath path = resultTree.getSelectionPath();
331: if (path == null)
332: return;
333:
334: MutableTreeNode value = (MutableTreeNode) path
335: .getLastPathComponent();
336:
337: if (path.getPathCount() > 1) {
338: // Adjust selection so that repeating some removals
339: // behave naturally.
340: TreePath parentPath = path.getParentPath();
341: MutableTreeNode parent = (MutableTreeNode) parentPath
342: .getLastPathComponent();
343: int removingIndex = parent.getIndex(value);
344: int nextIndex = removingIndex + 1;
345: if (nextIndex < parent.getChildCount()) {
346: TreeNode next = parent.getChildAt(nextIndex);
347: resultTree.setSelectionPath(parentPath
348: .pathByAddingChild(next));
349: } else {
350: resultTree.setSelectionPath(parentPath);
351: }
352:
353: resultTreeModel.removeNodeFromParent(value);
354: }
355:
356: HyperSearchOperationNode.removeNodeFromCache(value);
357: if (resultTreeRoot.getChildCount() == 0) {
358: hideDockable();
359: }
360: } //}}}
361:
362: //{{{ removeAllNodes() method
363: private void removeAllNodes() {
364: resultTreeRoot.removeAllChildren();
365: resultTreeModel.reload(resultTreeRoot);
366: setSearchStatus(null);
367: hideDockable();
368: } //}}}
369:
370: //{{{ hideDockable() method
371: private void hideDockable() {
372: view.getDockableWindowManager().hideDockableWindow(NAME);
373: } //}}}
374:
375: //}}}
376:
377: //{{{ ActionHandler class
378: public class ActionHandler implements ActionListener {
379: public void actionPerformed(ActionEvent evt) {
380: Object source = evt.getSource();
381: if (source == clear) {
382: removeAllNodes();
383: } else if (source == multi) {
384: multiStatus = !multiStatus;
385: updateMultiStatus();
386:
387: if (!multiStatus) {
388: for (int i = resultTreeRoot.getChildCount() - 2; i >= 0; i--) {
389: resultTreeModel
390: .removeNodeFromParent((MutableTreeNode) resultTreeRoot
391: .getChildAt(i));
392: }
393: }
394: }
395: }
396: } //}}}
397:
398: //{{{ KeyHandler class
399: class KeyHandler extends KeyAdapter {
400: public void keyPressed(KeyEvent evt) {
401: switch (evt.getKeyCode()) {
402: case KeyEvent.VK_SPACE:
403: goToSelectedNode(M_OPEN);
404:
405: // fuck me dead
406: SwingUtilities.invokeLater(new Runnable() {
407: public void run() {
408: resultTree.requestFocus();
409: }
410: });
411:
412: evt.consume();
413: break;
414: case KeyEvent.VK_ENTER:
415: goToSelectedNode(M_OPEN);
416: evt.consume();
417: break;
418: case KeyEvent.VK_DELETE:
419: removeSelectedNode();
420: evt.consume();
421: break;
422: default:
423: break;
424: }
425: }
426: } //}}}
427:
428: //{{{ MouseHandler class
429: class MouseHandler extends MouseAdapter {
430: //{{{ mousePressed() method
431: public void mousePressed(MouseEvent evt) {
432: if (evt.isConsumed())
433: return;
434:
435: TreePath path1 = resultTree.getPathForLocation(evt.getX(),
436: evt.getY());
437: if (path1 == null)
438: return;
439:
440: resultTree.setSelectionPath(path1);
441: if (GUIUtilities.isPopupTrigger(evt))
442: showPopupMenu(evt);
443: else {
444: goToSelectedNode(M_OPEN);
445: }
446: } //}}}
447:
448: //{{{ Private members
449: private JPopupMenu popupMenu;
450:
451: //{{{ showPopupMenu method
452: private void showPopupMenu(MouseEvent evt) {
453: TreePath path = resultTree.getSelectionPath();
454: DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
455: .getLastPathComponent();
456:
457: popupMenu = new JPopupMenu();
458: Object userObj = node.getUserObject();
459: if (userObj instanceof HyperSearchFileNode
460: || userObj instanceof HyperSearchResult) {
461: popupMenu.add(new GoToNodeAction(
462: "hypersearch-results.open", M_OPEN));
463: popupMenu.add(new GoToNodeAction(
464: "hypersearch-results.open-view",
465: M_OPEN_NEW_VIEW));
466: popupMenu.add(new GoToNodeAction(
467: "hypersearch-results.open-plain-view",
468: M_OPEN_NEW_PLAIN_VIEW));
469: popupMenu.add(new GoToNodeAction(
470: "hypersearch-results.open-split",
471: M_OPEN_NEW_SPLIT));
472: }
473: if (!(userObj instanceof HyperSearchFolderNode))
474: popupMenu.add(new RemoveTreeNodeAction());
475: popupMenu.add(new ExpandChildTreeNodesAction());
476: if (userObj instanceof HyperSearchFolderNode
477: || userObj instanceof HyperSearchOperationNode) {
478: popupMenu.add(new CollapseChildTreeNodesAction());
479: if (userObj instanceof HyperSearchFolderNode)
480: popupMenu.add(new NewSearchAction());
481: }
482: if (userObj instanceof HyperSearchOperationNode) {
483: popupMenu.add(new JPopupMenu.Separator());
484: HyperSearchOperationNode resultNode = (HyperSearchOperationNode) userObj;
485: JCheckBoxMenuItem chkItem = new JCheckBoxMenuItem(jEdit
486: .getProperty("hypersearch-results.tree-view"),
487: resultNode.isTreeViewDisplayed());
488: chkItem.addActionListener(new TreeDisplayAction());
489: popupMenu.add(chkItem);
490:
491: popupMenu.add(new RedoSearchAction(
492: (HyperSearchOperationNode) userObj));
493: }
494:
495: GUIUtilities.showPopupMenu(popupMenu, evt.getComponent(),
496: evt.getX(), evt.getY());
497: evt.consume();
498: } //}}}
499:
500: //}}}
501: } //}}}
502:
503: //{{{ RemoveTreeNodeAction class
504: class RemoveTreeNodeAction extends AbstractAction {
505: RemoveTreeNodeAction() {
506: super (jEdit.getProperty("hypersearch-results.remove-node"));
507: }
508:
509: public void actionPerformed(ActionEvent evt) {
510: removeSelectedNode();
511: }
512: }//}}}
513:
514: //{{{ RemoveAllTreeNodesAction class
515: class RemoveAllTreeNodesAction extends AbstractAction {
516: RemoveAllTreeNodesAction() {
517: super (
518: jEdit
519: .getProperty("hypersearch-results.remove-all-nodes"));
520: }
521:
522: public void actionPerformed(ActionEvent evt) {
523: removeAllNodes();
524: }
525: }//}}}
526:
527: //{{{ NewSearchAction class
528: class NewSearchAction extends AbstractAction {
529: NewSearchAction() {
530: super (jEdit.getProperty("hypersearch-results.new-search"));
531: }
532:
533: public void actionPerformed(ActionEvent evt) {
534: TreePath path = resultTree.getSelectionPath();
535: DefaultMutableTreeNode operNode = (DefaultMutableTreeNode) path
536: .getLastPathComponent();
537: HyperSearchFolderNode nodeObj = (HyperSearchFolderNode) operNode
538: .getUserObject();
539:
540: String glob = "*";
541: SearchFileSet dirList = SearchAndReplace.getSearchFileSet();
542: if (dirList instanceof DirectoryListSet)
543: glob = ((DirectoryListSet) dirList).getFileFilter();
544: SearchAndReplace
545: .setSearchFileSet(new DirectoryListSet(nodeObj
546: .getNodeFile().getAbsolutePath(), glob,
547: true));
548: SearchDialog.showSearchDialog(view, null,
549: SearchDialog.DIRECTORY);
550: }
551: }//}}}
552:
553: //{{{ ExpandChildTreeNodesAction class
554: class ExpandChildTreeNodesAction extends AbstractAction {
555: ExpandChildTreeNodesAction() {
556: super (
557: jEdit
558: .getProperty("hypersearch-results.expand-child-nodes"));
559: }
560:
561: public void actionPerformed(ActionEvent evt) {
562: TreePath path = resultTree.getSelectionPath();
563: DefaultMutableTreeNode operNode = (DefaultMutableTreeNode) path
564: .getLastPathComponent();
565: expandAllNodes(operNode);
566: }
567: }//}}}
568:
569: //{{{ CollapseChildTreeNodesAction class
570: class CollapseChildTreeNodesAction extends AbstractAction {
571: CollapseChildTreeNodesAction() {
572: super (
573: jEdit
574: .getProperty("hypersearch-results.collapse-child-nodes"));
575: }
576:
577: public void actionPerformed(ActionEvent evt) {
578: TreePath path = resultTree.getSelectionPath();
579: DefaultMutableTreeNode operNode = (DefaultMutableTreeNode) path
580: .getLastPathComponent();
581: for (Enumeration e = operNode.children(); e
582: .hasMoreElements();) {
583: DefaultMutableTreeNode node = (DefaultMutableTreeNode) e
584: .nextElement();
585: resultTree.collapsePath(new TreePath(node.getPath()));
586: }
587: resultTree.scrollPathToVisible(new TreePath(operNode
588: .getPath()));
589: }
590: }//}}}
591:
592: //{{{ RedoSearchAction class
593: class RedoSearchAction extends AbstractAction {
594: private HyperSearchOperationNode hyperSearchOperationNode;
595:
596: public RedoSearchAction(
597: HyperSearchOperationNode hyperSearchOperationNode) {
598: super (jEdit.getProperty("hypersearch-results.redo"));
599: this .hyperSearchOperationNode = hyperSearchOperationNode;
600: }
601:
602: /**
603: * Invoked when an action occurs.
604: */
605: public void actionPerformed(ActionEvent e) {
606: SearchAndReplace.setSearchMatcher(hyperSearchOperationNode
607: .getSearchMatcher());
608: removeSelectedNode();
609: SearchAndReplace.hyperSearch(view, false);
610: }
611: } //}}}
612:
613: //{{{ TreeDisplayAction class
614: class TreeDisplayAction extends AbstractAction {
615: public void actionPerformed(ActionEvent evt) {
616: JCheckBoxMenuItem menuItem = (JCheckBoxMenuItem) evt
617: .getSource();
618: boolean curState = menuItem.isSelected();
619:
620: TreePath path = resultTree.getSelectionPath();
621: DefaultMutableTreeNode operNode = (DefaultMutableTreeNode) path
622: .getLastPathComponent();
623:
624: HyperSearchOperationNode operNodeObj = (HyperSearchOperationNode) operNode
625: .getUserObject();
626: if (curState)
627: operNodeObj.cacheResultNodes(operNode);
628: operNode.removeAllChildren();
629: Exception excp = null;
630: if (curState) {
631: try {
632: operNodeObj.insertTreeNodes(resultTree, operNode);
633: } catch (Exception ex) {
634: operNodeObj.restoreFlatNodes(resultTree, operNode);
635: menuItem.setSelected(false);
636: excp = ex;
637: } finally {
638: ((DefaultTreeModel) resultTree.getModel())
639: .nodeStructureChanged(operNode);
640: expandAllNodes(operNode);
641: resultTree.scrollPathToVisible(new TreePath(
642: operNode.getPath()));
643: }
644: if (excp != null)
645: throw new RuntimeException(excp);
646: } else
647: operNodeObj.restoreFlatNodes(resultTree, operNode);
648:
649: operNodeObj.setTreeViewDisplayed(menuItem.isSelected());
650: }
651: }//}}}
652:
653: //{{{ expandAllNodes() method
654: public void expandAllNodes(DefaultMutableTreeNode node) {
655:
656: traverseNodes(node, new TreeNodeCallbackAdapter() {
657: public boolean processNode(DefaultMutableTreeNode node) {
658: resultTree.expandPath(new TreePath(node.getPath()));
659: return true;
660: }
661: });
662: } //}}}
663:
664: //{{{ GoToNodeAction class
665: class GoToNodeAction extends AbstractAction {
666: private int mode;
667:
668: GoToNodeAction(String labelProp, int mode) {
669: super (jEdit.getProperty(labelProp));
670: this .mode = mode;
671: }
672:
673: public void actionPerformed(ActionEvent evt) {
674: goToSelectedNode(mode);
675: }
676: }//}}}
677:
678: //{{{ ResultCellRenderer class
679: class ResultCellRenderer extends DefaultTreeCellRenderer {
680: Font plainFont, boldFont;
681:
682: //{{{ ResultCellRenderer constructor
683: ResultCellRenderer() {
684: plainFont = UIManager.getFont("Tree.font");
685: if (plainFont == null)
686: plainFont = jEdit
687: .getFontProperty("metal.secondary.font");
688: boldFont = new Font(plainFont.getName(), Font.BOLD,
689: plainFont.getSize());
690: } //}}}
691:
692: //{{{ getTreeCellRendererComponent() method
693: public Component getTreeCellRendererComponent(JTree tree,
694: Object value, boolean sel, boolean expanded,
695: boolean leaf, int row, boolean hasFocus) {
696: super .getTreeCellRendererComponent(tree, value, sel,
697: expanded, leaf, row, hasFocus);
698: setIcon(null);
699: DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
700:
701: if (node.getUserObject() instanceof HyperSearchOperationNode) {
702: setFont(boldFont);
703:
704: CountNodes countNodes = new CountNodes();
705: traverseNodes(node, countNodes);
706:
707: setText(jEdit
708: .getProperty(
709: "hypersearch-results.result-caption",
710: new Object[] {
711: node.toString(),
712: Integer
713: .valueOf(countNodes.resultCount),
714: Integer
715: .valueOf(countNodes.bufferCount) }));
716: } else if (node.getUserObject() instanceof HyperSearchFolderNode) {
717: setFont(plainFont);
718: setText(node.toString() + " (" + node.getChildCount()
719: + " files/folders)");
720: } else if (node.getUserObject() instanceof HyperSearchFileNode) {
721: // file name
722: setFont(boldFont);
723: HyperSearchFileNode hyperSearchFileNode = (HyperSearchFileNode) node
724: .getUserObject();
725: setText(jEdit
726: .getProperty(
727: "hypersearch-results.file-caption",
728: new Object[] {
729: hyperSearchFileNode,
730: Integer
731: .valueOf(hyperSearchFileNode
732: .getCount()),
733: Integer.valueOf(node
734: .getChildCount()) }));
735: } else {
736: setFont(plainFont);
737: }
738:
739: return this ;
740: } //}}}
741:
742: //{{{ CountNodes class
743: class CountNodes implements HyperSearchTreeNodeCallback {
744: int bufferCount;
745: int resultCount;
746:
747: public boolean processNode(DefaultMutableTreeNode node) {
748: Object userObject = node.getUserObject();
749: if (userObject instanceof HyperSearchFileNode) {
750: resultCount += ((HyperSearchFileNode) userObject)
751: .getCount();
752: bufferCount++;
753: }
754: return true;
755: }
756: }//}}}
757: } //}}}
758:
759: // these are used to eliminate code duplication. i don't normally use
760: // the visitor or "template method" pattern, but this code was contributed
761: // by Peter Cox and i don't feel like changing it around too much.
762:
763: //{{{ ResultVisitor interface
764: interface ResultVisitor {
765: void visit(Buffer buffer, HyperSearchResult result);
766: } //}}}
767:
768: //{{{ BufferLoadedVisitor class
769: static class BufferLoadedVisitor implements ResultVisitor {
770: public void visit(Buffer buffer, HyperSearchResult result) {
771: result.bufferOpened(buffer);
772: }
773: } //}}}
774:
775: //{{{ BufferClosedVisitor class
776: static class BufferClosedVisitor implements ResultVisitor {
777: public void visit(Buffer buffer, HyperSearchResult result) {
778: result.bufferClosed();
779: }
780: } //}}}
781:
782: //{{{ TreeNodeCallbackAdapter class
783: static class TreeNodeCallbackAdapter implements
784: HyperSearchTreeNodeCallback {
785: public boolean processNode(DefaultMutableTreeNode node) {
786: return false;
787: }
788:
789: } //}}}
790: }
|