KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > texteditor > FindNextAction


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.ui.texteditor;
13
14
15 import java.util.ArrayList JavaDoc;
16 import java.util.List JavaDoc;
17 import java.util.ResourceBundle JavaDoc;
18 import java.util.regex.PatternSyntaxException JavaDoc;
19
20 import org.eclipse.swt.graphics.Point;
21 import org.eclipse.swt.widgets.Shell;
22
23 import org.eclipse.jface.action.IStatusLineManager;
24 import org.eclipse.jface.dialogs.IDialogSettings;
25
26 import org.eclipse.jface.text.IFindReplaceTarget;
27 import org.eclipse.jface.text.IFindReplaceTargetExtension3;
28 import org.eclipse.jface.text.TextUtilities;
29
30 import org.eclipse.ui.IEditorPart;
31 import org.eclipse.ui.IWorkbenchPart;
32 import org.eclipse.ui.IWorkbenchWindow;
33 import org.eclipse.ui.internal.texteditor.TextEditorPlugin;
34
35
36 /**
37  * An action which finds the next/previous occurrence of the last search or the
38  * current selection if present.
39  * <p>
40  * This class may be instantiated; it is not intended to be subclassed.
41  * </p>
42  *
43  * @since 2.0
44  */

45 public class FindNextAction extends ResourceAction implements IUpdate {
46
47     /** The action's target */
48     private IFindReplaceTarget fTarget;
49     /** The part the action is bound to */
50     private IWorkbenchPart fWorkbenchPart;
51     /** The workbench window */
52     private IWorkbenchWindow fWorkbenchWindow;
53     /** The dialog settings to retrieve the last search */
54     private IDialogSettings fDialogSettings;
55     /** The find history as initially given in the dialog settings. */
56     private List JavaDoc fFindHistory= new ArrayList JavaDoc();
57     /** The find string as initially given in the dialog settings. */
58     private String JavaDoc fFindString;
59     /** The search direction as initially given in the dialog settings. */
60     private boolean fForward;
61     /** The wrapping flag as initially given in the dialog settings. */
62     private boolean fWrapInit;
63     /** The case flag as initially given in the dialog settings. */
64     private boolean fCaseInit;
65     /** The whole word flag as initially given in the dialog settings. */
66     private boolean fWholeWordInit;
67     /**
68      * The regExSearch flag as initially given in the dialog settings.
69      *
70      * @since 3.0
71      */

72     private boolean fRegExSearch;
73     /**
74      * The last selection set by find/replace.
75      *
76      * @since 3.0
77      */

78     private String JavaDoc fSelection;
79
80     /**
81      * Creates a new find/replace action for the given workbench part.
82      * The action configures its visual representation from the given
83      * resource bundle.
84      *
85      * @param bundle the resource bundle
86      * @param prefix a prefix to be prepended to the various resource keys
87      * (described in <code>ResourceAction</code> constructor), or
88      * <code>null</code> if none
89      * @param workbenchPart the workbench part
90      * @param forward the search direction
91      * @see ResourceAction#ResourceAction(ResourceBundle, String)
92      */

93     public FindNextAction(ResourceBundle JavaDoc bundle, String JavaDoc prefix, IWorkbenchPart workbenchPart, boolean forward) {
94         super(bundle, prefix);
95         fWorkbenchPart= workbenchPart;
96         fForward= forward;
97         update();
98     }
99
100     /**
101      * Creates a new find/replace action for the given workbench window.
102      * The action configures its visual representation from the given
103      * resource bundle.
104      *
105      * @param bundle the resource bundle
106      * @param prefix a prefix to be prepended to the various resource keys
107      * (described in <code>ResourceAction</code> constructor), or
108      * <code>null</code> if none
109      * @param workbenchWindow the workbench window
110      * @param forward the search direction
111      * @see ResourceAction#ResourceAction(ResourceBundle, String)
112      *
113      * @deprecated use FindReplaceAction(ResourceBundle, String, IWorkbenchPart, boolean) instead
114      */

115     public FindNextAction(ResourceBundle JavaDoc bundle, String JavaDoc prefix, IWorkbenchWindow workbenchWindow, boolean forward) {
116         super(bundle, prefix);
117         fWorkbenchWindow= workbenchWindow;
118         fForward= forward;
119         update();
120     }
121
122     /**
123      * Returns the find string based on the selection or the find history.
124      * @return the find string
125      */

126     private String JavaDoc getFindString() {
127         String JavaDoc string= getSelectionString();
128
129         if ((string == null || fRegExSearch && string.equals(fSelection)) && !fFindHistory.isEmpty())
130             string= (String JavaDoc) fFindHistory.get(0);
131
132         return string;
133     }
134
135     /**
136      * Returns the status line manager of the active editor.
137      * @return the status line manager of the active editor
138      */

139     private IStatusLineManager getStatusLineManager() {
140         IEditorPart editor= fWorkbenchPart.getSite().getPage().getActiveEditor();
141         if (editor == null)
142             return null;
143         
144         return editor.getEditorSite().getActionBars().getStatusLineManager();
145     }
146
147     /**
148      * Sets the "no matches found" error message to the status line.
149      *
150      * @since 3.0
151      */

152     private void statusNotFound() {
153         fWorkbenchPart.getSite().getShell().getDisplay().beep();
154
155         IStatusLineManager manager= getStatusLineManager();
156         if (manager == null)
157             return;
158
159         manager.setMessage(EditorMessages.FindNext_Status_noMatch_label);
160     }
161
162     /**
163      * Clears the status line.
164      */

165     private void statusClear() {
166         IStatusLineManager manager= getStatusLineManager();
167         if (manager == null)
168             return;
169
170         manager.setErrorMessage(""); //$NON-NLS-1$
171
manager.setMessage(""); //$NON-NLS-1$
172
}
173
174     /*
175      * @see IAction#run()
176      */

177     public void run() {
178         if (fTarget != null) {
179             readConfiguration();
180
181             fFindString= getFindString();
182             if (fFindString == null) {
183                 statusNotFound();
184                 return;
185             }
186             
187             boolean wholeWord= fWholeWordInit && !fRegExSearch && isWord(fFindString);
188
189             statusClear();
190             if (!findNext(fFindString, fForward, fCaseInit, fWrapInit, wholeWord, fRegExSearch))
191                 statusNotFound();
192
193             writeConfiguration();
194         }
195     }
196     
197     /**
198      * Tests whether each character in the given
199      * string is a letter.
200      *
201      * @param str
202      * @return <code>true</code> if the given string is a word
203      * @since 3.2
204      */

205     private boolean isWord(String JavaDoc str) {
206         if (str == null || str.length() == 0)
207             return false;
208
209         for (int i= 0; i < str.length(); i++) {
210             if (!Character.isJavaIdentifierPart(str.charAt(i)))
211                 return false;
212         }
213         return true;
214     }
215
216     /*
217      * @see IUpdate#update()
218      */

219     public void update() {
220
221         if (fWorkbenchPart == null && fWorkbenchWindow != null)
222             fWorkbenchPart= fWorkbenchWindow.getPartService().getActivePart();
223
224         if (fWorkbenchPart != null)
225             fTarget= (IFindReplaceTarget) fWorkbenchPart.getAdapter(IFindReplaceTarget.class);
226         else
227             fTarget= null;
228
229         setEnabled(fTarget != null && fTarget.canPerformFind());
230     }
231
232     /*
233      * @see FindReplaceDialog#findIndex(String, int, boolean, boolean, boolean, boolean)
234      * @since 3.0
235      */

236     private int findIndex(String JavaDoc findString, int startPosition, boolean forwardSearch, boolean caseSensitive, boolean wrapSearch, boolean wholeWord, boolean regExSearch) {
237
238         if (forwardSearch) {
239             if (wrapSearch) {
240                 int index= findAndSelect(startPosition, findString, true, caseSensitive, wholeWord, regExSearch);
241                 if (index == -1) {
242                     beep();
243                     index= findAndSelect(-1, findString, true, caseSensitive, wholeWord, regExSearch);
244                 }
245                 return index;
246             }
247             return findAndSelect(startPosition, findString, true, caseSensitive, wholeWord, regExSearch);
248         }
249
250         // backward
251
if (wrapSearch) {
252             int index= findAndSelect(startPosition - 1, findString, false, caseSensitive, wholeWord, regExSearch);
253             if (index == -1) {
254                 beep();
255                 index= findAndSelect(-1, findString, false, caseSensitive, wholeWord, regExSearch);
256             }
257             return index;
258         }
259         return findAndSelect(startPosition - 1, findString, false, caseSensitive, wholeWord, regExSearch);
260     }
261
262     /**
263      * Returns whether the specified search string can be found using the given options.
264      *
265      * @param findString the string to search for
266      * @param forwardSearch the search direction
267      * @param caseSensitive should the search honor cases
268      * @param wrapSearch should the search wrap to the start/end if end/start reached
269      * @param wholeWord does the find string represent a complete word
270      * @param regExSearch if <code>true</code> findString represents a regular expression
271      * @return <code>true</code> if the find string can be found using the given options
272      * @since 3.0
273      */

274     private boolean findNext(String JavaDoc findString, boolean forwardSearch, boolean caseSensitive, boolean wrapSearch, boolean wholeWord, boolean regExSearch) {
275
276         Point r= fTarget.getSelection();
277         int findReplacePosition= r.x;
278         if (forwardSearch)
279             findReplacePosition += r.y;
280
281         int index= findIndex(findString, findReplacePosition, forwardSearch, caseSensitive, wrapSearch, wholeWord, regExSearch);
282
283         if (index != -1)
284             return true;
285
286         return false;
287     }
288
289     private void beep() {
290         Shell shell= null;
291         if (fWorkbenchPart != null)
292             shell= fWorkbenchPart.getSite().getShell();
293         else if (fWorkbenchWindow != null)
294             shell= fWorkbenchWindow.getShell();
295
296         if (shell != null && !shell.isDisposed())
297             shell.getDisplay().beep();
298     }
299
300     /**
301      * Searches for a string starting at the given offset and using the specified search
302      * directives. If a string has been found it is selected and its start offset is
303      * returned.
304      *
305      * @param offset the offset at which searching starts
306      * @param findString the string which should be found
307      * @param forwardSearch the direction of the search
308      * @param caseSensitive <code>true</code> performs a case sensitive search, <code>false</code> an insensitive search
309      * @param wholeWord if <code>true</code> only occurrences are reported in which the findString stands as a word by itself
310      * @param regExSearch if <code>true</code> findString represents a regular expression
311      * @return the position of the specified string, or -1 if the string has not been found
312      * @since 3.0
313      */

314     private int findAndSelect(int offset, String JavaDoc findString, boolean forwardSearch, boolean caseSensitive, boolean wholeWord, boolean regExSearch) {
315         if (fTarget instanceof IFindReplaceTargetExtension3) {
316             try {
317                 return ((IFindReplaceTargetExtension3)fTarget).findAndSelect(offset, findString, forwardSearch, caseSensitive, wholeWord, regExSearch);
318             } catch (PatternSyntaxException JavaDoc ex) {
319                 return -1;
320             }
321         }
322         return fTarget.findAndSelect(offset, findString, forwardSearch, caseSensitive, wholeWord);
323     }
324
325     //--------------- configuration handling --------------
326

327     /**
328      * Returns the dialog settings object used to share state
329      * between several find/replace dialogs.
330      *
331      * @return the dialog settings to be used
332      */

333     private IDialogSettings getDialogSettings() {
334         IDialogSettings settings= TextEditorPlugin.getDefault().getDialogSettings();
335         fDialogSettings= settings.getSection(FindReplaceDialog.class.getName());
336         if (fDialogSettings == null)
337             fDialogSettings= settings.addNewSection(FindReplaceDialog.class.getName());
338         return fDialogSettings;
339     }
340
341     /**
342      * Initializes itself from the dialog settings with the same state
343      * as at the previous invocation.
344      */

345     private void readConfiguration() {
346         IDialogSettings s= getDialogSettings();
347
348         fWrapInit= s.getBoolean("wrap"); //$NON-NLS-1$
349
fCaseInit= s.getBoolean("casesensitive"); //$NON-NLS-1$
350
fWholeWordInit= s.getBoolean("wholeword"); //$NON-NLS-1$
351
fRegExSearch= s.getBoolean("isRegEx"); //$NON-NLS-1$
352
fSelection= s.get("selection"); //$NON-NLS-1$
353

354         String JavaDoc[] findHistory= s.getArray("findhistory"); //$NON-NLS-1$
355
if (findHistory != null) {
356             fFindHistory.clear();
357             for (int i= 0; i < findHistory.length; i++)
358                 fFindHistory.add(findHistory[i]);
359         }
360     }
361
362     /**
363      * Stores its current configuration in the dialog store.
364      */

365     private void writeConfiguration() {
366         if (fFindString == null)
367             return;
368
369         IDialogSettings s= getDialogSettings();
370
371         String JavaDoc selection= fTarget.getSelectionText();
372         if (selection == null)
373             selection= ""; //$NON-NLS-1$
374
s.put("selection", selection); //$NON-NLS-1$
375

376         if (!fFindHistory.isEmpty() && fFindString.equals(fFindHistory.get(0)))
377             return;
378
379         int index= fFindHistory.indexOf(fFindString);
380         if (index != -1)
381             fFindHistory.remove(index);
382         fFindHistory.add(0, fFindString);
383
384         while (fFindHistory.size() > 8)
385             fFindHistory.remove(8);
386         String JavaDoc[] names= new String JavaDoc[fFindHistory.size()];
387         fFindHistory.toArray(names);
388         s.put("findhistory", names); //$NON-NLS-1$
389
}
390
391     /**
392      * Returns the actual selection of the find replace target.
393      *
394      * @return the actual selection of the find replace target
395      */

396     private String JavaDoc getSelectionString() {
397
398         /*
399          * 1GF86V3: ITPUI:WINNT - Internal errors using Find/Replace Dialog
400          * Now uses TextUtilities rather than focusing on '\n'
401          */

402         String JavaDoc selection= fTarget.getSelectionText();
403         if (selection != null && selection.length() > 0) {
404             int[] info= TextUtilities.indexOf(TextUtilities.DELIMITERS, selection, 0);
405             if (info[0] > 0)
406                 return selection.substring(0, info[0]);
407             else if (info[0] == -1)
408                 return selection;
409         }
410         return null;
411     }
412 }
413
Popular Tags