blob: 7b15dd3590e6c0949bf329ac796aa7ba0c845c2f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
******************************************************************************/
package org.eclipse.ui.internal.views.markers;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.mapping.ResourceMapping;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.help.IContext;
import org.eclipse.help.IContextProvider;
import org.eclipse.jface.action.ContributionManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.OpenStrategy;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.ColumnPixelData;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.SameShellProvider;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.events.HelpEvent;
import org.eclipse.swt.events.HelpListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.TreeAdapter;
import org.eclipse.swt.events.TreeEvent;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Scrollable;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.ide.ResourceUtil;
import org.eclipse.ui.internal.ide.IDEInternalPreferences;
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
import org.eclipse.ui.internal.ide.StatusUtil;
import org.eclipse.ui.menus.IMenuService;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
import org.eclipse.ui.progress.WorkbenchJob;
import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.ui.views.markers.MarkerField;
import org.eclipse.ui.views.markers.MarkerItem;
import org.eclipse.ui.views.markers.MarkerSupportConstants;
import org.eclipse.ui.views.markers.internal.MarkerGroup;
import org.eclipse.ui.views.markers.internal.MarkerMessages;
import org.eclipse.ui.views.markers.internal.MarkerSupportRegistry;
import org.eclipse.ui.views.tasklist.ITaskListResourceAdapter;
/**
* The ExtendedMarkersView is the internal implementation of the view that shows
* markers using the markerGenerators extension point.
*
* The ExtendedMarkersView fully supports the markerSupport extension point and
* is meant to be used as a view to complement them.
*
* The markerContentGenerators to be used by the view can be specified by
* appending a comma separated list of them after a colon in the class
* specification of the view. If this list is left out the problems
* markerContentProvider will be used.
*
* @since 3.4
*
*/
public class ExtendedMarkersView extends ViewPart {
/**
* MarkerSelectionEntry is a cache of the values for a marker entry.
*
* @since 3.4
*
*/
final class MarkerSelectionEntry {
Object[] cachedValues;
MarkerSelectionEntry(MarkerItem item) {
MarkerField[] fields = builder.getVisibleFields();
cachedValues = new Object[fields.length];
for (int i = 0; i < fields.length; i++) {
cachedValues[i] = fields[i].getValue(item);
}
}
/**
* Return whether or not the entry is equivalent to the cached state.
*
* @param item
* @return boolean <code>true</code> if they are equivalent
*/
boolean isEquivalentTo(MarkerItem item) {
MarkerField[] fields = builder.getVisibleFields();
if (cachedValues.length != fields.length)
return false;
for (int i = 0; i < fields.length; i++) {
if (cachedValues[i] == fields[i].getValue(item))
continue;
return false;
}
return true;
}
}
private static int instanceCount = 0;
private static final String TAG_GENERATOR = "markerContentGenerator"; //$NON-NLS-1$
private static final String TAG_HORIZONTAL_POSITION = "horizontalPosition"; //$NON-NLS-1$
private static final String TAG_VERTICAL_POSITION = "verticalPosition"; //$NON-NLS-1$
private static final String MARKER_FIELD = "MARKER_FIELD"; //$NON-NLS-1$
private static final String TAG_EXPANDED = "expanded"; //$NON-NLS-1$
private static final String TAG_CATEGORY = "category"; //$NON-NLS-1$
private static final String TAG_PART_NAME = "partName"; //$NON-NLS-1$
static {
Platform.getAdapterManager().registerAdapters(new IAdapterFactory() {
/*
* (non-Javadoc)
*
* @see org.eclipse.core.runtime.IAdapterFactory#getAdapter(java.lang.Object,
* java.lang.Class)
*/
public Object getAdapter(Object adaptableObject, Class adapterType) {
if (adapterType == IMarker.class
&& adaptableObject instanceof MarkerEntry)
return ((MarkerEntry) adaptableObject).getMarker();
return null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.core.runtime.IAdapterFactory#getAdapterList()
*/
public Class[] getAdapterList() {
return new Class[] { IMarker.class };
}
}, MarkerEntry.class);
}
/**
* Return the next secondary id.
*
* @return String
*/
static String newSecondaryID() {
return String.valueOf(instanceCount);
}
/**
* Open the supplied marker in an editor in page
*
* @param marker
* @param page
*/
public static void openMarkerInEditor(IMarker marker, IWorkbenchPage page) {
// optimization: if the active editor has the same input as
// the
// selected marker then
// RevealMarkerAction would have been run and we only need
// to
// activate the editor
IEditorPart editor = page.getActiveEditor();
if (editor != null) {
IEditorInput input = editor.getEditorInput();
IFile file = ResourceUtil.getFile(input);
if (file != null) {
if (marker.getResource().equals(file)) {
page.activate(editor);
}
}
}
if (marker != null && marker.getResource() instanceof IFile) {
try {
IDE.openEditor(page, marker, OpenStrategy.activateOnOpen());
} catch (PartInitException e) {
// Check for a nested CoreException
IStatus status = e.getStatus();
if (status != null
&& status.getException() instanceof CoreException) {
status = ((CoreException) status.getException())
.getStatus();
}
if (status == null)
StatusManager.getManager().handle(
StatusUtil.newStatus(IStatus.ERROR, e.getMessage(),
e), StatusManager.SHOW);
else
StatusManager.getManager().handle(status,
StatusManager.SHOW);
}
}
}
private CachedMarkerBuilder builder;
Collection categoriesToExpand;
private Clipboard clipboard;
Collection preservedSelection = new ArrayList();
private Job updateJob;
private MarkersTreeViewer viewer;
private IPropertyChangeListener preferenceListener;
private ISelectionListener pageSelectionListener;
private IPartListener2 partListener;
private IMemento memento;
private String[] defaultGeneratorIds = new String[0];
/**
* Return a new instance of the receiver.
*
* @param contentGeneratorId
* the id of the generator to load.
*/
public ExtendedMarkersView(String contentGeneratorId) {
super();
instanceCount++;
defaultGeneratorIds = new String[] { contentGeneratorId };
preferenceListener = new IPropertyChangeListener() {
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
*/
public void propertyChange(PropertyChangeEvent event) {
String propertyName = event.getProperty();
if (propertyName
.equals(IDEInternalPreferences.USE_MARKER_LIMITS)
|| propertyName
.equals(IDEInternalPreferences.MARKER_LIMITS_VALUE)) {
viewer.refresh();
updateTitle();
}
}
};
IDEWorkbenchPlugin.getDefault().getPreferenceStore()
.addPropertyChangeListener(preferenceListener);
}
/**
* Add all concrete {@link MarkerItem} elements associated with the receiver
* to allMarkers.
*
* @param markerItem
* @param allMarkers
*/
private void addAllConcreteItems(MarkerItem markerItem,
Collection allMarkers) {
if (markerItem.isConcrete()) {
allMarkers.add(markerItem);
return;
}
MarkerItem[] children = markerItem.getChildren();
for (int i = 0; i < children.length; i++) {
addAllConcreteItems(children[i], allMarkers);
}
}
/**
* Add the category to the list of expanded categories.
*
* @param category
*/
void addExpandedCategory(MarkerCategory category) {
getCategoriesToExpand().add(category.getName());
}
/**
* Add all of the markers in markerItem recursively.
*
* @param markerItem
* @param allMarkers
* {@link Collection} of {@link IMarker}
*/
private void addMarkers(MarkerItem markerItem, Collection allMarkers) {
if (markerItem.getMarker() != null)
allMarkers.add(markerItem.getMarker());
MarkerItem[] children = markerItem.getChildren();
for (int i = 0; i < children.length; i++) {
addMarkers(children[i], allMarkers);
}
}
/**
* Create the columns for the receiver.
*
* @param currentColumns
* the columns to refresh
*/
private void createColumns(TreeColumn[] currentColumns) {
Tree tree = viewer.getTree();
TableLayout layout = new TableLayout();
MarkerField[] fields = builder.getVisibleFields();
for (int i = 0; i < fields.length; i++) {
MarkerField markerField = fields[i];
// Take into account the expansion indicator
int columnWidth = markerField.getDefaultColumnWidth(tree);
if (i == 0) {
// Compute and store a font metric
GC gc = new GC(tree);
gc.setFont(tree.getFont());
FontMetrics fontMetrics = gc.getFontMetrics();
gc.dispose();
columnWidth = Math.max(columnWidth, fontMetrics
.getAverageCharWidth() * 5);
}
layout.addColumnData(new ColumnPixelData(columnWidth, true, true));
TreeViewerColumn column;
if (i < currentColumns.length)
column = new TreeViewerColumn(viewer, currentColumns[i]);
else {
column = new TreeViewerColumn(viewer, SWT.NONE);
column.getColumn().setResizable(true);
column.getColumn().setMoveable(true);
column.getColumn().addSelectionListener(getHeaderListener());
}
column.getColumn().setData(MARKER_FIELD, markerField);
// Show the help in the first column
column.setLabelProvider(new MarkerColumnLabelProvider(markerField));
column.getColumn().setText(markerField.getColumnHeaderText());
column.getColumn().setToolTipText(
markerField.getColumnTooltipText());
column.getColumn().setImage(markerField.getColumnHeaderImage());
EditingSupport support = markerField.getEditingSupport(viewer);
if (support != null)
column.setEditingSupport(support);
if (builder.getPrimarySortField().equals(markerField))
updateDirectionIndicator(column.getColumn(), markerField);
}
// Remove extra columns
if (currentColumns.length > fields.length) {
for (int i = fields.length; i < currentColumns.length; i++) {
currentColumns[i].dispose();
}
}
viewer.getTree().setLayout(layout);
tree.setLinesVisible(true);
tree.setHeaderVisible(true);
tree.layout(true);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
*/
public void createPartControl(Composite parent) {
parent.setLayout(new FillLayout());
viewer = new MarkersTreeViewer(new Tree(parent, SWT.H_SCROLL
| SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION));
viewer.getTree().setLinesVisible(true);
viewer.setUseHashlookup(true);
createColumns(new TreeColumn[0]);
viewer.setContentProvider(getContentProvider());
getSite().setSelectionProvider(viewer);
viewer.setInput(builder);
if (memento != null) {
Scrollable scrollable = (Scrollable) viewer.getControl();
ScrollBar bar = scrollable.getVerticalBar();
if (bar != null) {
Integer position = memento.getInteger(TAG_VERTICAL_POSITION);
if (position != null)
bar.setSelection(position.intValue());
}
bar = scrollable.getHorizontalBar();
if (bar != null) {
Integer position = memento.getInteger(TAG_HORIZONTAL_POSITION);
if (position != null)
bar.setSelection(position.intValue());
}
}
// Initialise any selection based filtering
pageSelectionListener = getPageSelectionListener();
getSite().getPage().addPostSelectionListener(pageSelectionListener);
partListener = getPartListener();
getSite().getPage().addPartListener(partListener);
pageSelectionListener.selectionChanged(getSite().getPage()
.getActivePart(), getSite().getPage().getSelection());
viewer.addOpenListener(new IOpenListener() {
public void open(OpenEvent event) {
openSelectedMarkers();
}
});
viewer.getTree().addTreeListener(new TreeAdapter() {
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.events.TreeAdapter#treeCollapsed(org.eclipse.swt.events.TreeEvent)
*/
public void treeCollapsed(TreeEvent e) {
removeExpandedCategory((MarkerCategory) e.item.getData());
}
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.events.TreeAdapter#treeExpanded(org.eclipse.swt.events.TreeEvent)
*/
public void treeExpanded(TreeEvent e) {
addExpandedCategory((MarkerCategory) e.item.getData());
}
});
// Set help on the view itself
viewer.getControl().addHelpListener(new HelpListener() {
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.events.HelpListener#helpRequested(org.eclipse.swt.events.HelpEvent)
*/
public void helpRequested(HelpEvent e) {
Object provider = getAdapter(IContextProvider.class);
if (provider == null)
return;
IContext context = ((IContextProvider) provider)
.getContext(viewer.getControl());
PlatformUI.getWorkbench().getHelpSystem().displayHelp(context);
}
});
registerContextMenu();
}
/**
* Return a part listener for the receiver.
*
* @return IPartListener2
*/
private IPartListener2 getPartListener() {
return new IPartListener2() {
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IPartListener2#partActivated(org.eclipse.ui.IWorkbenchPartReference)
*/
public void partActivated(IWorkbenchPartReference partRef) {
// Do nothing by default
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IPartListener2#partBroughtToTop(org.eclipse.ui.IWorkbenchPartReference)
*/
public void partBroughtToTop(IWorkbenchPartReference partRef) {
// Do nothing by default
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IPartListener2#partClosed(org.eclipse.ui.IWorkbenchPartReference)
*/
public void partClosed(IWorkbenchPartReference partRef) {
// Do nothing by default
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IPartListener2#partDeactivated(org.eclipse.ui.IWorkbenchPartReference)
*/
public void partDeactivated(IWorkbenchPartReference partRef) {
// Do nothing by default
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IPartListener2#partHidden(org.eclipse.ui.IWorkbenchPartReference)
*/
public void partHidden(IWorkbenchPartReference partRef) {
// Do nothing by default
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IPartListener2#partInputChanged(org.eclipse.ui.IWorkbenchPartReference)
*/
public void partInputChanged(IWorkbenchPartReference partRef) {
// Do nothing by default
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IPartListener2#partOpened(org.eclipse.ui.IWorkbenchPartReference)
*/
public void partOpened(IWorkbenchPartReference partRef) {
// Do nothing by default
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IPartListener2#partVisible(org.eclipse.ui.IWorkbenchPartReference)
*/
public void partVisible(IWorkbenchPartReference partRef) {
if (partRef.getId().equals(
ExtendedMarkersView.this.getSite().getId())) {
pageSelectionListener.selectionChanged(getSite().getPage()
.getActivePart(), getSite().getPage()
.getSelection());
}
}
};
}
public void dispose() {
super.dispose();
updateJob.cancel();
instanceCount--;
if (clipboard != null)
clipboard.dispose();
IDEWorkbenchPlugin.getDefault().getPreferenceStore()
.removePropertyChangeListener(preferenceListener);
getSite().getPage().removePostSelectionListener(pageSelectionListener);
getSite().getPage().removePartListener(partListener);
}
/**
* Return all of the marker items in the receiver that are concrete.
*
* @return MarkerItem[]
*/
MarkerItem[] getAllConcreteItems() {
MarkerItem[] elements = builder.getElements();
Collection allMarkers = new ArrayList();
for (int i = 0; i < elements.length; i++) {
addAllConcreteItems(elements[i], allMarkers);
}
MarkerItem[] markers = new MarkerItem[allMarkers.size()];
allMarkers.toArray(markers);
return markers;
}
/**
* Get all of the filters for the receiver.
*
* @return Collection of {@link MarkerFieldFilterGroup}
*/
Collection getAllFilters() {
return builder.getAllFilters();
}
/**
* Return all of the markers in the receiver.
*
* @return IMarker[]
*/
IMarker[] getAllMarkers() {
MarkerItem[] elements = builder.getElements();
Collection allMarkers = new ArrayList();
for (int i = 0; i < elements.length; i++) {
addMarkers(elements[i], allMarkers);
}
IMarker[] markers = new IMarker[allMarkers.size()];
allMarkers.toArray(markers);
return markers;
}
/**
* Return the group used for categorisation.
*
* @return MarkerGroup
*/
MarkerGroup getCategoryGroup() {
return builder.getCategoryGroup();
}
/**
* Return the clipboard for the receiver.
*
* @return Clipboard
*/
Clipboard getClipboard() {
if (clipboard == null)
clipboard = new Clipboard(viewer.getControl().getDisplay());
return clipboard;
}
/**
* Return the content provider for the receiver.
*
* @return ITreeContentProvider
*
*/
private ITreeContentProvider getContentProvider() {
return new ITreeContentProvider() {
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.IContentProvider#dispose()
*/
public void dispose() {
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ILazyTreeContentProvider#updateChildCount(java.lang.Object,
* int)
*/
// public void updateChildCount(Object element, int
// currentChildCount) {
//
// int length;
// if (element instanceof MarkerItem)
// length = ((MarkerItem) element).getChildren().length;
// else
// // If it is not a MarkerItem it is the root
// length = ((CachedMarkerBuilder) element).getElements().length;
//
// int markerLimit = MarkerSupportInternalUtilities
// .getMarkerLimit();
// length = markerLimit > 0 ? Math.min(length, markerLimit)
// : length;
// if (currentChildCount == length)
// return;
// viewer.setChildCount(element, length);
//
// }
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ILazyTreeContentProvider#updateElement(java.lang.Object,
* int)
*/
// public void updateElement(Object parent, int index) {
// MarkerItem newItem;
//
// if (parent instanceof MarkerItem)
// newItem = ((MarkerItem) parent).getChildren()[index];
// else
// newItem = ((CachedMarkerBuilder) parent).getElements()[index];
//
// viewer.replace(parent, index, newItem);
// updateChildCount(newItem, -1);
//
// if (!newItem.isConcrete()
// && categoriesToExpand
// .contains(((MarkerCategory) newItem).getName())) {
// viewer.expandToLevel(newItem, 1);
// categoriesToExpand.remove(newItem);
// }
//
// }
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
*/
public Object[] getChildren(Object parentElement) {
MarkerItem[] children = ((MarkerItem) parentElement)
.getChildren();
return getLimitedChildren(children);
}
/**
* Get the children limited by the marker limits.
*
* @param children
* @return Object[]
*/
private Object[] getLimitedChildren(Object[] children) {
int newLength = MarkerSupportInternalUtilities.getMarkerLimit();
if (newLength > 0 && newLength < children.length) {
Object[] newChildren = new Object[newLength];
System.arraycopy(children, 0, newChildren, 0, newLength);
return newChildren;
}
return children;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
*/
public Object[] getElements(Object inputElement) {
return getLimitedChildren(((CachedMarkerBuilder) inputElement)
.getElements());
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ILazyTreeContentProvider#getParent(java.lang.Object)
*/
public Object getParent(Object element) {
Object parent = ((MarkerItem) element).getParent();
if (parent == null)
return builder;
return parent;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
*/
public boolean hasChildren(Object element) {
return ((MarkerItem) element).getChildren().length > 0;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer,
* java.lang.Object, java.lang.Object)
*/
public void inputChanged(Viewer viewer, Object oldInput,
Object newInput) {
}
};
}
/**
* Return the listener that updates sort values on selection.
*
* @return SelectionListener
*/
private SelectionListener getHeaderListener() {
return new SelectionAdapter() {
/**
* Handles the case of user selecting the header area.
*/
public void widgetSelected(SelectionEvent e) {
final TreeColumn column = (TreeColumn) e.widget;
final MarkerField field = (MarkerField) column
.getData(MARKER_FIELD);
setPrimarySortField(field, column);
}
};
}
/**
* Return the selection listener for the page selection change.
*
* @return ISelectionListener
*/
private ISelectionListener getPageSelectionListener() {
return new ISelectionListener() {
/**
* Get an ITaskListResourceAdapter for use by the default/
*
* @return ITaskListResourceAdapter
*/
private ITaskListResourceAdapter getDefaultTaskListAdapter() {
return new ITaskListResourceAdapter() {
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.views.tasklist.ITaskListResourceAdapter#getAffectedResource(org.eclipse.core.runtime.IAdaptable)
*/
public IResource getAffectedResource(IAdaptable adaptable) {
Object resource = adaptable.getAdapter(IResource.class);
if (resource == null)
resource = adaptable.getAdapter(IFile.class);
if (resource == null)
return null;
return (IResource) resource;
}
};
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart,
* org.eclipse.jface.viewers.ISelection)
*/
public void selectionChanged(IWorkbenchPart part,
ISelection selection) {
// Do not respond to our own selections or if we are not
// visible
if (part == ExtendedMarkersView.this
|| !(getSite().getPage().isPartVisible(part)))
return;
List selectedElements = new ArrayList();
if (part instanceof IEditorPart) {
IEditorPart editor = (IEditorPart) part;
IFile file = ResourceUtil.getFile(editor.getEditorInput());
if (file == null) {
IEditorInput editorInput = editor.getEditorInput();
if (editorInput != null) {
Object mapping = editorInput
.getAdapter(ResourceMapping.class);
if (mapping != null) {
selectedElements.add(mapping);
}
}
} else {
selectedElements.add(file);
}
} else {
if (selection instanceof IStructuredSelection) {
for (Iterator iterator = ((IStructuredSelection) selection)
.iterator(); iterator.hasNext();) {
Object object = iterator.next();
if (object instanceof IAdaptable) {
ITaskListResourceAdapter taskListResourceAdapter;
Object adapter = ((IAdaptable) object)
.getAdapter(ITaskListResourceAdapter.class);
if (adapter != null
&& adapter instanceof ITaskListResourceAdapter) {
taskListResourceAdapter = (ITaskListResourceAdapter) adapter;
} else {
taskListResourceAdapter = getDefaultTaskListAdapter();
}
IResource resource = taskListResourceAdapter
.getAffectedResource((IAdaptable) object);
if (resource == null) {
Object mapping = ((IAdaptable) object)
.getAdapter(ResourceMapping.class);
if (mapping != null) {
selectedElements.add(mapping);
}
} else {
selectedElements.add(resource);
}
}
}
}
}
builder.updateForNewSelection(selectedElements.toArray());
}
};
}
/**
* Return all of the markers in the current selection
*
* @return Array of {@link IMarker}
*/
public IMarker[] getSelectedMarkers() {
ISelection selection = viewer.getSelection();
if (selection instanceof IStructuredSelection) {
IStructuredSelection structured = (IStructuredSelection) selection;
Iterator elements = structured.iterator();
Collection result = new ArrayList();
while (elements.hasNext()) {
MarkerItem next = (MarkerItem) elements.next();
if (next.isConcrete())
result.add(((MarkerEntry) next).getMarker());
}
if (result.isEmpty())
return MarkerSupportInternalUtilities.EMPTY_MARKER_ARRAY;
IMarker[] markers = new IMarker[result.size()];
result.toArray(markers);
return markers;
}
return MarkerSupportInternalUtilities.EMPTY_MARKER_ARRAY;
}
/**
* Return the sort direction.
*
* @return boolean
*/
public boolean getSortAscending() {
return viewer.getTree().getSortDirection() == SWT.TOP;
}
/**
* Return a job for updating the receiver.
*
* @return Job
*/
private Job getUpdateJob(final CachedMarkerBuilder builder) {
updateJob = new WorkbenchJob(MarkerMessages.MarkerView_queueing_updates) {
/*
* (non-Javadoc)
*
* @see org.eclipse.core.runtime.jobs.Job#belongsTo(java.lang.Object)
*/
public boolean belongsTo(Object family) {
return family == MarkerContentGenerator.CACHE_UPDATE_FAMILY;
}
/**
* Return the viewer that is being updated.
*
* @return TreeViewer
*/
private TreeViewer getViewer() {
return viewer;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
*/
public IStatus runInUIThread(IProgressMonitor monitor) {
if (viewer.getControl().isDisposed()) {
return Status.CANCEL_STATUS;
}
if (monitor.isCanceled())
return Status.CANCEL_STATUS;
// If there is only one category and the user has no saved state
// show it
if (builder.isShowingHierarchy()
&& getCategoriesToExpand().isEmpty()) {
MarkerCategory[] categories = builder.getCategories();
if (categories != null && categories.length == 1)
getCategoriesToExpand().add(categories[0].getName());
}
getViewer().refresh(true);
updateTitle();
if (preservedSelection.size() > 0) {
Collection newSelection = new ArrayList();
MarkerItem[] markerEntries = builder.getMarkerEntries();
for (int i = 0; i < markerEntries.length; i++) {
Iterator preserved = preservedSelection.iterator();
while (preserved.hasNext()) {
MarkerSelectionEntry next = (MarkerSelectionEntry) preserved
.next();
if (next.isEquivalentTo(markerEntries[i])) {
newSelection.add(markerEntries[i]);
continue;
}
}
}
getViewer().setSelection(
new StructuredSelection(newSelection.toArray()),
true);
preservedSelection.clear();
}
if (getViewer().getTree().getItemCount() > 0)
getViewer().getTree().setTopItem(
getViewer().getTree().getItem(0));
reexpandCategories(builder);
return Status.OK_STATUS;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.progress.WorkbenchJob#shouldRun()
*/
public boolean shouldRun() {
return !builder.isBuilding();
}
};
updateJob.setSystem(true);
return updateJob;
}
/**
* Return the object that is the input to the viewer.
*
* @return Object
*/
Object getViewerInput() {
return viewer.getInput();
}
/**
* Get all of the fields visible in the receiver.
*
* @return MarkerField[]
*/
MarkerField[] getVisibleFields() {
return builder.getVisibleFields();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.part.ViewPart#init(org.eclipse.ui.IViewSite,
* org.eclipse.ui.IMemento)
*/
public void init(IViewSite site, IMemento memento) throws PartInitException {
super.init(site, memento);
MarkerContentGenerator generator = null;
if (memento != null) {
generator = MarkerSupportRegistry.getInstance().getGenerator(
memento.getString(TAG_GENERATOR));
}
if (generator == null && defaultGeneratorIds.length > 0) {
generator = MarkerSupportRegistry.getInstance().getGenerator(
defaultGeneratorIds[0]);
if (generator == null)
logInvalidGenerator(defaultGeneratorIds[0]);
}
if (generator == null)
generator = MarkerSupportRegistry.getInstance()
.getDefaultGenerator();
// Add in the entries common to all markers views
IMenuService menuService = (IMenuService) site
.getService(IMenuService.class);
// Add in the markers view actions
menuService.populateContributionManager((ContributionManager) site
.getActionBars().getMenuManager(), "menu:" //$NON-NLS-1$
+ MarkerSupportRegistry.MARKERS_ID);
menuService.populateContributionManager((ContributionManager) site
.getActionBars().getToolBarManager(),
"toolbar:" + MarkerSupportRegistry.MARKERS_ID); //$NON-NLS-1$
String viewId = site.getId();
if (site.getSecondaryId() != null) {
viewId = viewId + site.getSecondaryId();
}
builder = new CachedMarkerBuilder(generator, viewId, memento);
builder.setUpdateJob(getUpdateJob(builder));
Object service = site.getAdapter(IWorkbenchSiteProgressService.class);
if (service != null)
builder.setProgressService((IWorkbenchSiteProgressService) service);
this.memento = memento;
if(memento == null || memento.getString(TAG_PART_NAME) == null)
return;
setPartName(memento.getString(TAG_PART_NAME));
}
/**
* Log that a generator id is invalid.
*
* @param id
*/
void logInvalidGenerator(String id) {
StatusManager.getManager().handle(
new Status(IStatus.WARNING, IDEWorkbenchPlugin.IDE_WORKBENCH,
NLS.bind("Invalid markerContentGenerator {0} ", //$NON-NLS-1$
id)));
}
/**
* Return whether or not group is enabled.
*
* @param group
* @return boolean
*/
boolean isEnabled(MarkerFieldFilterGroup group) {
return builder.getEnabledFilters().contains(group);
}
/**
* Return the main sort field for the receiver.
*
* @return {@link MarkerField}
*/
boolean isPrimarySortField(MarkerField field) {
return builder.getPrimarySortField().equals(field);
}
/**
* Return whether or not generator is the selected one.
*
* @param generator
* @return boolean
*/
boolean isShowing(MarkerContentGenerator generator) {
return this.builder.getGenerator().equals(generator);
}
/**
* Open the filters dialog for the receiver.
*/
void openFiltersDialog() {
FiltersConfigurationDialog dialog = new FiltersConfigurationDialog(
new SameShellProvider(getSite().getWorkbenchWindow().getShell()),
builder);
if (dialog.open() == Window.OK) {
builder.updateFrom(dialog);
}
}
/**
* Open the selected markers
*/
void openSelectedMarkers() {
IMarker[] markers = getSelectedMarkers();
for (int i = 0; i < markers.length; i++) {
IMarker marker = markers[i];
IWorkbenchPage page = getSite().getPage();
openMarkerInEditor(marker, page);
}
}
/**
* Register the context menu for the receiver so that commands may be added
* to it.
*/
private void registerContextMenu() {
MenuManager contextMenu = new MenuManager();
contextMenu.setRemoveAllWhenShown(true);
getSite().registerContextMenu(contextMenu, viewer);
// Add in the entries for all markers views if this has a different if
if (!getSite().getId().equals(MarkerSupportRegistry.MARKERS_ID))
getSite().registerContextMenu(MarkerSupportRegistry.MARKERS_ID,
contextMenu, viewer);
Control control = viewer.getControl();
Menu menu = contextMenu.createContextMenu(control);
control.setMenu(menu);
}
/**
* Remove the category from the list of expanded ones.
*
* @param category
*/
void removeExpandedCategory(MarkerCategory category) {
getCategoriesToExpand().remove(category.getName());
}
/**
* Preserve the selection for re-selection after the next update.
*
* @param selection
*/
void saveSelection(ISelection selection) {
preservedSelection.clear();
if (selection instanceof IStructuredSelection) {
IStructuredSelection structured = (IStructuredSelection) selection;
Iterator iterator = structured.iterator();
while (iterator.hasNext()) {
MarkerItem next = (MarkerItem) iterator.next();
if (next.isConcrete()) {
preservedSelection.add(new MarkerSelectionEntry(next));
getCategoriesToExpand().add(next.getParent());
} else
getCategoriesToExpand().add(next);
}
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.part.ViewPart#saveState(org.eclipse.ui.IMemento)
*/
public void saveState(IMemento memento) {
super.saveState(memento);
memento.putString(TAG_GENERATOR, builder.getGenerator().getId());
memento.putString(TAG_PART_NAME, getPartName());
if (!getCategoriesToExpand().isEmpty()) {
IMemento expanded = memento.createChild(TAG_EXPANDED);
Iterator categories = getCategoriesToExpand().iterator();
while (categories.hasNext()) {
expanded.createChild(TAG_CATEGORY, (String) categories.next());
}
}
builder.saveState(memento);
}
/**
* Select all of the elements in the receiver.
*/
void selectAll() {
viewer.getTree().selectAll();
}
/**
* Set the category group for the receiver.
*
* @param group
*/
void setCategoryGroup(MarkerGroup group) {
getCategoriesToExpand().clear();
builder.setCategoryGroup(group);
}
/**
* Set the content generator for the receiver.
*
* @param generator
*/
void setContentGenerator(MarkerContentGenerator generator) {
viewer.setSelection(new StructuredSelection());
viewer.removeAndClearAll();
builder.setGenerator(generator);
createColumns(viewer.getTree().getColumns());
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.part.WorkbenchPart#setFocus()
*/
public void setFocus() {
viewer.getControl().setFocus();
}
/**
* Set the primary sort field
*
* @param field
*/
void setPrimarySortField(MarkerField field) {
TreeColumn[] columns = viewer.getTree().getColumns();
for (int i = 0; i < columns.length; i++) {
TreeColumn treeColumn = columns[i];
if (columns[i].getData(MARKER_FIELD).equals(field)) {
setPrimarySortField(field, treeColumn);
return;
}
}
StatusManager.getManager().handle(
StatusUtil.newStatus(IStatus.WARNING,
"Sorting by non visible field " //$NON-NLS-1$
+ field.getColumnHeaderText(), null));
}
/**
* Set the primary sort field to field and update the column.
*
* @param field
* @param column
*/
private void setPrimarySortField(MarkerField field, TreeColumn column) {
builder.setPrimarySortField(field);
IWorkbenchSiteProgressService service = (IWorkbenchSiteProgressService) getViewSite()
.getAdapter(IWorkbenchSiteProgressService.class);
builder.refreshContents(service);
updateDirectionIndicator(column, field);
viewer.refresh();
reexpandCategories(builder);
}
/**
* Add group to the enabled filters.
*
* @param group
*/
void toggleFilter(MarkerFieldFilterGroup group) {
builder.toggleFilter(group);
}
/**
* Toggle the sort direction of the primary field
*/
void toggleSortDirection() {
setPrimarySortField(builder.getPrimarySortField());
}
/**
* Update the direction indicator as column is now the primary column.
*
* @param column
* @field {@link MarkerField}
*/
void updateDirectionIndicator(TreeColumn column, MarkerField field) {
viewer.getTree().setSortColumn(column);
if (builder.getSortDirection(field) == MarkerComparator.ASCENDING)
viewer.getTree().setSortDirection(SWT.UP);
else
viewer.getTree().setSortDirection(SWT.DOWN);
}
/**
* Update the title of the view.
*/
void updateTitle() {
String status = MarkerSupportConstants.EMPTY_STRING;
int totalCount = builder.getTotalMarkerCount();
int filteredCount = 0;
MarkerCategory[] categories = builder.getCategories();
// Categories might be null if building is still happening
if (categories != null && builder.isShowingHierarchy()) {
int markerLimit = MarkerSupportInternalUtilities.getMarkerLimit();
for (int i = 0; i < categories.length; i++) {
filteredCount += markerLimit < 0 ? categories[i].getTotalSize()
: Math.min(categories[i].getTotalSize(), markerLimit);
}
} else {
filteredCount = MarkerSupportInternalUtilities.getMarkerLimit();
}
if (filteredCount < 0 || filteredCount >= totalCount) {
status = NLS.bind(MarkerMessages.filter_itemsMessage, new Integer(
totalCount));
} else {
status = NLS.bind(MarkerMessages.filter_matchedMessage,
new Integer(filteredCount), new Integer(totalCount));
}
setContentDescription(status);
}
/**
* Set the selection of the receiver. reveal the item if reveal is true.
*
* @param structuredSelection
* @param reveal
*/
void setSelection(StructuredSelection structuredSelection, boolean reveal) {
List newSelection = new ArrayList(structuredSelection.size());
for (Iterator i = structuredSelection.iterator(); i.hasNext();) {
Object next = i.next();
if (next instanceof IMarker) {
MarkerItem marker = builder.getMarkerItem((IMarker) next);
if (marker != null) {
newSelection.add(marker);
}
}
}
viewer.setSelection(new StructuredSelection(newSelection), reveal);
}
/**
* Return the ids of the generators specified for the receiver.
*
* @return String[]
*/
String[] getGeneratorIds() {
return defaultGeneratorIds;
}
/**
* Turn off all filters in the builder.
*/
void disableAllFilters() {
builder.disableAllFilters();
}
/**
* Return the builder for the receiver.
*
* @return CachedMarkerBuilder
*/
CachedMarkerBuilder getBuilder() {
return builder;
}
/**
* Get the categories to expand for the receiver.
*
* @return Collection of MarkerCategory.
*/
private Collection getCategoriesToExpand() {
if (categoriesToExpand == null) {
categoriesToExpand = new HashSet();
if (this.memento != null) {
IMemento expanded = this.memento.getChild(TAG_EXPANDED);
if (expanded != null) {
IMemento[] mementoCategories = expanded
.getChildren(TAG_CATEGORY);
MarkerCategory[] markerCategories = builder.getCategories();
if (markerCategories != null) {
for (int i = 0; i < markerCategories.length; i++) {
for (int j = 0; j < mementoCategories.length; j++) {
if (markerCategories[i].getName().equals(
mementoCategories[j].getID()))
categoriesToExpand.add(markerCategories[i]
.getName());
}
}
}
}
}
}
return categoriesToExpand;
}
/**
* Restore the expanded categories.
*
* @param builder
*/
void reexpandCategories(final CachedMarkerBuilder builder) {
if (!getCategoriesToExpand().isEmpty() && builder.isShowingHierarchy()) {
MarkerItem[] items = builder.getElements();
for (int i = 0; i < items.length; i++) {
String name = ((MarkerCategory) items[i]).getName();
if (getCategoriesToExpand().contains(name))
viewer.expandToLevel(items[i], 2);
}
}
}
/**
* Initialize the title based on the count
*
* @param count
*/
void initializeTitle(String count) {
setPartName(NLS.bind(MarkerMessages.newViewTitle, new Object[] {
getPartName(), count }));
}
}