### Eclipse Workspace Patch 1.0 #P org.eclipse.ant.ui Index: plugin.xml =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ant.ui/plugin.xml,v retrieving revision 1.145 diff -u -r1.145 plugin.xml --- plugin.xml 19 Mar 2007 05:20:35 -0000 1.145 +++ plugin.xml 11 Jun 2007 11:59:27 -0000 @@ -122,7 +122,13 @@ name="%toggleMarkOccurrences.label" description="%toggleMarkOccurrences.description" categoryId="org.eclipse.jdt.ui.category.source" - id="org.eclipse.ant.ui.toggleMarkOccurrences" /> + id="org.eclipse.ant.ui.toggleMarkOccurrences" /> + + + schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" /> + @@ -829,4 +840,5 @@ - \ No newline at end of file + + Index: Ant Editor/org/eclipse/ant/internal/ui/editor/text/AntInformationProvider.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ant.ui/Ant Editor/org/eclipse/ant/internal/ui/editor/text/AntInformationProvider.java,v retrieving revision 1.3 diff -u -r1.3 AntInformationProvider.java --- Ant Editor/org/eclipse/ant/internal/ui/editor/text/AntInformationProvider.java 23 Feb 2005 17:31:01 -0000 1.3 +++ Ant Editor/org/eclipse/ant/internal/ui/editor/text/AntInformationProvider.java 11 Jun 2007 11:59:34 -0000 @@ -14,8 +14,9 @@ import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.information.IInformationProvider; +import org.eclipse.jface.text.information.IInformationProviderExtension; -public class AntInformationProvider implements IInformationProvider { +public class AntInformationProvider implements IInformationProvider, IInformationProviderExtension { XMLTextHover fTextHover; @@ -35,4 +36,10 @@ public String getInformation(ITextViewer textViewer, IRegion subject) { return fTextHover.getHoverInfo(textViewer, subject); } + /* (non-Javadoc) + * @see org.eclipse.jface.text.information.IInformationProviderExtension#getInformation2(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion) + */ + public Object getInformation2(ITextViewer textViewer, IRegion subject) { + return fTextHover.getInformation2(textViewer, subject); + } } Index: Ant Editor/org/eclipse/ant/internal/ui/editor/text/XMLTextHover.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ant.ui/Ant Editor/org/eclipse/ant/internal/ui/editor/text/XMLTextHover.java,v retrieving revision 1.38 diff -u -r1.38 XMLTextHover.java --- Ant Editor/org/eclipse/ant/internal/ui/editor/text/XMLTextHover.java 24 Apr 2007 04:52:51 -0000 1.38 +++ Ant Editor/org/eclipse/ant/internal/ui/editor/text/XMLTextHover.java 11 Jun 2007 11:59:34 -0000 @@ -42,6 +42,7 @@ import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.Position; import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.information.IInformationProviderExtension; import org.eclipse.jface.text.information.IInformationProviderExtension2; import org.eclipse.jface.text.source.Annotation; import org.eclipse.jface.text.source.IAnnotationModel; @@ -51,7 +52,7 @@ import org.eclipse.ui.editors.text.EditorsUI; -public class XMLTextHover implements ITextHover, ITextHoverExtension, IInformationProviderExtension2 { +public class XMLTextHover implements ITextHover, ITextHoverExtension, IInformationProviderExtension, IInformationProviderExtension2 { private AntEditor fEditor; @@ -352,6 +353,21 @@ return null; } + /* (non-Javadoc) + * @see org.eclipse.jface.text.information.IInformationProviderExtension#getInformation2(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion) + */ + public Object getInformation2(ITextViewer textViewer, IRegion subject) { + AntModel model= fEditor.getAntModel(); + + if (model == null) { + return null; + } + + AntElementNode node= model.getNode(subject.getOffset(), false); + + return node; + } + /* * @see org.eclipse.jface.text.information.IInformationProviderExtension2#getInformationPresenterControlCreator() * @since 3.3 Index: Ant Editor/org/eclipse/ant/internal/ui/editor/outline/AntEditorContentOutlinePage.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ant.ui/Ant Editor/org/eclipse/ant/internal/ui/editor/outline/AntEditorContentOutlinePage.java,v retrieving revision 1.52 diff -u -r1.52 AntEditorContentOutlinePage.java --- Ant Editor/org/eclipse/ant/internal/ui/editor/outline/AntEditorContentOutlinePage.java 20 Feb 2007 03:46:28 -0000 1.52 +++ Ant Editor/org/eclipse/ant/internal/ui/editor/outline/AntEditorContentOutlinePage.java 11 Jun 2007 11:59:34 -0000 @@ -67,7 +67,7 @@ /** * Content outline page for the Ant Editor. */ -public class AntEditorContentOutlinePage extends ContentOutlinePage implements IShowInSource, IAdaptable { +public class AntEditorContentOutlinePage extends ContentOutlinePage implements ISortableContentOutlinePage, IShowInSource, IAdaptable { private static final int EXPAND_TO_LEVEL= 2; @@ -126,20 +126,6 @@ } } - private class AntOutlineComparator extends ViewerComparator { - /* (non-Javadoc) - * @see org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) - */ - public int compare(Viewer viewer, Object e1, Object e2) { - if (!(e1 instanceof AntElementNode && e2 instanceof AntElementNode)) { - return super.compare(viewer, e1, e2); - } - String name1= ((AntElementNode) e1).getLabel(); - String name2= ((AntElementNode) e2).getLabel(); - return getComparator().compare(name1, name2); - } - } - /** * Sets whether internal targets should be filtered out of the outline. * @@ -510,4 +496,11 @@ } } } + + /* (non-Javadoc) + * @see org.eclipse.ant.internal.ui.editor.outline.ISortableContentOutlinePage#sort(boolean) + */ + public void sort(boolean sorting) { + setSort(sorting); + } } Index: Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditorMessages.properties =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ant.ui/Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditorMessages.properties,v retrieving revision 1.22 diff -u -r1.22 AntEditorMessages.properties --- Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditorMessages.properties 27 Mar 2006 19:08:01 -0000 1.22 +++ Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditorMessages.properties 11 Jun 2007 11:59:28 -0000 @@ -20,6 +20,11 @@ ContentFormat.image= ContentFormat.description=Format build file source +Outline.label=Quick Outline +Outline.tooltip=Quick Outline +Outline.image= +Outline.description=Quick Outline + AntEditorCompletionProcessor.Required___4=Required: AntEditorCompletionProcessor.28=No attribute completions available AntEditorCompletionProcessor.29=No task completions available Index: Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditorSourceViewerConfiguration.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ant.ui/Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditorSourceViewerConfiguration.java,v retrieving revision 1.34 diff -u -r1.34 AntEditorSourceViewerConfiguration.java --- Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditorSourceViewerConfiguration.java 16 Apr 2007 18:31:07 -0000 1.34 +++ Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditorSourceViewerConfiguration.java 11 Jun 2007 11:59:30 -0000 @@ -24,6 +24,7 @@ import org.eclipse.ant.internal.ui.ColorManager; import org.eclipse.ant.internal.ui.editor.formatter.XmlDocumentFormattingStrategy; import org.eclipse.ant.internal.ui.editor.formatter.XmlElementFormattingStrategy; +import org.eclipse.ant.internal.ui.editor.outline.QuickOutlinePopupDialog; import org.eclipse.ant.internal.ui.editor.text.AntDocumentSetupParticipant; import org.eclipse.ant.internal.ui.editor.text.AntEditorPartitionScanner; import org.eclipse.ant.internal.ui.editor.text.AntInformationProvider; @@ -32,8 +33,13 @@ import org.eclipse.ant.internal.ui.editor.text.XMLReconcilingStrategy; import org.eclipse.ant.internal.ui.editor.text.XMLTextHover; import org.eclipse.ant.internal.ui.preferences.AntEditorPreferenceConstants; +import org.eclipse.jdt.internal.ui.text.JavaElementProvider; +import org.eclipse.jdt.internal.ui.text.JavaOutlineInformationControl; +import org.eclipse.jdt.ui.actions.IJavaEditorActionDefinitionIds; +import org.eclipse.jdt.ui.text.IJavaPartitions; import org.eclipse.jface.internal.text.html.HTMLTextPresenter; import org.eclipse.jface.preference.PreferenceConverter; +import org.eclipse.jface.text.AbstractInformationControlManager; import org.eclipse.jface.text.DefaultInformationControl; import org.eclipse.jface.text.IAutoEditStrategy; import org.eclipse.jface.text.IDocument; @@ -308,4 +314,24 @@ targets.put("org.eclipse.ant.ui.buildFiles", fEditor); //$NON-NLS-1$ return targets; } + + public IInformationPresenter getOutlinePresenter(ISourceViewer sourceViewer) { + InformationPresenter presenter; + presenter= new InformationPresenter(new IInformationControlCreator() { + public IInformationControl createInformationControl(Shell parent) { + int shellStyle= SWT.RESIZE; + return new QuickOutlinePopupDialog(parent, shellStyle, fEditor, fEditor); + } + }); + presenter.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer)); + presenter.setAnchor(AbstractInformationControlManager.ANCHOR_GLOBAL); + IInformationProvider provider= new AntInformationProvider(new XMLTextHover(fEditor)); + presenter.setInformationProvider(provider, IDocument.DEFAULT_CONTENT_TYPE); + presenter.setInformationProvider(provider, AntEditorPartitionScanner.XML_CDATA); + presenter.setInformationProvider(provider, AntEditorPartitionScanner.XML_COMMENT); + presenter.setInformationProvider(provider, AntEditorPartitionScanner.XML_DTD); + presenter.setInformationProvider(provider, AntEditorPartitionScanner.XML_TAG); + presenter.setSizeConstraints(50, 20, true, false); + return presenter; + } } \ No newline at end of file Index: Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditor.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ant.ui/Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditor.java,v retrieving revision 1.109 diff -u -r1.109 AntEditor.java --- Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditor.java 20 Mar 2007 22:09:34 -0000 1.109 +++ Ant Editor/org/eclipse/ant/internal/ui/editor/AntEditor.java 11 Jun 2007 11:59:28 -0000 @@ -34,6 +34,10 @@ import org.eclipse.ant.internal.ui.editor.actions.RunToLineAdapter; import org.eclipse.ant.internal.ui.editor.actions.ToggleLineBreakpointAction; import org.eclipse.ant.internal.ui.editor.outline.AntEditorContentOutlinePage; +import org.eclipse.ant.internal.ui.editor.outline.AntOutlineComparator; +import org.eclipse.ant.internal.ui.editor.outline.IOutlineContentCreator; +import org.eclipse.ant.internal.ui.editor.outline.IOutlineSelectionHandler; +import org.eclipse.ant.internal.ui.editor.outline.ISortableContentOutlinePage; import org.eclipse.ant.internal.ui.editor.text.AntEditorDocumentProvider; import org.eclipse.ant.internal.ui.editor.text.AntFoldingStructureProvider; import org.eclipse.ant.internal.ui.editor.text.IReconcilingParticipant; @@ -41,7 +45,9 @@ import org.eclipse.ant.internal.ui.model.AntElementNode; import org.eclipse.ant.internal.ui.model.AntModel; import org.eclipse.ant.internal.ui.model.AntModelChangeEvent; +import org.eclipse.ant.internal.ui.model.AntModelContentProvider; import org.eclipse.ant.internal.ui.model.AntModelCore; +import org.eclipse.ant.internal.ui.model.AntModelLabelProvider; import org.eclipse.ant.internal.ui.model.AntProjectNode; import org.eclipse.ant.internal.ui.model.IAntModelListener; import org.eclipse.ant.internal.ui.preferences.AntEditorPreferenceConstants; @@ -74,6 +80,7 @@ import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.information.IInformationPresenter; import org.eclipse.jface.text.link.LinkedModeModel; import org.eclipse.jface.text.source.Annotation; import org.eclipse.jface.text.source.IAnnotationModel; @@ -86,12 +93,15 @@ import org.eclipse.jface.text.source.projection.ProjectionSupport; import org.eclipse.jface.text.source.projection.ProjectionViewer; import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.IPostSelectionProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.ShellAdapter; import org.eclipse.swt.events.ShellEvent; @@ -121,7 +131,7 @@ /** * The actual editor implementation for Eclipse's Ant integration. */ -public class AntEditor extends TextEditor implements IReconcilingParticipant, IProjectionListener { +public class AntEditor extends TextEditor implements IReconcilingParticipant, IProjectionListener, IOutlineContentCreator, IOutlineSelectionHandler { /** * Updates the Ant outline page selection and this editor's range indicator. * @@ -189,13 +199,42 @@ } } - class StatusLineSourceViewer extends ProjectionViewer{ + class AntSourceViewer extends ProjectionViewer { + /** + * Text operation code for requesting the outline for the current input. + */ + public static final int SHOW_OUTLINE= 51; - public StatusLineSourceViewer(Composite composite, IVerticalRuler verticalRuler, IOverviewRuler overviewRuler, int styles) { + private IInformationPresenter fOutlinePresenter; + + public AntSourceViewer(Composite composite, IVerticalRuler verticalRuler, IOverviewRuler overviewRuler, int styles) { super(composite, verticalRuler, overviewRuler, isOverviewRulerVisible(), styles); } /* (non-Javadoc) + * @see org.eclipse.jface.text.source.SourceViewer#configure(org.eclipse.jface.text.source.SourceViewerConfiguration) + */ + public void configure(SourceViewerConfiguration configuration) { + super.configure(configuration); + if (configuration instanceof AntEditorSourceViewerConfiguration) { + AntEditorSourceViewerConfiguration antSourceViewerConfiguration= (AntEditorSourceViewerConfiguration)configuration; + fOutlinePresenter= antSourceViewerConfiguration.getOutlinePresenter(this); + if (fOutlinePresenter != null) + fOutlinePresenter.install(this); + } + } + + /* + * @see ITextOperationTarget#canDoOperation(int) + */ + public boolean canDoOperation(int operation) { + if (operation == SHOW_OUTLINE) + return fOutlinePresenter != null; + + return super.canDoOperation(operation); + } + + /* (non-Javadoc) * @see org.eclipse.jface.text.ITextOperationTarget#doOperation(int) */ public void doOperation(int operation) { @@ -208,6 +247,10 @@ String msg= fContentAssistant.showPossibleCompletions(); setStatusLineErrorMessage(msg); return; + case SHOW_OUTLINE: + if (fOutlinePresenter != null) + fOutlinePresenter.showInformation(); + return; } super.doOperation(operation); @@ -522,6 +565,12 @@ ResourceBundle bundle = ResourceBundle.getBundle("org.eclipse.ant.internal.ui.editor.AntEditorMessages"); //$NON-NLS-1$ IAction action = new ContentAssistAction(bundle, "ContentAssistProposal.", this); //$NON-NLS-1$ + action= new TextOperationAction(bundle,"ShowOutline.", this, AntSourceViewer.SHOW_OUTLINE, true); //$NON-NLS-1$ +// action.setActionDefinitionId(IJavaEditorActionDefinitionIds.SHOW_OUTLINE); + action.setActionDefinitionId("org.eclipse.ant.ui.edit.text.show.outline"); + setAction(IJavaEditorActionDefinitionIds.SHOW_OUTLINE, action); +// PlatformUI.getWorkbench().getHelpSystem().setHelp(action, IJavaHelpContextIds.SHOW_OUTLINE_ACTION); + // This action definition is associated with the accelerator Ctrl+Space action.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS); setAction("ContentAssistProposal", action); //$NON-NLS-1$ @@ -697,7 +746,7 @@ if (AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH.equals(property)) { Object value= event.getNewValue(); - StatusLineSourceViewer viewer= (StatusLineSourceViewer) getSourceViewer(); + AntSourceViewer viewer= (AntSourceViewer) getSourceViewer(); int newValue= -1; if (value instanceof Integer) { newValue=((Integer) value).intValue(); @@ -777,7 +826,7 @@ */ protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) { fOverviewRuler= createOverviewRuler(getSharedColors()); - ISourceViewer viewer= new StatusLineSourceViewer(parent, ruler, getOverviewRuler(), styles); + ISourceViewer viewer= new AntSourceViewer(parent, ruler, getOverviewRuler(), styles); //ensure decoration support has been created and configured. getSourceViewerDecorationSupport(viewer); return viewer; @@ -1376,4 +1425,70 @@ } } } + + + /* (non-Javadoc) + * @see org.eclipse.ant.internal.ui.editor.outline.IOutlineContentCreator#createDefaultOutlineComparator() + */ + public ViewerComparator createDefaultOutlineComparator() { + return null; + } + + + /* (non-Javadoc) + * @see org.eclipse.ant.internal.ui.editor.outline.IOutlineContentCreator#createOutlineComparator() + */ + public ViewerComparator createOutlineComparator() { + return new AntOutlineComparator(); + } + + + /* (non-Javadoc) + * @see org.eclipse.ant.internal.ui.editor.outline.IOutlineContentCreator#createOutlineContentProvider() + */ + public ITreeContentProvider createOutlineContentProvider() { + return new AntModelContentProvider(); + } + + + /* (non-Javadoc) + * @see org.eclipse.ant.internal.ui.editor.outline.IOutlineContentCreator#createOutlineLabelProvider() + */ + public ILabelProvider createOutlineLabelProvider() { + return new AntModelLabelProvider(); + } + + + /* (non-Javadoc) + * @see org.eclipse.ant.internal.ui.editor.outline.IOutlineContentCreator#getOutlineInput() + */ + public Object getOutlineInput() { + return fAntModel; + } + + + /* (non-Javadoc) + * @see org.eclipse.ant.internal.ui.editor.outline.IOutlineSelectionHandler#getContentOutline() + */ + public ISortableContentOutlinePage getContentOutline() { + return new AntEditorContentOutlinePage(AntModelCore.getDefault(), this); + } + + + /* (non-Javadoc) + * @see org.eclipse.ant.internal.ui.editor.outline.IOutlineSelectionHandler#updateSelection(org.eclipse.jface.viewers.SelectionChangedEvent) + */ + public void updateSelection(SelectionChangedEvent e) { + // TODO Auto-generated method stub + + } + + + /* (non-Javadoc) + * @see org.eclipse.ant.internal.ui.editor.outline.IOutlineSelectionHandler#updateSelection(java.lang.Object) + */ + public void updateSelection(Object object) { + // TODO Auto-generated method stub + + } } \ No newline at end of file Index: Ant Editor/org/eclipse/ant/internal/ui/editor/outline/ISortableContentOutlinePage.java =================================================================== RCS file: Ant Editor/org/eclipse/ant/internal/ui/editor/outline/ISortableContentOutlinePage.java diff -N Ant Editor/org/eclipse/ant/internal/ui/editor/outline/ISortableContentOutlinePage.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Ant Editor/org/eclipse/ant/internal/ui/editor/outline/ISortableContentOutlinePage.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2004, 2006 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ant.internal.ui.editor.outline; + +import org.eclipse.ui.views.contentoutline.IContentOutlinePage; + +/** + * IConentOutlinePage with externally enabled/disabled element sorting + */ +public interface ISortableContentOutlinePage extends IContentOutlinePage { + /** + * Turns sorting on or off + * @param sorting - boolean value indicating if sorting should be enabled + */ + public void sort(boolean sorting); + +} Index: Ant Editor/org/eclipse/ant/internal/ui/editor/outline/SortAction.java =================================================================== RCS file: Ant Editor/org/eclipse/ant/internal/ui/editor/outline/SortAction.java diff -N Ant Editor/org/eclipse/ant/internal/ui/editor/outline/SortAction.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Ant Editor/org/eclipse/ant/internal/ui/editor/outline/SortAction.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2006 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ant.internal.ui.editor.outline; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.ViewerComparator; + +public class SortAction extends Action { + + private boolean fSorted; + + private StructuredViewer fViewer; + + private ViewerComparator fComparator; + + private ViewerComparator fDefaultComparator; + + /** + * @param viewer + * @param tooltipText + * @param sorter + * @param defaultSorter + * @param listener + * @param useMiniImage + */ + public SortAction(StructuredViewer viewer, String tooltipText, + ViewerComparator sorter, ViewerComparator defaultSorter, + IPropertyChangeListener listener) { + + super(tooltipText, IAction.AS_CHECK_BOX); + // Set the tooltip + setToolTipText(tooltipText); + // Set the image +// setImageDescriptor(PDEPluginImages.DESC_ALPHAB_SORT_CO); + // Set the default comparator + fDefaultComparator = defaultSorter; + // Set the viewer + fViewer = viewer; + // Set the comparator + // If one was not specified, use the default + if (sorter == null) { + fComparator = new ViewerComparator(); + } else { + fComparator = sorter; + } + // Determine if the viewer is already sorted + // Note: Most likely the default comparator is null + if (viewer.getComparator() == fDefaultComparator) { + fSorted = false; + } else { + fSorted = true; + } + // Set the status of this action depending on whether it is sorted or + // not + setChecked(fSorted); + // If a listener was specified, use it + if (listener != null) { + addListenerObject(listener); + } + } + + /* (non-Javadoc) + * @see org.eclipse.jface.action.Action#run() + */ + public void run() { + // Toggle sorting on/off + if (fSorted) { + // Sorting is on + // Turn it off + fViewer.setComparator(fDefaultComparator); + fSorted = false; + } else { + // Sorting is off + // Turn it on + fViewer.setComparator(fComparator); + fSorted = true; + } + notifyResult(true); + } + +} Index: Ant Editor/org/eclipse/ant/internal/ui/editor/outline/QuickOutlinePopupDialog.java =================================================================== RCS file: Ant Editor/org/eclipse/ant/internal/ui/editor/outline/QuickOutlinePopupDialog.java diff -N Ant Editor/org/eclipse/ant/internal/ui/editor/outline/QuickOutlinePopupDialog.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Ant Editor/org/eclipse/ant/internal/ui/editor/outline/QuickOutlinePopupDialog.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,617 @@ +/******************************************************************************* + * Copyright (c) 2006 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ant.internal.ui.editor.outline; + +import org.eclipse.ant.internal.ui.editor.utils.StringMatcher; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.PopupDialog; +import org.eclipse.jface.text.IInformationControl; +import org.eclipse.jface.text.IInformationControlExtension; +import org.eclipse.jface.text.IInformationControlExtension2; +import org.eclipse.jface.viewers.AbstractTreeViewer; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.FontMetrics; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; + +/** + * AbstractInfoPopupDialog + * + */ +public class QuickOutlinePopupDialog extends PopupDialog implements + IInformationControl, IInformationControlExtension, + IInformationControlExtension2, DisposeListener { + + private TreeViewer fTreeViewer; + + private IOutlineContentCreator fOutlineContentCreator; + + private IOutlineSelectionHandler fOutlineSelectionHandler; + + private Text fFilterText; + + private StringMatcher fStringMatcher; + + private QuickOutlineNamePatternFilter fNamePatternFilter; + + private SortAction fSortAction; + + private ITreeContentProvider fTreeContentProvider; + + private ILabelProvider fTreeLabelProvider; + + private ViewerComparator fTreeViewerComparator; + + private ViewerComparator fTreeViewerDefaultComparator; + + public QuickOutlinePopupDialog(Shell parent, int shellStyle, + IOutlineContentCreator creator, + IOutlineSelectionHandler handler) { + super(parent, shellStyle, true, true, true, true, null, null); + // Set outline creator + fOutlineContentCreator = creator; + // Set outline handler + fOutlineSelectionHandler = handler; + // Initialize the other fields + initialize(); + // Create all controls early to preserve the life cycle of the original + // implementation. + create(); + } + + /** + * + */ + private void initialize() { + setInfoText("Press \'Esc\' to exit the dialog."); + + fFilterText = null; + fTreeViewer = null; + fStringMatcher = null; + fNamePatternFilter = null; + fSortAction = null; + fTreeContentProvider = null; + fTreeLabelProvider = null; + fTreeViewerComparator = null; + fTreeViewerDefaultComparator = null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.PopupDialog#createDialogArea(org.eclipse.swt.widgets.Composite) + */ + protected Control createDialogArea(Composite parent) { + // Applies only to dialog body - not title. See createTitleControl + // Create an empty dialog area, if the source page is not defined + if ((fOutlineContentCreator == null) || + (fOutlineSelectionHandler == null)) { + return super.createDialogArea(parent); + } + // Create the tree viewer + createUIWidgetTreeViewer(parent); + // Add listeners to the tree viewer + createUIListenersTreeViewer(); + // Create the actions + createUIActions(); + // Add a dispose listner + addDisposeListener(this); + // Return the tree + return fTreeViewer.getControl(); + } + + /** + * + */ + private void createUIActions() { + // Add sort action to dialog menu + fSortAction = new SortAction(fTreeViewer, + "Sort", + fTreeViewerComparator, fTreeViewerDefaultComparator, null); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.PopupDialog#fillDialogMenu(org.eclipse.jface.action.IMenuManager) + */ + protected void fillDialogMenu(IMenuManager dialogMenu) { + // Add the sort action + dialogMenu.add(fSortAction); + // Separator + dialogMenu.add(new Separator()); + // Add the default actions + super.fillDialogMenu(dialogMenu); + } + + /** + * @param parent + */ + private void createUIWidgetTreeViewer(Composite parent) { + + // NOTE: Instructions to implement for PDE form pages: + // Need to call PDEFormEditor.getFormOutline() + // Specify PDE form editor as input + // Need to adjust commandId="org.eclipse.pde.ui.quickOutline" + // scope: contextId="org.eclipse.ui.textEditorScope" + // SEE org.eclipse.ui.contexts.window + // TODO: MP: QO: LOW: Implement bi-directional support between form and source page for manifest + + int style = SWT.H_SCROLL | SWT.V_SCROLL; + // Create the tree + Tree widget = new Tree(parent, style); + // Configure the layout + GridData data = new GridData(GridData.FILL_BOTH); + data.heightHint = widget.getItemHeight() * 12; + widget.setLayoutData(data); + // Create the tree viewer + fTreeViewer = new TreeViewer(widget); + // Add the name pattern filter + fNamePatternFilter = new QuickOutlineNamePatternFilter(); + fTreeViewer.addFilter(fNamePatternFilter); + // Set the content provider + fTreeContentProvider = fOutlineContentCreator.createOutlineContentProvider(); + fTreeViewer.setContentProvider(fTreeContentProvider); + // Set the label provider + fTreeLabelProvider = fOutlineContentCreator.createOutlineLabelProvider(); + fTreeViewer.setLabelProvider(fTreeLabelProvider); + // Create the outline sorter (to be set on the sort action) + fTreeViewerComparator = fOutlineContentCreator.createOutlineComparator(); + // Set the comparator to null (sort action will be disabled initially + // because of this) + // Create the default outline sorter (Most like this will just return + // null to indicate sorting disabled + fTreeViewerDefaultComparator = + fOutlineContentCreator.createDefaultOutlineComparator(); + fTreeViewer.setComparator(fTreeViewerDefaultComparator); + fTreeViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS); + fTreeViewer.setUseHashlookup(true); + fTreeViewer.setInput(fOutlineContentCreator.getOutlineInput()); + } + + /** + * + */ + private void createUIListenersTreeViewer() { + // Get the underlying tree widget + final Tree tree = fTreeViewer.getTree(); + // Handle key events + tree.addKeyListener(new KeyListener() { + public void keyPressed(KeyEvent e) { + if (e.character == 0x1B) { + // Dispose on ESC key press + dispose(); + } + } + public void keyReleased(KeyEvent e) { + // NO-OP + } + }); + // Handle mouse clicks + tree.addMouseListener(new MouseAdapter() { + public void mouseUp(MouseEvent e) { + handleTreeViewerMouseUp(tree, e); + } + }); + // Handle mouse move events + tree.addMouseMoveListener(new QuickOutlineMouseMoveListener(fTreeViewer)); + // Handle widget selection events + tree.addSelectionListener(new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + // NO-OP + } + public void widgetDefaultSelected(SelectionEvent e) { + gotoSelectedElement(); + } + }); + } + + /** + * @param tree + * @param e + */ + private void handleTreeViewerMouseUp(final Tree tree, MouseEvent e) { + // Ensure a selection was made, the first mouse button was + // used and the event happened in the tree + if ((tree.getSelectionCount() < 1) || + (e.button != 1) || + (tree.equals(e.getSource()) == false)) { + return; + } + // Selection is made in the selection changed listener + Object object = tree.getItem(new Point(e.x, e.y)); + TreeItem selection = tree.getSelection()[0]; + if (selection.equals(object)) { + gotoSelectedElement(); + } + } + + /** + * @return + */ + private Object getSelectedElement() { + if (fTreeViewer == null) { + return null; + } + return ((IStructuredSelection) fTreeViewer.getSelection()).getFirstElement(); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IInformationControl#addDisposeListener(org.eclipse.swt.events.DisposeListener) + */ + public void addDisposeListener(DisposeListener listener) { + getShell().addDisposeListener(listener); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IInformationControl#addFocusListener(org.eclipse.swt.events.FocusListener) + */ + public void addFocusListener(FocusListener listener) { + getShell().addFocusListener(listener); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IInformationControl#computeSizeHint() + */ + public Point computeSizeHint() { + // Return the shell's size + // Note that it already has the persisted size if persisting is enabled. + return getShell().getSize(); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IInformationControl#dispose() + */ + public void dispose() { + close(); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IInformationControl#isFocusControl() + */ + public boolean isFocusControl() { + if (fTreeViewer.getControl().isFocusControl() || + fFilterText.isFocusControl()) { + return true; + } + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IInformationControl#removeDisposeListener(org.eclipse.swt.events.DisposeListener) + */ + public void removeDisposeListener(DisposeListener listener) { + getShell().removeDisposeListener(listener); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IInformationControl#removeFocusListener(org.eclipse.swt.events.FocusListener) + */ + public void removeFocusListener(FocusListener listener) { + getShell().removeFocusListener(listener); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IInformationControl#setBackgroundColor(org.eclipse.swt.graphics.Color) + */ + public void setBackgroundColor(Color background) { + applyBackgroundColor(background, getContents()); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IInformationControl#setFocus() + */ + public void setFocus() { + getShell().forceFocus(); + fFilterText.setFocus(); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IInformationControl#setForegroundColor(org.eclipse.swt.graphics.Color) + */ + public void setForegroundColor(Color foreground) { + applyForegroundColor(foreground, getContents()); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IInformationControl#setInformation(java.lang.String) + */ + public void setInformation(String information) { + // Ignore + // See IInformationControlExtension2 + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IInformationControl#setLocation(org.eclipse.swt.graphics.Point) + */ + public void setLocation(Point location) { + /* + * If the location is persisted, it gets managed by PopupDialog - fine. Otherwise, the location is + * computed in Window#getInitialLocation, which will center it in the parent shell / main + * monitor, which is wrong for two reasons: + * - we want to center over the editor / subject control, not the parent shell + * - the center is computed via the initalSize, which may be also wrong since the size may + * have been updated since via min/max sizing of AbstractInformationControlManager. + * In that case, override the location with the one computed by the manager. Note that + * the call to constrainShellSize in PopupDialog.open will still ensure that the shell is + * entirely visible. + */ + if ((getPersistBounds() == false) || + (getDialogSettings() == null)) { + getShell().setLocation(location); + } + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IInformationControl#setSize(int, int) + */ + public void setSize(int width, int height) { + getShell().setSize(width, height); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IInformationControl#setSizeConstraints(int, int) + */ + public void setSizeConstraints(int maxWidth, int maxHeight) { + // Ignore + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IInformationControl#setVisible(boolean) + */ + public void setVisible(boolean visible) { + if (visible) { + open(); + } else { + saveDialogBounds(getShell()); + getShell().setVisible(false); + } + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IInformationControlExtension#hasContents() + */ + public boolean hasContents() { + if ((fTreeViewer == null) || + (fTreeViewer.getInput() == null)) { + return false; + } + return true; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.text.IInformationControlExtension2#setInput(java.lang.Object) + */ + public void setInput(Object input) { + // Input comes from PDESourceInfoProvider.getInformation2() + // The input should be a model object of some sort + // Turn it into a structured selection and set the selection in the tree + if (input != null) { + fTreeViewer.setSelection(new StructuredSelection(input)); + } + } + + /* (non-Javadoc) + * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent) + */ + public void widgetDisposed(DisposeEvent e) { + // Note: We do not reuse the dialog + fTreeViewer= null; + fFilterText= null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.PopupDialog#createTitleControl(org.eclipse.swt.widgets.Composite) + */ + protected Control createTitleControl(Composite parent) { + // Applies only to dialog title - not body. See createDialogArea + // Create the text widget + createUIWidgetFilterText(parent); + // Add listeners to the text widget + createUIListenersFilterText(); + // Return the text widget + return fFilterText; + } + + /** + * @param parent + * @return + */ + private void createUIWidgetFilterText(Composite parent) { + // Create the widget + fFilterText = new Text(parent, SWT.NONE); + // Set the font + GC gc = new GC(parent); + gc.setFont(parent.getFont()); + FontMetrics fontMetrics = gc.getFontMetrics(); + gc.dispose(); + // Create the layout + GridData data = new GridData(GridData.FILL_HORIZONTAL); + data.heightHint= Dialog.convertHeightInCharsToPixels(fontMetrics, 1); + data.horizontalAlignment = GridData.FILL; + data.verticalAlignment = GridData.CENTER; + fFilterText.setLayoutData(data); + } + + /** + * + */ + private void gotoSelectedElement() { + Object selectedElement = getSelectedElement(); + if (selectedElement == null) { + return; + } + dispose(); + // Get the content outline page within the content outline view + // and select the item there to keep the quick outline in sync with the + // main outline and prevent duplicate selection events from occurring + fOutlineSelectionHandler.getContentOutline().setSelection( + new StructuredSelection(selectedElement)); + } + + /** + * + */ + private void createUIListenersFilterText() { + // Handle key events + fFilterText.addKeyListener(new KeyListener() { + public void keyPressed(KeyEvent e) { + if (e.keyCode == 0x0D) { + // Return key was pressed + gotoSelectedElement(); + } else if (e.keyCode == SWT.ARROW_DOWN) { + // Down key was pressed + fTreeViewer.getTree().setFocus(); + } else if (e.keyCode == SWT.ARROW_UP) { + // Up key was pressed + fTreeViewer.getTree().setFocus(); + } else if (e.character == 0x1B) { + // Escape key was pressed + dispose(); + } + } + public void keyReleased(KeyEvent e) { + // NO-OP + } + }); + // Handle text modify events + fFilterText.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + String text = ((Text)e.widget).getText(); + int length = text.length(); + if (length > 0) { + // Append a '*' pattern to the end of the text value if it + // does not have one already + if (text.charAt(length - 1) != '*') { + text = text + '*'; + } + // Prepend a '*' pattern to the beginning of the text value + // if it does not have one already + if (text.charAt(0) != '*') { + text = '*' + text; + } + } + // Set and update the pattern + setMatcherString(text, true); + } + }); + } + + /** + * Sets the patterns to filter out for the receiver. + *

