### Eclipse Workspace Patch 1.0 #P org.eclipse.jface.text Index: src/org/eclipse/jface/text/TextViewer.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jface.text/src/org/eclipse/jface/text/TextViewer.java,v retrieving revision 1.180 diff -u -r1.180 TextViewer.java --- src/org/eclipse/jface/text/TextViewer.java 20 Jun 2007 14:30:54 -0000 1.180 +++ src/org/eclipse/jface/text/TextViewer.java 19 Jul 2007 14:41:21 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Cagatay Calli - https://bugs.eclipse.org/bugs/show_bug.cgi?id=29692 *******************************************************************************/ package org.eclipse.jface.text; @@ -74,6 +75,10 @@ import org.eclipse.jface.text.hyperlink.IHyperlinkPresenter; import org.eclipse.jface.text.projection.ChildDocument; import org.eclipse.jface.text.projection.ChildDocumentManager; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.AnnotationModel; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.SourceViewer; /** @@ -754,7 +759,7 @@ /** * This viewer's find/replace target. */ - class FindReplaceTarget implements IFindReplaceTarget, IFindReplaceTargetExtension, IFindReplaceTargetExtension3 { + class FindReplaceTarget implements IFindReplaceTarget, IFindReplaceTargetExtension, IFindReplaceTargetExtension3, IFindReplaceTargetExtension4 { /** The range for this target. */ private FindReplaceRange fRange; @@ -997,7 +1002,47 @@ } } } + + /* + * @see IFindReplaceTargetExtension4#highlightAll(String, boolean, boolean, boolean) + * @since 3.4 + */ + public int highlightAll(String findString, boolean caseSensitive, + boolean wholeWord, boolean regExSearch) { + int matchCount; + + if (fRange != null) { + IRegion range= fRange.getRange(); + matchCount = TextViewer.this.highlightAllInRange(findString, caseSensitive, wholeWord, range.getOffset(), range.getLength(), regExSearch); + } else { + matchCount = TextViewer.this.highlightAll(findString, caseSensitive, wholeWord, regExSearch); + } + + return matchCount; + } + + /* + * @see IFindReplaceTargetExtension4#clearHighlights() + * @since 3.4 + */ + public void clearHighlights() { + // TODO This removes annotations if target supports it. Remove highlights from non-supporting targets. + if(TextViewer.this instanceof SourceViewer){ + AnnotationModel model = (AnnotationModel) ((SourceViewer) TextViewer.this).getAnnotationModel(); + Iterator iter = model.getAnnotationIterator(); + while(iter.hasNext()){ + Annotation currentAnnotation = (Annotation) iter.next(); + if(currentAnnotation.getType().equals("org.eclipse.search.results")){ //$NON-NLS-1$ + model.removeAnnotation(currentAnnotation); + } + } + } + } + } + + + /** @@ -5331,5 +5376,145 @@ public void setTabsToSpacesConverter(IAutoEditStrategy converter) { fTabsToSpacesConverter= converter; } + + /** + * Returns whether this TextViewer is annotatible. + * @return whether this TextViewer is annotatible + * @since 3.4 + */ + public boolean isAnnotatible(){ + return (this instanceof ISourceViewer); + } + + /** + * Adheres to the contract of {@link org.eclipse.jface.text.IFindReplaceTargetExtension4#highlightAll(String, boolean, boolean, boolean)}. + * + * @param findString the find string specification + * @param caseSensitive true if case sensitive, false otherwise + * @param wholeWord true if matches must be whole words, false otherwise + * @param regExSearch true if findString is a regular expression, false otherwise + * @return number of occurrences in range + * @since 3.4 + */ + protected int highlightAll(String findString, boolean caseSensitive, + boolean wholeWord, boolean regExSearch) { + int matchCounter = 0; + + try { + + int widgetOffset= 0; + int firstMatch = -1; + IRegion matchRegion; + FindReplaceDocumentAdapter adapter= getFindReplaceDocumentAdapter(); + + while((matchRegion= adapter.find(widgetOffset, findString, true, caseSensitive, wholeWord, regExSearch))!=null){ + int widgetPos= matchRegion.getOffset(); + int length= matchRegion.getLength(); + + if(matchCounter == 0) firstMatch = widgetPos; + else { + if(firstMatch == widgetPos) + return matchCounter; + } + + if(isAnnotatible()){ + AnnotationModel model = (AnnotationModel) ((ISourceViewer) TextViewer.this).getAnnotationModel(); + Annotation findAnnotation = new Annotation("org.eclipse.search.results",true,adapter.subSequence(widgetPos, widgetPos+length-1).toString()); //$NON-NLS-1$ + Position position = new Position(widgetPos,length); + model.addAnnotation(findAnnotation, position); + } + else { + // TODO Add raw highlighing for targets that don't support annotations +// Color highlight = new Color(getTextWidget().getDisplay(),255,0,0); +// setTextColor(highlight, widgetPos, length, false); + return 0; + } + + matchCounter++; + widgetOffset = widgetPos + length; + } + + } catch (BadLocationException x) { + if (TRACE_ERRORS) + System.out.println(JFaceTextMessages.getString("TextViewer.error.bad_location.findAndSelect")); //$NON-NLS-1$ + } + + return matchCounter; + + } + + /** + * Adheres to the contract of {@link org.eclipse.jface.text.IFindReplaceTargetExtension4#highlightAll(String, boolean, boolean, boolean)}. + * + * @param findString the find string specification + * @param caseSensitive true if case sensitive, false otherwise + * @param wholeWord true if matches must be whole words, false otherwise + * @param rangeOffset the search scope offset + * @param rangeLength the search scope length + * @param regExSearch true if findString is a regular expression, false otherwise + * @return number of occurrences in range + * @since 3.4 + */ + protected int highlightAllInRange(String findString, boolean caseSensitive, + boolean wholeWord, int rangeOffset, int rangeLength, boolean regExSearch){ + int matchCounter = 0; + + try { + + int firstMatch = -1; + int widgetOffset= modelOffset2WidgetOffset(rangeOffset); + if (widgetOffset == -1) + return -1; + + FindReplaceDocumentAdapter adapter= getFindReplaceDocumentAdapter(); + IRegion matchRegion; + int widgetPos= -1; + int length= 0; + while((matchRegion= adapter.find(widgetOffset, findString, true, caseSensitive, wholeWord, regExSearch)) != null) { + widgetPos= matchRegion.getOffset(); + length= matchRegion.getLength(); + + if(matchCounter == 0) firstMatch = widgetPos; + else { + if(firstMatch == widgetPos) + return matchCounter; + } + + int modelPos= widgetPos == -1 ? -1 : widgetOffset2ModelOffset(widgetPos); + + if (widgetPos != -1 && (modelPos < rangeOffset || modelPos + length > rangeOffset + rangeLength)) + widgetPos= -1; + + if (widgetPos > -1) { + + if(isAnnotatible()){ + AnnotationModel model = (AnnotationModel) ((ISourceViewer) TextViewer.this).getAnnotationModel(); + Annotation findAnnotation = new Annotation("org.eclipse.search.results",true,adapter.subSequence(widgetPos, widgetPos+length-1).toString()); //$NON-NLS-1$ + Position position = new Position(widgetPos,length); + model.addAnnotation(findAnnotation, position); + } + else { + // TODO Add raw highlighing for targets that don't support annotations +// Color highlight = new Color(getTextWidget().getDisplay(),255,0,0); +// setTextColor(highlight, widgetPos, length, false); + return 0; + } + + matchCounter++; + + widgetOffset = widgetPos + length; + } + + else break; + } + + + } catch (BadLocationException x) { + if (TRACE_ERRORS) + System.out.println(JFaceTextMessages.getString("TextViewer.error.bad_location.findAndSelect")); //$NON-NLS-1$ + } + + return matchCounter; + } } Index: src/org/eclipse/jface/text/IFindReplaceTargetExtension4.java =================================================================== RCS file: src/org/eclipse/jface/text/IFindReplaceTargetExtension4.java diff -N src/org/eclipse/jface/text/IFindReplaceTargetExtension4.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/jface/text/IFindReplaceTargetExtension4.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Cagatay Calli - initial API and implementation (https://bugs.eclipse.org/bugs/show_bug.cgi?id=29692) + *******************************************************************************/ + +package org.eclipse.jface.text; + +/** + * Extension interface for {@link org.eclipse.jface.text.IFindReplaceTarget}. + *

