/*******************************************************************************
* Copyright (c) 2007 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.seam.ui.search;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.util.TransferDragSourceListener;
import org.eclipse.jface.viewers.DecoratingLabelProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredViewer;
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.search.internal.ui.Messages;
import org.eclipse.search.internal.ui.SearchMessages;
import org.eclipse.search.internal.ui.text.EditorOpener;
import org.eclipse.search.internal.ui.text.FileLabelProvider;
import org.eclipse.search.internal.ui.text.IFileSearchContentProvider;
import org.eclipse.search.internal.ui.text.NewTextSearchActionGroup;
import org.eclipse.search.ui.IContextMenuConstants;
import org.eclipse.search.ui.ISearchResultViewPart;
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.search2.internal.ui.OpenSearchPreferencesAction;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSourceAdapter;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionContext;
import org.eclipse.ui.actions.ActionGroup;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.IPageSite;
import org.eclipse.ui.part.IShowInTargetList;
import org.eclipse.ui.part.ResourceTransfer;
import org.eclipse.ui.texteditor.ITextEditor;
import org.jboss.tools.common.java.IJavaSourceReference;
import org.jboss.tools.seam.core.IOpenableElement;
import org.jboss.tools.seam.ui.SeamGuiPlugin;
/**
* Seam Search Result page
*
* @author Jeremy
*
*/
public class SeamSearchResultPage extends AbstractTextSearchViewPage implements IAdaptable {
static class DecoratorIgnoringViewerSorter extends ViewerComparator {
private final ILabelProvider fLabelProvider;
public DecoratorIgnoringViewerSorter(ILabelProvider labelProvider) {
fLabelProvider= labelProvider;
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ViewerComparator#category(java.lang.Object)
*/
public int category(Object element) {
if (element instanceof IContainer) {
return 1;
}
return 2;
}
public int compare(Viewer viewer, Object e1, Object e2) {
int cat1 = category(e1);
int cat2 = category(e2);
if (cat1 != cat2) {
return cat1 - cat2;
}
String name1= fLabelProvider.getText(e1);
String name2= fLabelProvider.getText(e2);
if (name1 == null)
name1 = "";//$NON-NLS-1$
if (name2 == null)
name2 = "";//$NON-NLS-1$
return getComparator().compare(name1, name2);
}
}
private static final String KEY_SORTING= "org.eclipse.search.resultpage.sorting"; //$NON-NLS-1$
private static final String KEY_LIMIT= "org.eclipse.search.resultpage.limit"; //$NON-NLS-1$
private static final int DEFAULT_ELEMENT_LIMIT = 1000;
private ActionGroup fActionGroup;
private IFileSearchContentProvider fContentProvider;
private int fCurrentSortOrder;
private EditorOpener fEditorOpener= new EditorOpener();
private static final String[] SHOW_IN_TARGETS= new String[] { IPageLayout.ID_RES_NAV };
private static final IShowInTargetList SHOW_IN_TARGET_LIST= new IShowInTargetList() {
public String[] getShowInTargetIds() {
return SHOW_IN_TARGETS;
}
};
/**
* Constructs SeamSearchResultPage object
*/
public SeamSearchResultPage() {
setElementLimit(new Integer(DEFAULT_ELEMENT_LIMIT));
}
/**
* (non-Javadoc)
* @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#setElementLimit(java.lang.Integer)
*/
public void setElementLimit(Integer elementLimit) {
super.setElementLimit(elementLimit);
int limit= elementLimit.intValue();
getSettings().put(KEY_LIMIT, limit);
}
/**
* (non-Javadoc)
* @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#getViewer()
*/
public StructuredViewer getViewer() {
return super.getViewer();
}
private void addDragAdapters(StructuredViewer viewer) {
Transfer[] transfers= new Transfer[] { ResourceTransfer.getInstance() };
int ops= DND.DROP_COPY | DND.DROP_LINK;
viewer.addDragSupport(ops, transfers, new ResourceTransferDragAdapter(viewer));
}
/**
* (non-Javadoc)
* @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#configureTableViewer(org.eclipse.jface.viewers.TableViewer)
*/
protected void configureTableViewer(TableViewer viewer) {
viewer.setUseHashlookup(true);
SeamSearchViewLabelProvider innerLabelProvider= new SeamSearchViewLabelProvider(this, FileLabelProvider.SHOW_LABEL_PATH);
viewer.setLabelProvider(new DecoratingLabelProvider(innerLabelProvider, PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator()));
viewer.setContentProvider(new SeamTableContentProvider(this));
viewer.setComparator(new DecoratorIgnoringViewerSorter(innerLabelProvider));
fContentProvider= (IFileSearchContentProvider) viewer.getContentProvider();
addDragAdapters(viewer);
}
/**
* (non-Javadoc)
* @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#configureTreeViewer(org.eclipse.jface.viewers.TreeViewer)
*/
protected void configureTreeViewer(TreeViewer viewer) {
viewer.setUseHashlookup(true);
SeamSearchViewLabelProvider innerLabelProvider= new SeamSearchViewLabelProvider(this, FileLabelProvider.SHOW_LABEL_PATH);
viewer.setLabelProvider(new DecoratingLabelProvider(innerLabelProvider, PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator()));
viewer.setContentProvider(new SeamTreeContentProvider(this, viewer));
viewer.setComparator(new DecoratorIgnoringViewerSorter(innerLabelProvider));
fContentProvider= (IFileSearchContentProvider) viewer.getContentProvider();
addDragAdapters(viewer);
}
/**
* (non-Javadoc)
* @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#showMatch(org.eclipse.search.ui.text.Match, int, int, boolean)
*/
protected void showMatch(Match match, int offset, int length, boolean activate) throws PartInitException {
if (match.getElement() instanceof IJavaSourceReference) {
IJavaElement javaElement = ((IJavaSourceReference)match.getElement()).getSourceMember();
try {
IEditorPart part = JavaUI.openInEditor(javaElement);
if (part != null) {
JavaUI.revealInEditor(part, (IJavaElement)javaElement);
}
} catch (JavaModelException e) {
SeamGuiPlugin.getDefault().logError(e);
}
} else if (match.getElement() instanceof IOpenableElement) {
((IOpenableElement)match.getElement()).open();
} else if (match.getElement() instanceof IFile) {
IFile file= (IFile) match.getElement();
IEditorPart editor= fEditorOpener.open(getSite().getPage(),file, activate);
offset = match.getOffset();
length = match.getLength();
if (offset != 0 && length != 0) {
if (editor instanceof ITextEditor) {
ITextEditor textEditor= (ITextEditor) editor;
textEditor.selectAndReveal(offset, length);
} else if (editor != null) {
showWithMarker(editor, file, offset, length);
}
}
} else if (match.getElement() instanceof IJavaElement) {
IJavaElement javaElement = (IJavaElement)match.getElement();
try {
IEditorPart part = JavaUI.openInEditor(javaElement);
if (part != null) {
JavaUI.revealInEditor(part, (IJavaElement)javaElement);
}
} catch (JavaModelException e) {
SeamGuiPlugin.getDefault().logError(e);
}
}
}
private void showWithMarker(IEditorPart editor, IFile file, int offset, int length) throws PartInitException {
IMarker marker= null;
try {
marker= file.createMarker(NewSearchUI.SEARCH_MARKER);
HashMap attributes= new HashMap(4);
attributes.put(IMarker.CHAR_START, new Integer(offset));
attributes.put(IMarker.CHAR_END, new Integer(offset + length));
marker.setAttributes(attributes);
IDE.gotoMarker(editor, marker);
} catch (CoreException e) {
throw new PartInitException(SearchMessages.FileSearchPage_error_marker, e);
} finally {
if (marker != null)
try {
marker.delete();
} catch (CoreException e) {
SeamGuiPlugin.getDefault().logError(e);
}
}
}
/**
* (non-Javadoc)
* @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#fillContextMenu(org.eclipse.jface.action.IMenuManager)
*/
protected void fillContextMenu(IMenuManager mgr) {
super.fillContextMenu(mgr);
addSortActions(mgr);
fActionGroup.setContext(new ActionContext(getSite().getSelectionProvider().getSelection()));
fActionGroup.fillContextMenu(mgr);
}
private void addSortActions(IMenuManager mgr) {
if (getLayout() != FLAG_LAYOUT_FLAT)
return;
MenuManager sortMenu= new MenuManager(SearchMessages.FileSearchPage_sort_by_label);
mgr.appendToGroup(IContextMenuConstants.GROUP_VIEWER_SETUP, sortMenu);
}
/**
* (non-Javadoc)
* @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#setViewPart(org.eclipse.search.ui.ISearchResultViewPart)
*/
public void setViewPart(ISearchResultViewPart part) {
super.setViewPart(part);
fActionGroup= new NewTextSearchActionGroup(part);
}
/**
* (non-Javadoc)
* @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#init(org.eclipse.ui.part.IPageSite)
*/
public void init(IPageSite site) {
super.init(site);
IMenuManager menuManager = site.getActionBars().getMenuManager();
menuManager.appendToGroup(IContextMenuConstants.GROUP_PROPERTIES, new OpenSearchPreferencesAction());
}
/**
* (non-Javadoc)
* @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#dispose()
*/
public void dispose() {
fActionGroup.dispose();
super.dispose();
}
/**
* (non-Javadoc)
* @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#elementsChanged(java.lang.Object[])
*/
protected void elementsChanged(Object[] objects) {
if (fContentProvider != null)
fContentProvider.elementsChanged(objects);
}
/**
* (non-Javadoc)
* @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#clear()
*/
protected void clear() {
if (fContentProvider != null)
fContentProvider.clear();
}
/**
* Sets up a given sort order
*
* @param sortOrder
*/
public void setSortOrder(int sortOrder) {
fCurrentSortOrder= sortOrder;
DecoratingLabelProvider lpWrapper= (DecoratingLabelProvider) getViewer().getLabelProvider();
((FileLabelProvider) lpWrapper.getLabelProvider()).setOrder(sortOrder);
getViewer().refresh();
getSettings().put(KEY_SORTING, fCurrentSortOrder);
}
/**
* (non-Javadoc)
* @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#restoreState(org.eclipse.ui.IMemento)
*/
public void restoreState(IMemento memento) {
super.restoreState(memento);
try {
fCurrentSortOrder= getSettings().getInt(KEY_SORTING);
} catch (NumberFormatException e) {
// Ignore
}
int elementLimit= DEFAULT_ELEMENT_LIMIT;
try {
elementLimit= getSettings().getInt(KEY_LIMIT);
} catch (NumberFormatException e) {
}
if (memento != null) {
Integer value= memento.getInteger(KEY_SORTING);
if (value != null)
fCurrentSortOrder= value.intValue();
value= memento.getInteger(KEY_LIMIT);
if (value != null)
elementLimit= value.intValue();
}
setElementLimit(new Integer(elementLimit));
}
/**
* (non-Javadoc)
* @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#saveState(org.eclipse.ui.IMemento)
*/
public void saveState(IMemento memento) {
super.saveState(memento);
memento.putInteger(KEY_SORTING, fCurrentSortOrder);
memento.putInteger(KEY_LIMIT, getElementLimit().intValue());
}
/**
* (non-Javadoc)
* @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
*/
public Object getAdapter(Class adapter) {
if (IShowInTargetList.class.equals(adapter)) {
return SHOW_IN_TARGET_LIST;
}
return null;
}
/**
* (non-Javadoc)
* @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#getLabel()
*/
public String getLabel() {
String label= super.getLabel();
StructuredViewer viewer= getViewer();
if (viewer instanceof TableViewer) {
TableViewer tv= (TableViewer) viewer;
AbstractTextSearchResult result= getInput();
if (result != null) {
int itemCount= ((IStructuredContentProvider) tv.getContentProvider()).getElements(getInput()).length;
int fileCount= getInput().getElements().length;
if (itemCount < fileCount) {
String format= SearchMessages.FileSearchPage_limited_format_files;
return Messages.format(format, new Object[]{label, new Integer(itemCount), new Integer(fileCount)});
}
}
}
return label;
}
/** copy from Eclipse 3.3 org.eclipse.search.internal.ui.text.ResourceTransferDragAdapter */
/** Maybe NavigatorDragAdopter would be a better alternative. */
static public class ResourceTransferDragAdapter extends DragSourceAdapter implements TransferDragSourceListener {
private ISelectionProvider fProvider;
/**
* Creates a new ResourceTransferDragAdapter for the given selection
* provider.
*
* @param provider the selection provider to access the viewer's selection
*/
public ResourceTransferDragAdapter(ISelectionProvider provider) {
fProvider= provider;
Assert.isNotNull(fProvider);
}
public Transfer getTransfer() {
return ResourceTransfer.getInstance();
}
public void dragStart(DragSourceEvent event) {
event.doit= !convertSelection().isEmpty();
}
public void dragSetData(DragSourceEvent event) {
List resources= convertSelection();
event.data= resources.toArray(new IResource[resources.size()]);
}
public void dragFinished(DragSourceEvent event) {
if (!event.doit)
return;
}
private List convertSelection() {
ISelection s= fProvider.getSelection();
if (!(s instanceof IStructuredSelection))
return Collections.EMPTY_LIST;
IStructuredSelection selection= (IStructuredSelection) s;
List result= new ArrayList(selection.size());
for (Iterator iter= selection.iterator(); iter.hasNext();) {
Object element= iter.next();
if (element instanceof IResource) {
result.add(element);
}
}
return result;
}
}
}