001: package tide.syntaxtree;
002:
003: import tide.editor.Accelerators;
004: import javax.swing.*;
005: import javax.swing.event.*;
006: import java.awt.*;
007: import java.awt.event.*;
008: import java.util.*;
009: import snow.utils.gui.Icons;
010: import javax.swing.tree.TreeNode;
011: import javax.swing.tree.DefaultMutableTreeNode;
012:
013: /** Todo: filter, not only search.
014: */
015: public final class SyntaxTreeSearchPanel extends JPanel {
016: final JTextField searchField = new JTextField(5);
017: final SyntaxTreePanel stp;
018:
019: //TODO
020: // final private JButton searchPrevious = new JButton(new Icons.UpIcon(10,10, true));
021: // final private JButton searchNext = new JButton(new Icons.DownIcon(10,10, true));
022:
023: final private JButton close = new JButton(Icons.sharedCross);
024:
025: public TreeNode actualHit = null;
026: public String actualHitText = null;
027:
028: public SyntaxTreeSearchPanel(SyntaxTreePanel stp) {
029: super (new FlowLayout(FlowLayout.LEFT, 2, 0));
030: this .stp = stp;
031: add(close);
032: add(new JLabel(" Search: "));
033: close.setMargin(new Insets(0, 0, 0, 0));
034: close.setFocusPainted(false);
035:
036: add(searchField);
037:
038: /* searchPrevious.setMargin(new Insets(0,0,0,0));
039: searchPrevious.setFocusPainted(false);
040:
041: searchNext.setMargin(new Insets(0,0,0,0));
042: searchNext.setFocusPainted(false);
043: */
044: close.addActionListener(new ActionListener() {
045: public void actionPerformed(ActionEvent ae) {
046: setVisible(false);
047: }
048: });
049:
050: stp.registerKeyboardAction(new ActionListener() {
051: public void actionPerformed(ActionEvent ae) {
052: CTRL_F_pressed();
053: }
054: }, "Search", Accelerators.search,
055: JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); // true??
056:
057: /* searchField.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) {
058: search();
059: } });*/
060:
061: searchField.addKeyListener(new KeyAdapter() {
062: @Override
063: public void keyReleased(KeyEvent ke) {
064: if (ke.getKeyCode() == KeyEvent.VK_ENTER) {
065: search(true);
066: } else {
067: search(false);
068: }
069: }
070: });
071: }
072:
073: /** keys passed from the tree key adapter. (key typed)
074: * the tree has already a kind of search, subtle, if you quickly type some text, you'll find it,
075: * but only for nodes "starting with " the text.
076: * here we have a global scope seach.
077: * TODO: a filter !
078: */
079: public void appendTypedChar(char c) {
080: if (c < 30) {
081: return;
082: }
083:
084: if (!this .isVisible()) {
085: this .setVisible(true);
086: searchField.setText("" + c);
087: } else {
088: searchField.setText(searchField.getText() + c);
089: }
090: searchField.requestFocus();
091: search(true);
092: }
093:
094: public void CTRL_F_pressed() {
095: showSearchPanel();
096: }
097:
098: public void showSearchPanel() {
099: if (!this .isVisible()) {
100: this .setVisible(true);
101: }
102: searchField.selectAll();
103: searchField.requestFocus();
104: }
105:
106: public void resetSearch() {
107: actualHit = null;
108: }
109:
110: public void search(boolean enforceNext) {
111: DefaultMutableTreeNode root = (DefaultMutableTreeNode) stp
112: .getActualRoot();
113:
114: if (actualHit == null) {
115: actualHit = root;
116: }
117: if (actualHit == null)
118: return;
119:
120: // breathfirst
121: Enumeration bfen = root.breadthFirstEnumeration();
122:
123: String toSearch = searchField.getText().toUpperCase();
124: boolean includeActual = false;
125: if (actualHitText != null && toSearch.startsWith(actualHitText)
126: && !enforceNext) {
127: includeActual = true;
128: }
129:
130: boolean startSearching = false;
131: if (actualHit == null)
132: startSearching = true;
133: while (bfen.hasMoreElements()) {
134: TreeNode tn = (TreeNode) bfen.nextElement();
135: if (!startSearching) {
136: if (tn == actualHit) {
137: startSearching = true;
138: if (!includeActual)
139: continue;
140: }
141: }
142:
143: if (startSearching) {
144:
145: String nv = tn.toString().toUpperCase();
146: if (nv.indexOf(toSearch) >= 0) {
147: actualHit = tn;
148: actualHitText = toSearch;
149: stp.setNodeToPreselect(actualHit);
150: return;
151: }
152: }
153: }
154:
155: // not found:
156: actualHit = null;
157: actualHitText = null;
158: stp.setNodeToPreselect(null);
159: }
160:
161: }
|