+ * The following characters have special meaning: + * ? => any character + * * => any string + *

+ * + * @param pattern the pattern + * @param update true if the viewer should be updated + */ + private void setMatcherString(String pattern, boolean update) { + if (pattern.length() == 0) { + fStringMatcher = null; + } else { + fStringMatcher = new StringMatcher(pattern, true, false); + } + // Update the name pattern filter on the tree viewer + fNamePatternFilter.setStringMatcher(fStringMatcher); + // Update the tree viewer according to the pattern + if (update) { + stringMatcherUpdated(); + } + } + + /** + * The string matcher has been modified. The default implementation + * refreshes the view and selects the first matched element + */ + private void stringMatcherUpdated() { + // Refresh the tree viewer to re-filter + fTreeViewer.getControl().setRedraw(false); + fTreeViewer.refresh(); + fTreeViewer.expandAll(); + selectFirstMatch(); + fTreeViewer.getControl().setRedraw(true); + } + + /** + * Selects the first element in the tree which + * matches the current filter pattern. + */ + private void selectFirstMatch() { + Tree tree = fTreeViewer.getTree(); + Object element = findFirstMatchToPattern(tree.getItems()); + if (element != null) { + fTreeViewer.setSelection(new StructuredSelection(element), true); + } else { + fTreeViewer.setSelection(StructuredSelection.EMPTY); + } + } + + /** + * @param items + * @return + */ + private Object findFirstMatchToPattern(TreeItem[] items) { + // Match the string pattern against labels + ILabelProvider labelProvider = + (ILabelProvider)fTreeViewer.getLabelProvider(); + // Process each item in the tree + for (int i = 0; i < items.length; i++) { + Object element = items[i].getData(); + // Return the first element if no pattern is set + if (fStringMatcher == null) { + return element; + } + // Return the element if it matches the pattern + if (element != null) { + String label = labelProvider.getText(element); + if (fStringMatcher.match(label)) { + return element; + } + } + // Recursively check the elements children for a match + element = findFirstMatchToPattern(items[i].getItems()); + // Return the child element match if found + if (element != null) { + return element; + } + } + // No match found + return null; + } + +} Index: Ant Editor/org/eclipse/ant/internal/ui/editor/outline/IOutlineSelectionHandler.java =================================================================== RCS file: Ant Editor/org/eclipse/ant/internal/ui/editor/outline/IOutlineSelectionHandler.java diff -N Ant Editor/org/eclipse/ant/internal/ui/editor/outline/IOutlineSelectionHandler.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Ant Editor/org/eclipse/ant/internal/ui/editor/outline/IOutlineSelectionHandler.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2006 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ant.internal.ui.editor.outline; + +import org.eclipse.jface.viewers.SelectionChangedEvent; + +/** + * IOutlineSelectionHandler + * + */ +public interface IOutlineSelectionHandler { + + /** + * @param e + */ + public void updateSelection(SelectionChangedEvent e); + + /** + * @param e + */ + public void updateSelection(Object object); + + /** + * @return + */ + public ISortableContentOutlinePage getContentOutline(); + +} Index: Ant Editor/org/eclipse/ant/internal/ui/editor/outline/QuickOutlineNamePatternFilter.java =================================================================== RCS file: Ant Editor/org/eclipse/ant/internal/ui/editor/outline/QuickOutlineNamePatternFilter.java diff -N Ant Editor/org/eclipse/ant/internal/ui/editor/outline/QuickOutlineNamePatternFilter.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Ant Editor/org/eclipse/ant/internal/ui/editor/outline/QuickOutlineNamePatternFilter.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2006 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ant.internal.ui.editor.outline; + +import org.eclipse.ant.internal.ui.editor.utils.StringMatcher; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; + +/** + * QuickOutlineNamePatternFilter + * + */ +public class QuickOutlineNamePatternFilter extends ViewerFilter { + + private StringMatcher fStringMatcher; + + /** + * + */ + public QuickOutlineNamePatternFilter() { + fStringMatcher = null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ViewerFilter#select(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) + */ + public boolean select(Viewer viewer, Object parentElement, Object element) { + // Element passes the filter if the string matcher is undefined or the + // viewer is not a tree viewer + if ((fStringMatcher == null) || + ((viewer instanceof TreeViewer) == false)) { + return true; + } + TreeViewer treeViewer = (TreeViewer)viewer; + // Match the pattern against the label of the given element + String matchName = + ((ILabelProvider) treeViewer.getLabelProvider()).getText(element); + // Element passes the filter if it matches the pattern + if ((matchName != null) && + fStringMatcher.match(matchName)) { + return true; + } + // Determine whether the element has children that pass the filter + return hasUnfilteredChild(treeViewer, element); + } + + /** + * @param viewer + * @param element + * @return + */ + private boolean hasUnfilteredChild(TreeViewer viewer, Object element) { + // No point calling hasChildren() because the operation is the same cost + // as getting the children + // If the element has a child that passes the filter, then we want to + // keep the parent around - even if it does not pass the filter itself + Object[] children = + ((ITreeContentProvider) viewer.getContentProvider()).getChildren(element); + for (int i = 0; i < children.length; i++) { + if (select(viewer, element, children[i])) { + return true; + } + } + // Element does not pass the filter + return false; + } + + /** + * @param stringMatcher + */ + public void setStringMatcher(StringMatcher stringMatcher) { + fStringMatcher = stringMatcher; + } + +} Index: Ant Editor/org/eclipse/ant/internal/ui/editor/utils/StringMatcher.java =================================================================== RCS file: Ant Editor/org/eclipse/ant/internal/ui/editor/utils/StringMatcher.java diff -N Ant Editor/org/eclipse/ant/internal/ui/editor/utils/StringMatcher.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Ant Editor/org/eclipse/ant/internal/ui/editor/utils/StringMatcher.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,384 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ant.internal.ui.editor.utils; + +import java.util.Vector; + +/** + * Copied from JDT UI + * A string pattern matcher. Supports '*' and '?' wildcards. + */ +public class StringMatcher { + protected String fPattern; + protected int fLength; // pattern length + protected boolean fIgnoreWildCards; + protected boolean fIgnoreCase; + protected boolean fHasLeadingStar; + protected boolean fHasTrailingStar; + protected String fSegments[]; //the given pattern is split into * separated segments + + /* boundary value beyond which we don't need to search in the text */ + protected int fBound= 0; + + + protected static final char fSingleWildCard= '\u0000'; + + public static class Position { + int start; //inclusive + int end; //exclusive + public Position(int start, int end) { + this.start= start; + this.end= end; + } + public int getStart() { + return start; + } + public int getEnd() { + return end; + } + } + /** + * StringMatcher constructor takes in a String object that is a simple + * pattern. The pattern may contain '*' for 0 and many characters and + * '?' for exactly one character. + * + * Literal '*' and '?' characters must be escaped in the pattern + * e.g., "\*" means literal "*", etc. + * + * Escaping any other character (including the escape character itself), + * just results in that character in the pattern. + * e.g., "\a" means "a" and "\\" means "\" + * + * If invoking the StringMatcher with string literals in Java, don't forget + * escape characters are represented by "\\". + * + * @param pattern the pattern to match text against + * @param ignoreCase if true, case is ignored + * @param ignoreWildCards if true, wild cards and their escape sequences are ignored + * (everything is taken literally). + */ + public StringMatcher(String pattern, boolean ignoreCase, boolean ignoreWildCards) { + if (pattern == null) + throw new IllegalArgumentException(); + fIgnoreCase= ignoreCase; + fIgnoreWildCards= ignoreWildCards; + fPattern= pattern; + fLength= pattern.length(); + + if (fIgnoreWildCards) { + parseNoWildCards(); + } else { + parseWildCards(); + } + } + /** + * Find the first occurrence of the pattern between startend(exclusive). + * @param text the String object to search in + * @param start the starting index of the search range, inclusive + * @param end the ending index of the search range, exclusive + * @return an StringMatcher.Position object that keeps the starting + * (inclusive) and ending positions (exclusive) of the first occurrence of the + * pattern in the specified range of the text; return null if not found or subtext + * is empty (start==end). A pair of zeros is returned if pattern is empty string + * Note that for pattern like "*abc*" with leading and trailing stars, position of "abc" + * is returned. For a pattern like"*??*" in text "abcdf", (1,3) is returned + */ + public StringMatcher.Position find(String text, int start, int end) { + if (text == null) + throw new IllegalArgumentException(); + + int tlen= text.length(); + if (start < 0) + start= 0; + if (end > tlen) + end= tlen; + if (end < 0 ||start >= end ) + return null; + if (fLength == 0) + return new Position(start, start); + if (fIgnoreWildCards) { + int x= posIn(text, start, end); + if (x < 0) + return null; + return new Position(x, x+fLength); + } + + int segCount= fSegments.length; + if (segCount == 0)//pattern contains only '*'(s) + return new Position (start, end); + + int curPos= start; + int matchStart= -1; + int i; + for (i= 0; i < segCount && curPos < end; ++i) { + String current= fSegments[i]; + int nextMatch= regExpPosIn(text, curPos, end, current); + if (nextMatch < 0 ) + return null; + if(i == 0) + matchStart= nextMatch; + curPos= nextMatch + current.length(); + } + if (i < segCount) + return null; + return new Position(matchStart, curPos); + } + /** + * match the given text with the pattern + * @return true if matched eitherwise false + * @param text a String object + */ + public boolean match(String text) { + return match(text, 0, text.length()); + } + /** + * Given the starting (inclusive) and the ending (exclusive) positions in the + * text, determine if the given substring matches with aPattern + * @return true if the specified portion of the text matches the pattern + * @param text a String object that contains the substring to match + * @param start marks the starting position (inclusive) of the substring + * @param end marks the ending index (exclusive) of the substring + */ + public boolean match(String text, int start, int end) { + if (null == text) + throw new IllegalArgumentException(); + + if (start > end) + return false; + + if (fIgnoreWildCards) + return (end - start == fLength) && fPattern.regionMatches(fIgnoreCase, 0, text, start, fLength); + int segCount= fSegments.length; + if (segCount == 0 && (fHasLeadingStar || fHasTrailingStar)) // pattern contains only '*'(s) + return true; + if (start == end) + return fLength == 0; + if (fLength == 0) + return start == end; + + int tlen= text.length(); + if (start < 0) + start= 0; + if (end > tlen) + end= tlen; + + int tCurPos= start; + int bound= end - fBound; + if ( bound < 0) + return false; + int i=0; + String current= fSegments[i]; + int segLength= current.length(); + + /* process first segment */ + if (!fHasLeadingStar){ + if(!regExpRegionMatches(text, start, current, 0, segLength)) { + return false; + } + ++i; + tCurPos= tCurPos + segLength; + } + if ((fSegments.length == 1) && (!fHasLeadingStar) && (!fHasTrailingStar)) { + // only one segment to match, no wildcards specified + return tCurPos == end; + } + /* process middle segments */ + while (i < segCount) { + current= fSegments[i]; + int currentMatch; + int k= current.indexOf(fSingleWildCard); + if (k < 0) { + currentMatch= textPosIn(text, tCurPos, end, current); + if (currentMatch < 0) + return false; + } else { + currentMatch= regExpPosIn(text, tCurPos, end, current); + if (currentMatch < 0) + return false; + } + tCurPos= currentMatch + current.length(); + i++; + } + + /* process final segment */ + if (!fHasTrailingStar && tCurPos != end) { + int clen= current.length(); + return regExpRegionMatches(text, end - clen, current, 0, clen); + } + return i == segCount ; + } + + /** + * This method parses the given pattern into segments seperated by wildcard '*' characters. + * Since wildcards are not being used in this case, the pattern consists of a single segment. + */ + private void parseNoWildCards() { + fSegments= new String[1]; + fSegments[0]= fPattern; + fBound= fLength; + } + /** + * Parses the given pattern into segments seperated by wildcard '*' characters. + */ + private void parseWildCards() { + if(fPattern.startsWith("*"))//$NON-NLS-1$ + fHasLeadingStar= true; + if(fPattern.endsWith("*")) {//$NON-NLS-1$ + /* make sure it's not an escaped wildcard */ + if (fLength > 1 && fPattern.charAt(fLength - 2) != '\\') { + fHasTrailingStar= true; + } + } + + Vector temp= new Vector(); + + int pos= 0; + StringBuffer buf= new StringBuffer(); + while (pos < fLength) { + char c= fPattern.charAt(pos++); + switch (c) { + case '\\': + if (pos >= fLength) { + buf.append(c); + } else { + char next= fPattern.charAt(pos++); + /* if it's an escape sequence */ + if (next == '*' || next == '?' || next == '\\') { + buf.append(next); + } else { + /* not an escape sequence, just insert literally */ + buf.append(c); + buf.append(next); + } + } + break; + case '*': + if (buf.length() > 0) { + /* new segment */ + temp.addElement(buf.toString()); + fBound += buf.length(); + buf.setLength(0); + } + break; + case '?': + /* append special character representing single match wildcard */ + buf.append(fSingleWildCard); + break; + default: + buf.append(c); + } + } + + /* add last buffer to segment list */ + if (buf.length() > 0) { + temp.addElement(buf.toString()); + fBound += buf.length(); + } + + fSegments= new String[temp.size()]; + temp.copyInto(fSegments); + } + /** + * @param text a string which contains no wildcard + * @param start the starting index in the text for search, inclusive + * @param end the stopping point of search, exclusive + * @return the starting index in the text of the pattern , or -1 if not found + */ + protected int posIn(String text, int start, int end) {//no wild card in pattern + int max= end - fLength; + + if (!fIgnoreCase) { + int i= text.indexOf(fPattern, start); + if (i == -1 || i > max) + return -1; + return i; + } + + for (int i= start; i <= max; ++i) { + if (text.regionMatches(true, i, fPattern, 0, fLength)) + return i; + } + + return -1; + } + /** + * @param text a simple regular expression that may only contain '?'(s) + * @param start the starting index in the text for search, inclusive + * @param end the stopping point of search, exclusive + * @param p a simple regular expression that may contains '?' + * @return the starting index in the text of the pattern , or -1 if not found + */ + protected int regExpPosIn(String text, int start, int end, String p) { + int plen= p.length(); + + int max= end - plen; + for (int i= start; i <= max; ++i) { + if (regExpRegionMatches(text, i, p, 0, plen)) + return i; + } + return -1; + } + + + protected boolean regExpRegionMatches(String text, int tStart, String p, int pStart, int plen) { + while (plen-- > 0) { + char tchar= text.charAt(tStart++); + char pchar= p.charAt(pStart++); + + /* process wild cards */ + if (!fIgnoreWildCards) { + /* skip single wild cards */ + if (pchar == fSingleWildCard) { + continue; + } + } + if (pchar == tchar) + continue; + if (fIgnoreCase) { + if (Character.toUpperCase(tchar) == Character.toUpperCase(pchar)) + continue; + // comparing after converting to upper case doesn't handle all cases; + // also compare after converting to lower case + if (Character.toLowerCase(tchar) == Character.toLowerCase(pchar)) + continue; + } + return false; + } + return true; + } + /** + * @param text the string to match + * @param start the starting index in the text for search, inclusive + * @param end the stopping point of search, exclusive + * @param p a string that has no wildcard + * @return the starting index in the text of the pattern , or -1 if not found + */ + protected int textPosIn(String text, int start, int end, String p) { + + int plen= p.length(); + int max= end - plen; + + if (!fIgnoreCase) { + int i= text.indexOf(p, start); + if (i == -1 || i > max) + return -1; + return i; + } + + for (int i= start; i <= max; ++i) { + if (text.regionMatches(true, i, p, 0, plen)) + return i; + } + + return -1; + } +} Index: Ant Editor/org/eclipse/ant/internal/ui/editor/outline/IOutlineContentCreator.java =================================================================== RCS file: Ant Editor/org/eclipse/ant/internal/ui/editor/outline/IOutlineContentCreator.java diff -N Ant Editor/org/eclipse/ant/internal/ui/editor/outline/IOutlineContentCreator.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Ant Editor/org/eclipse/ant/internal/ui/editor/outline/IOutlineContentCreator.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2006 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ant.internal.ui.editor.outline; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.ViewerComparator; + +/** + * IContentOutlineCreator + * + */ +public interface IOutlineContentCreator { + + /** + * @return + */ + public ViewerComparator createOutlineComparator(); + + /** + * @return + */ + public ViewerComparator createDefaultOutlineComparator(); + + /** + * @return + */ + public ILabelProvider createOutlineLabelProvider(); + + /** + * @return + */ + public ITreeContentProvider createOutlineContentProvider(); + + /** + * @return + */ + public Object getOutlineInput(); + +} Index: Ant Editor/org/eclipse/ant/internal/ui/editor/outline/AntOutlineComparator.java =================================================================== RCS file: Ant Editor/org/eclipse/ant/internal/ui/editor/outline/AntOutlineComparator.java diff -N Ant Editor/org/eclipse/ant/internal/ui/editor/outline/AntOutlineComparator.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Ant Editor/org/eclipse/ant/internal/ui/editor/outline/AntOutlineComparator.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,19 @@ +package org.eclipse.ant.internal.ui.editor.outline; + +import org.eclipse.ant.internal.ui.model.AntElementNode; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; + +public class AntOutlineComparator extends ViewerComparator { + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) + */ + public int compare(Viewer viewer, Object e1, Object e2) { + if (!(e1 instanceof AntElementNode && e2 instanceof AntElementNode)) { + return super.compare(viewer, e1, e2); + } + String name1= ((AntElementNode) e1).getLabel(); + String name2= ((AntElementNode) e2).getLabel(); + return getComparator().compare(name1, name2); + } +} Index: Ant Editor/org/eclipse/ant/internal/ui/editor/outline/QuickOutlineMouseMoveListener.java =================================================================== RCS file: Ant Editor/org/eclipse/ant/internal/ui/editor/outline/QuickOutlineMouseMoveListener.java diff -N Ant Editor/org/eclipse/ant/internal/ui/editor/outline/QuickOutlineMouseMoveListener.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Ant Editor/org/eclipse/ant/internal/ui/editor/outline/QuickOutlineMouseMoveListener.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2006 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ant.internal.ui.editor.outline; + +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseMoveListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Item; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; + +/** + * QuickOutlineMouseMoveListener + * + */ +public class QuickOutlineMouseMoveListener implements MouseMoveListener { + + private TreeItem fLastItem; + + private TreeViewer fTreeViewer; + + /** + * + */ + public QuickOutlineMouseMoveListener(TreeViewer treeViewer) { + fLastItem = null; + fTreeViewer = treeViewer; + } + + /* (non-Javadoc) + * @see org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent) + */ + public void mouseMove(MouseEvent e) { + Tree tree = fTreeViewer.getTree(); + if (tree.equals(e.getSource())) { + Object o= tree.getItem(new Point(e.x, e.y)); + if (o instanceof TreeItem) { + if (!o.equals(fLastItem)) { + fLastItem= (TreeItem)o; + tree.setSelection(new TreeItem[] { fLastItem }); + } else if (e.y < tree.getItemHeight() / 4) { + // Scroll up + Point p= tree.toDisplay(e.x, e.y); + Item item= fTreeViewer.scrollUp(p.x, p.y); + if (item instanceof TreeItem) { + fLastItem= (TreeItem)item; + tree.setSelection(new TreeItem[] { fLastItem }); + } + } else if (e.y > tree.getBounds().height - tree.getItemHeight() / 4) { + // Scroll down + Point p= tree.toDisplay(e.x, e.y); + Item item= fTreeViewer.scrollDown(p.x, p.y); + if (item instanceof TreeItem) { + fLastItem= (TreeItem)item; + tree.setSelection(new TreeItem[] { fLastItem }); + } + } + } + } + } + +}