+ * Extends the find replace target to add "highlight all" functionality. + * + * @since 3.4 + */ +public interface IFindReplaceTargetExtension4 { + /** + * Finds and highlights all occurrences of the user's findString. + * Returns the number of all occurrences. + * + * @param findString the string to search for + * @param caseSensitive should the search be case sensitive + * @param wholeWord does the search string represent a complete word + * @param regExSearch if true findString represents a regular expression + * @return number of occurrences + * + * @since 3.4 + */ + int highlightAll(String findString, boolean caseSensitive, boolean wholeWord, boolean regExSearch); + + /** + * Clears all highlights and corresponding annotations. + * + * @since 3.4 + */ + void clearHighlights(); +} #P org.eclipse.ui.workbench.texteditor Index: src/org/eclipse/ui/texteditor/FindReplaceDialog.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/FindReplaceDialog.java,v retrieving revision 1.71 diff -u -r1.71 FindReplaceDialog.java --- src/org/eclipse/ui/texteditor/FindReplaceDialog.java 15 Jul 2007 14:32:09 -0000 1.71 +++ src/org/eclipse/ui/texteditor/FindReplaceDialog.java 19 Jul 2007 14:41:26 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Cagatay Calli - https://bugs.eclipse.org/bugs/show_bug.cgi?id=29692 *******************************************************************************/ package org.eclipse.ui.texteditor; @@ -16,6 +17,19 @@ import java.util.Set; import java.util.regex.PatternSyntaxException; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.fieldassist.ComboContentAdapter; +import org.eclipse.jface.fieldassist.FieldDecoration; +import org.eclipse.jface.fieldassist.FieldDecorationRegistry; +import org.eclipse.jface.resource.JFaceColors; +import org.eclipse.jface.text.IFindReplaceTarget; +import org.eclipse.jface.text.IFindReplaceTargetExtension; +import org.eclipse.jface.text.IFindReplaceTargetExtension3; +import org.eclipse.jface.text.IFindReplaceTargetExtension4; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.TextUtilities; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.events.ModifyEvent; @@ -36,21 +50,6 @@ import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; - -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.jface.dialogs.IDialogSettings; -import org.eclipse.jface.fieldassist.ComboContentAdapter; -import org.eclipse.jface.fieldassist.FieldDecoration; -import org.eclipse.jface.fieldassist.FieldDecorationRegistry; -import org.eclipse.jface.resource.JFaceColors; - -import org.eclipse.jface.text.IFindReplaceTarget; -import org.eclipse.jface.text.IFindReplaceTargetExtension; -import org.eclipse.jface.text.IFindReplaceTargetExtension3; -import org.eclipse.jface.text.IRegion; -import org.eclipse.jface.text.Region; -import org.eclipse.jface.text.TextUtilities; - import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchWindow; @@ -203,6 +202,12 @@ */ private boolean fGiveFocusToFindField= true; + /** + * "Highlight All" toggle button + * @since 3.4 + */ + private Button fHighlightAllButton; + /** * Creates a new dialog with the given shell as parent. @@ -341,11 +346,38 @@ // Make the all the buttons the same size as the Remove Selection button. fReplaceAllButton.setEnabled(isEditable()); + + fHighlightAllButton = new Button(panel,SWT.TOGGLE); + fHighlightAllButton.setText("Highlight All"); //$NON-NLS-1$ + fHighlightAllButton.setSelection(false); + fHighlightAllButton.addSelectionListener(new SelectionAdapter(){ + public void widgetSelected(SelectionEvent e){ + if(fHighlightAllButton.getSelection()){ + performHighlightAll(); + updateFindHistory(); + } + else { + clearHighlights(); + } + } + }); + setGridData(fHighlightAllButton, SWT.FILL, true, SWT.FILL, false); return panel; } /** + * Clears all highlights and corresponding annotations. + * + * @since 3.4 + */ + private void clearHighlights() { + if(fTarget instanceof IFindReplaceTargetExtension4){ + ((IFindReplaceTargetExtension4) fTarget).clearHighlights(); + } + } + + /** * Creates the options configuration section of the find replace dialog. * * @param parent the parent composite @@ -947,7 +979,9 @@ * Removes focus changed listener from browser and stores settings for re-open. */ private void handleDialogClose() { - + // clear highlights + clearHighlights(); + // remove listeners if (okToUse(fFindField)) { fFindField.removeModifyListener(fFindModifyListener); @@ -1827,4 +1861,38 @@ settings.put(sectionName, names); } + + /** + * Highlights all occurrences of the user's findString + * in the text of the target. + * + * @since 3.4 + */ + private void performHighlightAll() { + + String findString= getFindString(); + int matchCount; + + if(!(fTarget instanceof IFindReplaceTargetExtension4)) return; + + if (findString != null && findString.length() > 0) { + + try { + matchCount= ((IFindReplaceTargetExtension4) fTarget).highlightAll(findString, isCaseSensitiveSearch(), isWholeWordSearch(), isRegExSearchAvailableAndChecked()); + + if (matchCount != 0) { + String msg= " match(es) are highlighted"; //$NON-NLS-1$ + msg= String.valueOf(matchCount) + msg; + statusMessage(msg); + } else { + statusMessage(EditorMessages.FindReplace_Status_noMatch_label); + } + } catch (PatternSyntaxException ex) { + statusError(ex.getLocalizedMessage()); + } catch (IllegalStateException ex) { + // we don't keep state in this dialog + } + } + writeSelection(); + } } Index: src/org/eclipse/ui/texteditor/FindReplaceTarget.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/FindReplaceTarget.java,v retrieving revision 1.12 diff -u -r1.12 FindReplaceTarget.java --- src/org/eclipse/ui/texteditor/FindReplaceTarget.java 20 Jun 2007 14:30:51 -0000 1.12 +++ src/org/eclipse/ui/texteditor/FindReplaceTarget.java 19 Jul 2007 14:41:26 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Cagatay Calli - https://bugs.eclipse.org/bugs/show_bug.cgi?id=29692 *******************************************************************************/ package org.eclipse.ui.texteditor; @@ -16,6 +17,7 @@ import org.eclipse.jface.text.IFindReplaceTarget; import org.eclipse.jface.text.IFindReplaceTargetExtension; import org.eclipse.jface.text.IFindReplaceTargetExtension3; +import org.eclipse.jface.text.IFindReplaceTargetExtension4; import org.eclipse.jface.text.IRegion; @@ -23,7 +25,7 @@ * Internal find/replace target wrapping the editor's source viewer. * @since 2.1 */ -class FindReplaceTarget implements IFindReplaceTarget, IFindReplaceTargetExtension, IFindReplaceTargetExtension2, IFindReplaceTargetExtension3 { +class FindReplaceTarget implements IFindReplaceTarget, IFindReplaceTargetExtension, IFindReplaceTargetExtension2, IFindReplaceTargetExtension3, IFindReplaceTargetExtension4 { /** The editor */ private AbstractTextEditor fEditor; @@ -219,4 +221,19 @@ public boolean validateTargetState() { return fEditor.validateEditorInputState(); } + + /* + * @see org.eclipse.jface.text.IFindReplaceTargetExtension4#highlightAll(String, boolean, boolean, boolean) + */ + public int highlightAll(String findString, boolean caseSensitive, + boolean wholeWord, boolean regExSearch) { + return ((IFindReplaceTargetExtension4) fTarget).highlightAll(findString, caseSensitive, wholeWord, regExSearch); + } + + /* + * @see org.eclipse.jface.text.IFindReplaceTargetExtension4#clearHighlights() + */ + public void clearHighlights() { + ((IFindReplaceTargetExtension4) fTarget).clearHighlights(); + } }