blob: cf7640d982c4e4c09edf79c7600379b91a5a7a4b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2016 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.ui.search;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.commands.ActionHandler;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IWorkbenchCommandConstants;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.part.IPageSite;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.search.ui.NewSearchUI;
import org.eclipse.search.ui.text.AbstractTextSearchResult;
import org.eclipse.search.ui.text.AbstractTextSearchViewPage;
import org.eclipse.search.ui.text.Match;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.ITypeRoot;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.manipulation.SharedASTProviderCore;
import org.eclipse.jdt.internal.core.manipulation.search.IOccurrencesFinder;
import org.eclipse.jdt.internal.core.manipulation.search.OccurrencesFinder;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.actions.AbstractToggleLinkingAction;
import org.eclipse.jdt.internal.ui.viewsupport.ColoringLabelProvider;
import org.eclipse.jdt.internal.ui.viewsupport.ISelectionListenerWithAST;
import org.eclipse.jdt.internal.ui.viewsupport.SelectionListenerWithASTManager;
public class OccurrencesSearchResultPage extends AbstractTextSearchViewPage {
private static final String DIALOGSTORE_LINKEDITORS= "TypeHierarchyViewPart.linkeditors"; //$NON-NLS-1$
private TextSearchTableContentProvider fContentProvider;
private boolean fLinkingEnabled;
private AbstractToggleLinkingAction fToggleLinkingAction;
private LinkWithEditorListener fLinkWithEditorListener;
private class LinkWithEditorListener implements IPartListener2, ISelectionListenerWithAST {
private ITextEditor fActiveEditor;
private boolean fIsVisible;
public void install(IWorkbenchPage page) {
page.addPartListener(this);
fIsVisible= page.isPartVisible(getViewPart());
if (fIsVisible) {
installOnActiveEditor(page);
}
}
private void installOnActiveEditor(IWorkbenchPage page) {
IEditorPart activeEditor= page.getActiveEditor();
if (activeEditor instanceof ITextEditor) {
editorActive(activeEditor);
ISelection selection= activeEditor.getSite().getSelectionProvider().getSelection();
ITypeRoot typeRoot= JavaUI.getEditorInputTypeRoot(activeEditor.getEditorInput());
if (typeRoot != null && selection instanceof ITextSelection) {
CompilationUnit astRoot= SharedASTProviderCore.getAST(typeRoot, SharedASTProviderCore.WAIT_ACTIVE_ONLY, null);
if (astRoot != null) {
preformEditorSelectionChanged((ITextSelection) selection, astRoot);
}
}
}
}
private void uninstallOnActiveEditor() {
if (fActiveEditor != null) {
SelectionListenerWithASTManager.getDefault().removeListener(fActiveEditor, this);
fActiveEditor= null;
}
}
public void uninstall(IWorkbenchPage page) {
page.removePartListener(this);
uninstallOnActiveEditor();
}
@Override
public void partActivated(IWorkbenchPartReference partRef) {
if (fIsVisible && partRef instanceof IEditorReference) {
editorActive(((IEditorReference) partRef).getEditor(true));
}
}
private void editorActive(IEditorPart editor) {
if (editor instanceof ITextEditor) {
if (editor != fActiveEditor) {
setInput(null, null);
}
fActiveEditor= (ITextEditor) editor;
SelectionListenerWithASTManager.getDefault().addListener(fActiveEditor, this);
}
}
@Override
public void partDeactivated(IWorkbenchPartReference partRef) {
}
@Override
public void selectionChanged(IEditorPart part, ITextSelection selection, CompilationUnit astRoot) {
preformEditorSelectionChanged(selection, astRoot);
}
@Override
public void partVisible(IWorkbenchPartReference partRef) {
if (NewSearchUI.SEARCH_VIEW_ID.equals(partRef.getId()) && partRef.getPart(true) == getViewPart()) {
if (fActiveEditor == null) {
fIsVisible= true;
}
}
}
@Override
public void partHidden(IWorkbenchPartReference partRef) {
if (NewSearchUI.SEARCH_VIEW_ID.equals(partRef.getId()) && partRef.getPart(true) == getViewPart()) {
fIsVisible= false;
uninstallOnActiveEditor();
} else if (partRef instanceof IEditorReference && partRef.getPart(true) == fActiveEditor) {
uninstallOnActiveEditor();
}
}
@Override
public void partBroughtToTop(IWorkbenchPartReference partRef) {
}
@Override
public void partClosed(IWorkbenchPartReference partRef) {
if (partRef instanceof IEditorReference && partRef.getPart(true) == fActiveEditor) {
uninstallOnActiveEditor();
}
}
@Override
public void partInputChanged(IWorkbenchPartReference partRef) {
}
@Override
public void partOpened(IWorkbenchPartReference partRef) {
}
}
private class ToggleLinkingAction extends AbstractToggleLinkingAction {
@Override
public void run() {
setLinkingEnabled(isChecked());
}
}
public OccurrencesSearchResultPage() {
super(AbstractTextSearchViewPage.FLAG_LAYOUT_FLAT);
fLinkWithEditorListener= new LinkWithEditorListener();
fLinkingEnabled= false;
fToggleLinkingAction= new ToggleLinkingAction();
fToggleLinkingAction.setActionDefinitionId(IWorkbenchCommandConstants.NAVIGATE_TOGGLE_LINK_WITH_EDITOR);
}
@Override
public void init(IPageSite pageSite) {
super.init(pageSite);
// wait until site is set
setLinkingEnabled(getDialogSettings().getBoolean(DIALOGSTORE_LINKEDITORS));
}
@Override
public void dispose() {
if (fLinkingEnabled) {
fLinkWithEditorListener.uninstall(getSite().getPage());
}
super.dispose();
}
@Override
protected void fillToolbar(IToolBarManager tbm) {
super.fillToolbar(tbm);
tbm.add(fToggleLinkingAction);
}
@Override
public void createControl(Composite parent) {
super.createControl(parent);
IActionBars bars= getSite().getActionBars();
IMenuManager menu= bars.getMenuManager();
menu.add(fToggleLinkingAction);
IHandlerService handlerService= getSite().getService(IHandlerService.class);
handlerService.activateHandler(IWorkbenchCommandConstants.NAVIGATE_TOGGLE_LINK_WITH_EDITOR, new ActionHandler(fToggleLinkingAction));
}
/*
* @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#showMatch(org.eclipse.search.ui.text.Match, int, int)
*/
@Override
protected void showMatch(Match match, int currentOffset, int currentLength, boolean activate) throws PartInitException {
JavaElementLine element= (JavaElementLine) match.getElement();
IJavaElement javaElement= element.getJavaElement();
try {
IEditorPart editor= JavaUI.openInEditor(javaElement, false, false);
if (editor instanceof ITextEditor) {
ITextEditor textEditor= (ITextEditor) editor;
textEditor.selectAndReveal(currentOffset, currentLength);
}
// activating at the end avoids an outdated selection event from JavaUI.openInEditor(..):
if (editor != null && activate)
editor.getEditorSite().getPage().activate(editor);
} catch (PartInitException e1) {
return;
} catch (JavaModelException e1) {
return;
}
}
/*
* @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#elementsChanged(java.lang.Object[])
*/
@Override
protected void elementsChanged(Object[] objects) {
if (fContentProvider != null)
fContentProvider.elementsChanged(objects);
}
/*
* @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#clear()
*/
@Override
protected void clear() {
if (fContentProvider != null)
fContentProvider.clear();
}
/*
* @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#configureTreeViewer(org.eclipse.jface.viewers.TreeViewer)
*/
@Override
protected void configureTreeViewer(TreeViewer viewer) {
throw new IllegalStateException("Doesn't support tree mode."); //$NON-NLS-1$
}
/*
* @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#configureTableViewer(org.eclipse.jface.viewers.TableViewer)
*/
@Override
protected void configureTableViewer(TableViewer viewer) {
viewer.setComparator(new ViewerComparator() {
@Override
public int compare(Viewer v, Object e1, Object e2) {
JavaElementLine jel1= (JavaElementLine) e1;
JavaElementLine jel2= (JavaElementLine) e2;
return jel1.getLineNumber() - jel2.getLineNumber();
}
});
viewer.setLabelProvider(new ColoringLabelProvider(new OccurrencesSearchLabelProvider(this)));
fContentProvider= new TextSearchTableContentProvider();
viewer.setContentProvider(fContentProvider);
}
public boolean isLinkingEnabled() {
return fLinkingEnabled;
}
public void setLinkingEnabled(boolean enabled) {
if (fLinkingEnabled != enabled) {
fLinkingEnabled= enabled;
fToggleLinkingAction.setChecked(enabled);
getDialogSettings().put(DIALOGSTORE_LINKEDITORS, enabled);
if (enabled) {
fLinkWithEditorListener.install(getSite().getPage());
} else {
fLinkWithEditorListener.uninstall(getSite().getPage());
}
}
}
private IDialogSettings getDialogSettings() {
return JavaPlugin.getDefault().getDialogSettingsSection("OccurrencesSearchResultPage"); //$NON-NLS-1$
}
private void preformEditorSelectionChanged(ITextSelection selection, CompilationUnit astRoot) {
if (!isLinkingEnabled()) {
return;
}
IOccurrencesFinder finder;
AbstractTextSearchResult input= getInput();
if (input == null) {
finder= new OccurrencesFinder();
} else {
String id= ((OccurrencesSearchQuery) input.getQuery()).getFinderId();
if (id == OccurrencesFinder.ID) {
finder= new OccurrencesFinder();
} else if (ExceptionOccurrencesFinder.ID.equals(id)) {
finder= new ExceptionOccurrencesFinder();
} else {
finder= new ImplementOccurrencesFinder();
}
}
int offset= selection.getOffset();
int length= selection.getLength();
if (finder.initialize(astRoot, offset, length) == null) {
final OccurrencesSearchQuery query= new OccurrencesSearchQuery(finder, astRoot.getTypeRoot());
query.run(null);
OccurrencesSearchResult result= (OccurrencesSearchResult) query.getSearchResult();
final JavaElementLine line= getMatchingLine(result, offset, length);
getSite().getShell().getDisplay().asyncExec(() -> setInput(query.getSearchResult(), line == null ? null : new StructuredSelection(line)));
}
}
private static JavaElementLine getMatchingLine(OccurrencesSearchResult result, int offset, int length) {
for (Object element : result.getElements()) {
JavaElementLine line = (JavaElementLine) element;
for (Match matche : result.getMatches(line)) {
OccurrenceMatch match= (OccurrenceMatch) matche;
if (match.getOriginalOffset() <= offset && offset + length <= match.getOriginalOffset() + match.getOriginalLength()) {
return line;
}
}
}
return null;
}
}