KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > j > IncrementalFindTextFieldHandler


1 /*
2  * IncrementalFindTextFieldHandler.java
3  *
4  * Copyright (C) 1998-2004 Peter Graves
5  * $Id: IncrementalFindTextFieldHandler.java,v 1.5 2004/07/15 19:20:11 piso Exp $
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */

21
22 package org.armedbear.j;
23
24 import java.awt.event.KeyEvent JavaDoc;
25 import javax.swing.SwingUtilities JavaDoc;
26 import javax.swing.undo.CompoundEdit JavaDoc;
27
28 public final class IncrementalFindTextFieldHandler extends DefaultTextFieldHandler
29     implements Constants
30 {
31     private final Display display;
32     private final Buffer buffer;
33
34     private Search search;
35     private CompoundEdit JavaDoc edit;
36     private boolean inHistory;
37     private KeyMap keyMap;
38
39     // Initial state.
40
private final Position initialDot;
41     private final int initialDotCol;
42     private final Position initialMark;
43
44     public IncrementalFindTextFieldHandler(Editor editor, HistoryTextField textField)
45     {
46         super(editor, textField);
47         display = editor.getDisplay();
48         buffer = editor.getBuffer();
49         search = new Search();
50         if (buffer.supportsUndo) {
51             edit = new CompoundEdit JavaDoc();
52             edit.addEdit(new UndoFold(editor));
53             edit.addEdit(new UndoMove(editor));
54         }
55         initializeKeyMap();
56         // Save initial state.
57
initialDot = editor.getDotCopy();
58         initialDotCol = display.getCaretCol() + display.getShift();
59         if (editor.getMark() != null)
60             initialMark = editor.getMark().copy();
61         else
62             initialMark = null;
63     }
64
65     public void initializeKeyMap()
66     {
67         keyMap = new KeyMap();
68         keyMap.addMappingsForCommand("incrementalFind", KeyMap.getGlobalKeyMap());
69         keyMap.addMappingsForCommand("incrementalFind", buffer.getKeyMapForMode());
70         keyMap.addMappingsForCommand("findNext", KeyMap.getGlobalKeyMap());
71         keyMap.addMappingsForCommand("findNext", buffer.getKeyMapForMode());
72         keyMap.addMappingsForCommand("findPrev", KeyMap.getGlobalKeyMap());
73         keyMap.addMappingsForCommand("findPrev", buffer.getKeyMapForMode());
74     }
75
76     public void escape()
77     {
78         restoreInitialState();
79         editor.ensureActive();
80         editor.setFocusToDisplay();
81         editor.updateLocation();
82         // Erase "not found" message (if any).
83
editor.status("");
84     }
85
86     private void restoreInitialState()
87     {
88         editor.updateDotLine();
89         editor.setDot(initialDot);
90         editor.updateDotLine();
91         editor.setMark(initialMark);
92         if (initialMark != null && initialMark.getLine() != initialDot.getLine())
93             editor.setUpdateFlag(REPAINT);
94         display.setCaretCol(initialDotCol - display.getShift());
95         editor.setUpdateFlag(REFRAME);
96         editor.updateDisplay();
97     }
98
99     public void keyPressed(KeyEvent JavaDoc e)
100     {
101         final char keyChar = e.getKeyChar();
102         final int keyCode = e.getKeyCode();
103         // Mask off the bits we don't care about (Java 1.4).
104
final int modifiers = e.getModifiers() & 0x0f;
105         switch (keyCode) {
106             case KeyEvent.VK_ESCAPE:
107                 escape();
108                 e.consume();
109                 return;
110             case KeyEvent.VK_BACK_SPACE:
111                 backspace();
112                 e.consume();
113                 return;
114             case KeyEvent.VK_N:
115                 if (modifiers == CTRL_MASK) {
116                     e.consume();
117                     retrieveHistory(1);
118                     return;
119                 }
120                 break;
121             case KeyEvent.VK_P:
122                 if (modifiers == CTRL_MASK) {
123                     e.consume();
124                     retrieveHistory(-1);
125                     return;
126                 }
127                 break;
128             case KeyEvent.VK_W:
129                 if (modifiers == CTRL_MASK) {
130                     e.consume();
131                     yankWord();
132                 }
133                 break;
134             case KeyEvent.VK_ENTER:
135                 e.consume(); // Fall through...
136
case KeyEvent.VK_LEFT:
137             case KeyEvent.VK_KP_LEFT:
138             case KeyEvent.VK_RIGHT:
139             case KeyEvent.VK_KP_RIGHT:
140             case KeyEvent.VK_UP:
141             case KeyEvent.VK_KP_UP:
142             case KeyEvent.VK_DOWN:
143             case KeyEvent.VK_KP_DOWN:
144             case KeyEvent.VK_HOME:
145             case KeyEvent.VK_END:
146                 if (modifiers == 0)
147                     finish(e);
148                 return;
149             default:
150                 break;
151         }
152         KeyMapping mapping = keyMap.lookup(keyChar, keyCode, modifiers);
153         if (mapping != null) {
154             Object JavaDoc command = mapping.getCommand();
155             if (command == "incrementalFind" || command == "findNext") {
156                 e.consume();
157                 findNext();
158                 return;
159             }
160             if (command == "findPrev") {
161                 e.consume();
162                 findPrev();
163                 return;
164             }
165         }
166     }
167
168     private void retrieveHistory(int direction)
169     {
170         History history = textField.getHistory();
171         if (history == null)
172             return;
173         if (!inHistory)
174             history.reset();
175         String JavaDoc s = direction < 0 ? history.getPrevious() : history.getNext();
176         if (s != null && s.length() != 0) {
177             inHistory = true;
178             search.setPattern(s);
179             textField.setText(s);
180             textField.setCaretPosition(s.length());
181             return;
182         }
183     }
184
185     private void yankWord()
186     {
187         inHistory = false;
188         int begin = editor.getDotOffset();
189         int end = begin + search.getPatternLength();
190         final Line dotLine = editor.getDotLine();
191         final int limit = dotLine.length();
192         final Mode mode = buffer.getMode();
193         // Grab non-word chars at end of search pattern.
194
while (end < limit && !mode.isIdentifierPart(dotLine.charAt(end)))
195             ++end;
196         // Grab next word.
197
while (end < limit && mode.isIdentifierPart(dotLine.charAt(end)))
198             ++end;
199         String JavaDoc s = dotLine.substring(begin, end);
200         // If the current pattern is all lower case, convert the new pattern
201
// to lower case so the search will continue to be case insensitive.
202
if (Utilities.isLowerCase(search.getPattern()))
203             s = s.toLowerCase();
204         if (!s.equals(search.getPattern())) {
205             search.setPattern(s);
206             editor.markFoundPattern(search);
207             editor.updateDisplay();
208         }
209     }
210
211     private void finish(KeyEvent JavaDoc e)
212     {
213         if (search.getPattern() != null && search.getPatternLength() > 0) {
214             editor.setLastSearch(search);
215             History history = textField.getHistory();
216             if (history != null) {
217                 history.append(search.getPattern());
218                 history.save();
219             }
220             if (edit != null) {
221                 edit.end();
222                 buffer.addEdit(edit);
223             }
224         }
225         final int keyCode = e.getKeyCode();
226         if (keyCode == KeyEvent.VK_ENTER) {
227             String JavaDoc pattern = textField.getText();
228             if (pattern == null || pattern.length() == 0) {
229                 editor.updateLocation();
230                 FindDialog.find(editor);
231                 editor.updateDisplay();
232                 return;
233             }
234         } else {
235             editor.handleKeyEvent(e.getKeyChar(), keyCode, e.getModifiers());
236             // We may need to do a horizontal reframe (home, end).
237
editor.updateDisplay();
238         }
239         editor.ensureActive();
240         editor.setFocusToDisplay();
241         editor.updateLocation();
242     }
243
244     public void keyReleased(KeyEvent JavaDoc e)
245     {
246         textField.setText(search.getPattern());
247         textField.setCaretPosition(search.getPatternLength());
248     }
249
250     public void keyTyped(KeyEvent JavaDoc e)
251     {
252         // Mask off the bits we don't care about (Java 1.4).
253
final int modifiers = e.getModifiers() & 0x0f;
254         if (modifiers == 0 || modifiers == SHIFT_MASK)
255             handleKeyEvent(e);
256     }
257
258     private void handleKeyEvent(KeyEvent JavaDoc e)
259     {
260         // Mask off bits we don't care about (Java 1.4).
261
int modifiers = e.getModifiers() & 0x0f;
262         if (modifiers != 0 && modifiers != KeyEvent.SHIFT_MASK)
263             return;
264         char c = e.getKeyChar();
265         if (c == KeyEvent.CHAR_UNDEFINED)
266             return;
267         if (c == 8) {
268             e.consume();
269             return;
270         }
271         inHistory = false;
272         search.appendCharToPattern(c);
273         // Convention is to ignore case unless pattern is mixed case or
274
// all caps.
275
search.setIgnoreCase(Utilities.isLowerCase(search.getPattern()));
276         Position pos = search.findString(buffer, editor.getDot(), true);
277         if (pos != null)
278             found(pos);
279         else
280             search.notFound(editor);
281     }
282
283     private void backspace()
284     {
285         String JavaDoc s = textField.getText();
286         if (s.length() > 0) {
287             s = s.substring(0, s.length()-1);
288             textField.setText(s);
289             search.setPattern(s);
290             search.setIgnoreCase(Utilities.isLowerCase(s));
291             if (s.length() > 0) {
292                 Position pos = search.findString(buffer, initialDot, true);
293                 if (pos != null) {
294                     found(pos);
295                     // Erase "not found" message (if any).
296
editor.status("");
297                 } else
298                     search.notFound(editor);
299             } else
300                 restoreInitialState();
301         }
302     }
303
304     private void findNext()
305     {
306         if (search.getPatternLength() > 0) {
307             // Only advance dot if we're really searching for the same pattern
308
// again. We might be doing the first search on a pattern
309
// retrieved from history.
310
if (!inHistory) {
311                 if (editor.getDotOffset() < editor.getDotLine().length())
312                     editor.getDot().skip(1);
313                 else if (editor.getDotLine().next() != null)
314                     editor.setDot(editor.getDotLine().next(), 0);
315                 else
316                     // Wrap buffer.
317
editor.setDot(buffer.getFirstLine(), 0);
318             }
319         } else {
320             // Recall last pattern.
321
History history = textField.getHistory();
322             if (history != null) {
323                 history.reset();
324                 String JavaDoc s = history.getPrevious();
325                 if (s == null)
326                     s = "";
327                 search.setPattern(s);
328                 if (s.length() == 0)
329                     return;
330                 textField.setText(s);
331                 textField.setCaretPosition(s.length());
332             }
333         }
334         inHistory = false;
335         // Convention is to ignore case unless pattern is mixed case or all
336
// caps.
337
search.setIgnoreCase(Utilities.isLowerCase(search.getPattern()));
338         Position pos = search.findString(buffer, editor.getDot(), true);
339         if (pos != null)
340             found(pos);
341     }
342
343     private void findPrev()
344     {
345         if (search.getPatternLength() > 0) {
346             Position start;
347             if (editor.getMark() != null)
348                 start = new Region(editor).getBegin();
349             else
350                 start = editor.getDotCopy();
351             boolean wrapped = false;
352             if (!start.prev()) {
353                 start = buffer.getEnd();
354                 wrapped = true;
355             }
356             Position pos = search.reverseFindString(buffer, start);
357             if (pos == null && !wrapped)
358                 pos = search.reverseFindString(buffer, buffer.getEnd());
359             if (pos != null)
360                 found(pos);
361         }
362     }
363
364     private boolean dirty;
365
366     private void found(Position pos)
367     {
368         if (editor.getMark() != null)
369             if (editor.getMarkLine() != editor.getDotLine())
370                 editor.setUpdateFlag(REPAINT);
371         editor.updateDotLine();
372         editor.getDot().moveTo(pos);
373         editor.updateDotLine();
374         editor.setUpdateFlag(REFRAME);
375         dirty = true;
376         SwingUtilities.invokeLater(foundRunnable);
377     }
378
379     private final Runnable JavaDoc foundRunnable = new Runnable JavaDoc() {
380         public void run()
381         {
382             if (dirty) {
383                 editor.markFoundPattern(search);
384                 editor.updateDisplay();
385                 dirty = false;
386             }
387         }
388     };
389 }
390
Popular Tags