blob: 2e6b32a194ab13a2ba5f0dff8a3b98875f4f3629 [file] [log] [blame]
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
package org.eclipse.search.internal.ui;
import org.eclipse.core.runtime.IPath;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.util.Assert;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.PlatformUI;
import org.eclipse.search.ui.IContextMenuConstants;
import org.eclipse.search.ui.IContextMenuContributor;
import org.eclipse.search.ui.ISearchResultViewEntry;
import org.eclipse.search.internal.ui.util.FileLabelProvider;
/**
* A special viewer to present search results. The viewer implements an
* optimized adding and removing strategy. Furthermore it manages
* contributions for search result types. For example the viewer's context
* menu differs if the search result has been generated by a text or
* a java search.
*/
class SearchResultViewer extends TableViewer {
private SearchResultView fOuterPart;
private boolean fFirstTime= true;
private ShowNextResultAction fShowNextResultAction;
private ShowPreviousResultAction fShowPreviousResultAction;
private GotoMarkerAction fGotoMarkerAction;
private SearchAgainAction fSearchAgainAction;
private RemoveAllSearchesAction fRemoveAllSearchesAction;
private RemoveMatchAction fRemoveMatchAction;
private SortDropDownAction fSortDropDownAction;
private SearchDropDownAction fSearchDropDownAction;
private CopyToClipboardAction fCopyToClipboardAction;
private int fMarkerToShow;
private boolean fHandleNextSelectionChangedEvent= true;
/*
* These static fields will go away when support for
* multiple search will be implemented
*/
private static IContextMenuContributor fgContextMenuContributor;
private static IAction fgGotoMarkerAction;
public SearchResultViewer(SearchResultView outerPart, Composite parent) {
super(new Table(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION));
fOuterPart= outerPart;
Assert.isNotNull(fOuterPart);
setUseHashlookup(true);
setContentProvider(new SearchResultContentProvider());
setLabelProvider(new SearchResultLabelProvider(new FileLabelProvider(FileLabelProvider.SHOW_LABEL), PlatformUI.getWorkbench().getDecoratorManager()));
boolean hasSearch= SearchManager.getDefault().getCurrentSearch() != null;
fShowNextResultAction= new ShowNextResultAction(this);
fShowNextResultAction.setEnabled(false);
fShowPreviousResultAction= new ShowPreviousResultAction(this);
fShowPreviousResultAction.setEnabled(false);
fGotoMarkerAction= new GotoMarkerAction(this);
fGotoMarkerAction.setEnabled(false);
fRemoveMatchAction= new RemoveMatchAction(this);
fRemoveMatchAction.setEnabled(false);
fRemoveAllSearchesAction= new RemoveAllSearchesAction();
fSearchAgainAction= new SearchAgainAction();
fSearchAgainAction.setEnabled(hasSearch);
fRemoveAllSearchesAction.setEnabled(hasSearch);
fSortDropDownAction = new SortDropDownAction(this);
fSortDropDownAction.setEnabled(getItemCount() > 0);
fSearchDropDownAction= new SearchDropDownAction(this);
fSearchDropDownAction.setEnabled(hasSearch);
fCopyToClipboardAction= new CopyToClipboardAction(this);
addSelectionChangedListener(
new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
handleSelectionChanged(true);
}
}
);
getTable().addSelectionListener(new SelectionAdapter() {
public void widgetDefaultSelected(SelectionEvent e) {
showResult();
}
});
MenuManager menuMgr= new MenuManager("#PopUp"); //$NON-NLS-1$
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(
new IMenuListener() {
public void menuAboutToShow(IMenuManager mgr) {
SearchPlugin.createStandardGroups(mgr);
fillContextMenu(mgr);
}
});
Menu menu= menuMgr.createContextMenu(getTable());
getTable().setMenu(menu);
// Register menu
fOuterPart.getSite().registerContextMenu(menuMgr, this);
}
private void handleSelectionChanged(boolean updateMarkerToShow) {
int selectionCount= getSelectedEntriesCount();
boolean hasSingleSelection= selectionCount == 1;
boolean hasElements= getItemCount() > 0;
fShowNextResultAction.setEnabled(hasSingleSelection || (hasElements && selectionCount == 0));
fShowPreviousResultAction.setEnabled(hasSingleSelection || (hasElements && selectionCount == 0));
fGotoMarkerAction.setEnabled(hasSingleSelection);
fRemoveMatchAction.setEnabled(hasSingleSelection);
if (updateMarkerToShow && fHandleNextSelectionChangedEvent) {
fMarkerToShow= -1;
} else
fHandleNextSelectionChangedEvent= true;
if (!updateMarkerToShow)
fHandleNextSelectionChangedEvent= false;
String location= ""; //$NON-NLS-1$
if (hasSingleSelection) {
ISearchResultViewEntry entry= (ISearchResultViewEntry)getTable().getItem(getTable().getSelectionIndex()).getData();
IPath path= entry.getResource().getFullPath();
if (path != null)
location= path.makeRelative().toString();
}
setStatusLineMessage(location);
}
void enableActions() {
/*
* Note: The check before each set operation reduces flickering
*/
boolean state= getItemCount() > 0;
if (state != fShowNextResultAction.isEnabled())
fShowNextResultAction.setEnabled(state);
if (state != fShowPreviousResultAction.isEnabled())
fShowPreviousResultAction.setEnabled(state);
if (state != fSortDropDownAction.isEnabled())
fSortDropDownAction.setEnabled(state);
state= SearchManager.getDefault().getCurrentSearch() != null;
if (state != fRemoveAllSearchesAction.isEnabled())
fRemoveAllSearchesAction.setEnabled(state);
if (state != fSearchDropDownAction.isEnabled())
fSearchDropDownAction.setEnabled(state);
if (state != fSearchAgainAction.isEnabled())
fSearchAgainAction.setEnabled(state);
state= !getSelection().isEmpty();
if (state != fGotoMarkerAction.isEnabled())
fGotoMarkerAction.setEnabled(state);
if (state != fRemoveMatchAction.isEnabled())
fRemoveMatchAction.setEnabled(state);
}
protected void inputChanged(Object input, Object oldInput) {
getTable().removeAll();
super.inputChanged(input, oldInput);
fMarkerToShow= -1;
updateTitle();
enableActions();
if (getItemCount() > 0)
selectResult(getTable(), 0);
}
protected int getSelectedEntriesCount() {
ISelection s= getSelection();
if (s == null || s.isEmpty() || !(s instanceof IStructuredSelection))
return 0;
IStructuredSelection selection= (IStructuredSelection)s;
return selection.size();
}
//--- Contribution management -----------------------------------------------
protected boolean enableRemoveMatchMenuItem() {
if (getSelectedEntriesCount() != 1)
return false;
Table table= getTable();
int index= table.getSelectionIndex();
SearchResultViewEntry entry= null;
if (index > -1)
entry= (SearchResultViewEntry)table.getItem(index).getData();
return (entry != null && entry.getMatchCount() > 1);
}
void fillContextMenu(IMenuManager menu) {
if (fgContextMenuContributor != null)
fgContextMenuContributor.fill(menu, this);
if (!getSelection().isEmpty()) {
menu.appendToGroup(IContextMenuConstants.GROUP_ADDITIONS, fCopyToClipboardAction);
menu.appendToGroup(IContextMenuConstants.GROUP_GOTO, fGotoMarkerAction);
if (enableRemoveMatchMenuItem())
menu.appendToGroup(IContextMenuConstants.GROUP_REORGANIZE, fRemoveMatchAction);
menu.appendToGroup(IContextMenuConstants.GROUP_REORGANIZE, new RemoveResultAction(this));
}
// If we have elements
if (getItemCount() > 0)
menu.appendToGroup(IContextMenuConstants.GROUP_REORGANIZE, new RemoveAllResultsAction());
menu.appendToGroup(IContextMenuConstants.GROUP_VIEWER_SETUP, fSearchAgainAction);
menu.appendToGroup(IContextMenuConstants.GROUP_VIEWER_SETUP, fSortDropDownAction);
}
IAction getGotoMarkerAction() {
// null as return value is covered (no action will take place)
return fgGotoMarkerAction;
}
void setGotoMarkerAction(IAction gotoMarkerAction) {
fgGotoMarkerAction= gotoMarkerAction;
}
void setContextMenuTarget(IContextMenuContributor contributor) {
fgContextMenuContributor= contributor;
}
void setPageId(String pageId) {
fSortDropDownAction.setPageId(pageId);
ILabelProvider labelProvider= fOuterPart.getLabelProvider(pageId);
if (labelProvider != null)
internalSetLabelProvider(labelProvider);
}
void fillToolBar(IToolBarManager tbm) {
tbm.add(fShowNextResultAction);
tbm.add(fShowPreviousResultAction);
tbm.add(fGotoMarkerAction);
tbm.add(fRemoveMatchAction);
tbm.add(new Separator());
tbm.add(new OpenSearchDialogAction());
tbm.add(fRemoveAllSearchesAction);
tbm.add(fSearchDropDownAction);
// need to hook F5 to table
getTable().addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
if (e.keyCode == SWT.F5) {
fSearchAgainAction.run();
return; // performance
}
if (e.character == SWT.DEL) {
new RemoveResultAction(SearchResultViewer.this).run();
return; // performance
}
if (e.stateMask == SWT.CTRL && e.character == 'E'-0x40) {
showNextResult();
return; // performance
}
if (e.stateMask == (SWT.CTRL | SWT.SHIFT) && e.character == 'E'-0x40) {
showPreviousResult();
return; // performance
}
}
});
}
int getItemCount() {
return SearchManager.getDefault().getCurrentItemCount();
}
void internalSetLabelProvider(ILabelProvider provider) {
setLabelProvider(new SearchResultLabelProvider(provider, PlatformUI.getWorkbench().getDecoratorManager()));
}
/**
* Makes the first marker of the current result entry
* visible in an editor. If no result
* is visible, this method does nothing.
*/
public void showResult() {
Table table= getTable();
if (!canDoShowResult(table))
return;
int index= table.getSelectionIndex();
if (index < 0)
return;
SearchResultViewEntry entry= (SearchResultViewEntry)getTable().getItem(index).getData();
fMarkerToShow= 0;
entry.setSelectedMarkerIndex(0);
openCurrentSelection();
}
/**
* Makes the next result (marker) visible in an editor. If no result
* is visible, this method makes the first result visible.
*/
public void showNextResult() {
Table table= getTable();
if (!canDoShowResult(table))
return;
int index= table.getSelectionIndex();
SearchResultViewEntry entry= null;
if (index > -1)
entry= (SearchResultViewEntry)table.getItem(index).getData();
fMarkerToShow++;
if (entry == null || fMarkerToShow >= entry.getMatchCount()) {
// move selection
if (index == -1) {
index= 0;
} else {
index++;
if (index >= table.getItemCount())
index= 0;
}
fMarkerToShow= 0;
entry= (SearchResultViewEntry)getTable().getItem(index).getData();
selectResult(table, index);
}
entry.setSelectedMarkerIndex(fMarkerToShow);
openCurrentSelection();
}
/**
* Makes the previous result (marker) visible. If there isn't any
* visible result, this method makes the last result visible.
*/
public void showPreviousResult() {
Table table= getTable();
if (!canDoShowResult(table))
return;
int index= table.getSelectionIndex();
SearchResultViewEntry entry;
fMarkerToShow--;
if (fMarkerToShow >= 0)
entry= (SearchResultViewEntry)getTable().getItem(getTable().getSelectionIndex()).getData();
else {
// move selection
int count= table.getItemCount();
if (index == -1) {
index= count - 1;
} else {
index--;
if (index < 0)
index= count - 1;
}
entry= (SearchResultViewEntry)getTable().getItem(index).getData();
fMarkerToShow= entry.getMatchCount() - 1;
selectResult(table, index);
}
entry.setSelectedMarkerIndex(fMarkerToShow);
openCurrentSelection();
}
private boolean canDoShowResult(Table table) {
if (table == null || getItemCount() == 0)
return false;
return true;
}
private void selectResult(Table table, int index) {
table.setSelection(index);
table.showSelection();
handleSelectionChanged(false);
}
private void openCurrentSelection() {
IAction action= getGotoMarkerAction();
if (action != null)
action.run();
}
/**
* Update the title
*/
protected void updateTitle() {
boolean hasCurrentSearch= SearchManager.getDefault().getCurrentSearch() != null;
String title;
if (hasCurrentSearch) {
String description= SearchManager.getDefault().getCurrentSearch().getFullDescription();
title= SearchMessages.getFormattedString("SearchResultView.titleWithDescription", description); //$NON-NLS-1$
} else
title= SearchMessages.getString("SearchResultView.title"); //$NON-NLS-1$
if (title == null || !title.equals(fOuterPart.getTitle()))
fOuterPart.setTitle(title);
}
/**
* Clear the title
*/
protected void clearTitle() {
String title= SearchMessages.getString("SearchResultView.title"); //$NON-NLS-1$
if (title == null || !title.equals(fOuterPart.getTitle()))
fOuterPart.setTitle(title);
}
/**
* Sets the message text to be displayed on the status line.
* The image on the status line is cleared.
*/
private void setStatusLineMessage(String message) {
fOuterPart.getViewSite().getActionBars().getStatusLineManager().setMessage(message);
}
protected void handleDispose(DisposeEvent event) {
Menu menu= getTable().getMenu();
if (menu != null)
menu.dispose();
super.handleDispose(event);
}
//--- Change event handling -------------------------------------------------
/**
* Handle a single add.
*/
protected void handleAddMatch(ISearchResultViewEntry entry) {
insert(entry, -1);
}
/**
* Handle a single remove.
*/
protected void handleRemoveMatch(ISearchResultViewEntry entry) {
Widget item= findItem(entry);
if (entry.getMatchCount() == 0) {
if (item instanceof TableItem) {
TableItem ti= (TableItem)item;
disassociate(ti);
ti.dispose();
}
}
else
updateItem(item, entry);
}
/**
* Handle remove all.
*/
protected void handleRemoveAll() {
setInput(null);
}
/**
* Handle an update of an entry.
*/
protected void handleUpdateMatch(ISearchResultViewEntry entry) {
Widget item= findItem(entry);
updateItem(item, entry);
}
//--- Persistency -------------------------------------------------
void restoreState(IMemento memento) {
fSortDropDownAction.restoreState(memento);
}
void saveState(IMemento memento) {
fSortDropDownAction.saveState(memento);
}
}