0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.ui.views.markers.internal;
0011:
0012: import java.io.IOException;
0013: import java.io.StringReader;
0014: import java.io.StringWriter;
0015: import java.text.MessageFormat;
0016: import java.util.ArrayList;
0017: import java.util.Arrays;
0018: import java.util.Collection;
0019: import java.util.HashSet;
0020: import java.util.Iterator;
0021: import java.util.List;
0022:
0023: import org.eclipse.core.commands.operations.IUndoContext;
0024: import org.eclipse.core.resources.IFile;
0025: import org.eclipse.core.resources.IMarker;
0026: import org.eclipse.core.resources.IResource;
0027: import org.eclipse.core.resources.IResourceChangeEvent;
0028: import org.eclipse.core.resources.IResourceChangeListener;
0029: import org.eclipse.core.resources.ResourcesPlugin;
0030: import org.eclipse.core.resources.mapping.ResourceMapping;
0031: import org.eclipse.core.resources.mapping.ResourceMappingContext;
0032: import org.eclipse.core.resources.mapping.ResourceTraversal;
0033: import org.eclipse.core.runtime.CoreException;
0034: import org.eclipse.core.runtime.IAdaptable;
0035: import org.eclipse.core.runtime.IProgressMonitor;
0036: import org.eclipse.core.runtime.IStatus;
0037: import org.eclipse.core.runtime.NullProgressMonitor;
0038: import org.eclipse.core.runtime.Status;
0039: import org.eclipse.core.runtime.jobs.IJobChangeListener;
0040: import org.eclipse.core.runtime.jobs.Job;
0041: import org.eclipse.help.HelpSystem;
0042: import org.eclipse.help.IContext;
0043: import org.eclipse.help.IContextProvider;
0044: import org.eclipse.jface.action.IMenuManager;
0045: import org.eclipse.jface.action.IToolBarManager;
0046: import org.eclipse.jface.action.MenuManager;
0047: import org.eclipse.jface.action.Separator;
0048: import org.eclipse.jface.dialogs.Dialog;
0049: import org.eclipse.jface.dialogs.IDialogSettings;
0050: import org.eclipse.jface.preference.IPreferenceStore;
0051: import org.eclipse.jface.util.IPropertyChangeListener;
0052: import org.eclipse.jface.util.PropertyChangeEvent;
0053: import org.eclipse.jface.viewers.AbstractTreeViewer;
0054: import org.eclipse.jface.viewers.ISelection;
0055: import org.eclipse.jface.viewers.IStructuredSelection;
0056: import org.eclipse.jface.viewers.OpenEvent;
0057: import org.eclipse.jface.viewers.StructuredSelection;
0058: import org.eclipse.jface.viewers.TreeViewer;
0059: import org.eclipse.jface.window.Window;
0060: import org.eclipse.osgi.util.NLS;
0061: import org.eclipse.swt.dnd.Clipboard;
0062: import org.eclipse.swt.dnd.DND;
0063: import org.eclipse.swt.dnd.DragSourceAdapter;
0064: import org.eclipse.swt.dnd.DragSourceEvent;
0065: import org.eclipse.swt.dnd.DragSourceListener;
0066: import org.eclipse.swt.dnd.TextTransfer;
0067: import org.eclipse.swt.dnd.Transfer;
0068: import org.eclipse.swt.events.HelpEvent;
0069: import org.eclipse.swt.events.HelpListener;
0070: import org.eclipse.swt.events.TreeAdapter;
0071: import org.eclipse.swt.events.TreeEvent;
0072: import org.eclipse.swt.widgets.Composite;
0073: import org.eclipse.swt.widgets.Tree;
0074: import org.eclipse.ui.IActionBars;
0075: import org.eclipse.ui.IEditorInput;
0076: import org.eclipse.ui.IEditorPart;
0077: import org.eclipse.ui.IMemento;
0078: import org.eclipse.ui.ISelectionListener;
0079: import org.eclipse.ui.IViewSite;
0080: import org.eclipse.ui.IWorkbenchActionConstants;
0081: import org.eclipse.ui.IWorkbenchPart;
0082: import org.eclipse.ui.PartInitException;
0083: import org.eclipse.ui.PlatformUI;
0084: import org.eclipse.ui.WorkbenchException;
0085: import org.eclipse.ui.XMLMemento;
0086: import org.eclipse.ui.actions.ActionFactory;
0087: import org.eclipse.ui.actions.ContributionItemFactory;
0088: import org.eclipse.ui.actions.SelectionProviderAction;
0089: import org.eclipse.ui.ide.IDE;
0090: import org.eclipse.ui.ide.ResourceUtil;
0091: import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
0092: import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
0093: import org.eclipse.ui.keys.IBindingService;
0094: import org.eclipse.ui.operations.RedoActionHandler;
0095: import org.eclipse.ui.operations.UndoActionHandler;
0096: import org.eclipse.ui.part.IShowInSource;
0097: import org.eclipse.ui.part.MarkerTransfer;
0098: import org.eclipse.ui.part.ShowInContext;
0099: import org.eclipse.ui.preferences.ViewPreferencesAction;
0100: import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
0101: import org.eclipse.ui.progress.WorkbenchJob;
0102: import org.eclipse.ui.views.markers.internal.MarkerAdapter.MarkerCategory;
0103: import org.eclipse.ui.views.tasklist.ITaskListResourceAdapter;
0104:
0105: /**
0106: * MarkerView is the abstract super class of the marker based views.
0107: *
0108: */
0109: public abstract class MarkerView extends TableView {
0110:
0111: private static final String TAG_SELECTION = "selection"; //$NON-NLS-1$
0112:
0113: private static final String TAG_MARKER = "marker"; //$NON-NLS-1$
0114:
0115: private static final String TAG_RESOURCE = "resource"; //$NON-NLS-1$
0116:
0117: private static final String TAG_ID = "id"; //$NON-NLS-1$
0118:
0119: private static final String TAG_FILTERS_SECTION = "filters"; //$NON-NLS-1$
0120:
0121: private static final String TAG_FILTER_ENTRY = "filter"; //$NON-NLS-1$
0122:
0123: private static final String MENU_FILTERS_GROUP = "group.filter";//$NON-NLS-1$
0124:
0125: private static final String MENU_SHOW_IN_GROUP = "group.showIn";//$NON-NLS-1$
0126:
0127: // Section from a 3.1 or earlier workbench
0128: private static final String OLD_FILTER_SECTION = "filter"; //$NON-NLS-1$
0129:
0130: static final Object MARKER_UPDATE_FAMILY = new Object();
0131:
0132: class MarkerProcessJob extends Job {
0133:
0134: /**
0135: * Create a new instance of the receiver.
0136: */
0137: MarkerProcessJob() {
0138: super (MarkerMessages.MarkerView_processUpdates);
0139: setSystem(true);
0140: }
0141:
0142: /*
0143: * (non-Javadoc)
0144: *
0145: * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
0146: */
0147: protected IStatus run(IProgressMonitor monitor) {
0148: updateForContentsRefresh(monitor);
0149: return Status.OK_STATUS;
0150:
0151: }
0152:
0153: /*
0154: * (non-Javadoc)
0155: *
0156: * @see org.eclipse.ui.progress.WorkbenchJob#shouldRun()
0157: */
0158: public boolean shouldRun() {
0159: // Do not run if the change came in before there is a viewer
0160: return PlatformUI.isWorkbenchRunning();
0161: }
0162:
0163: /*
0164: * (non-Javadoc)
0165: *
0166: * @see org.eclipse.core.runtime.jobs.Job#belongsTo(java.lang.Object)
0167: */
0168: public boolean belongsTo(Object family) {
0169: return MARKER_UPDATE_FAMILY == family;
0170: }
0171:
0172: }
0173:
0174: MarkerProcessJob markerProcessJob = new MarkerProcessJob();
0175:
0176: private class UpdateJob extends WorkbenchJob {
0177:
0178: private class MarkerDescriptor {
0179: String description;
0180:
0181: String folder;
0182:
0183: String resource;
0184:
0185: int line;
0186:
0187: MarkerDescriptor(ConcreteMarker marker) {
0188: description = marker.getDescription();
0189: folder = marker.getFolder();
0190: resource = marker.getResourceName();
0191: line = marker.getLine();
0192: }
0193:
0194: boolean isEquivalentTo(ConcreteMarker marker) {
0195: return marker.getDescription().equals(description)
0196: && marker.getFolder().equals(folder)
0197: && marker.getResourceName().equals(resource)
0198: && marker.getLine() == line;
0199: }
0200:
0201: }
0202:
0203: private Collection categoriesToExpand = new HashSet();
0204:
0205: private Collection preservedSelection = new ArrayList();
0206:
0207: UpdateJob() {
0208: super (MarkerMessages.MarkerView_queueing_updates);
0209: setSystem(true);
0210: }
0211:
0212: /*
0213: * (non-Javadoc)
0214: *
0215: * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
0216: */
0217: public IStatus runInUIThread(IProgressMonitor monitor) {
0218:
0219: if (getViewer().getControl().isDisposed()) {
0220: return Status.CANCEL_STATUS;
0221: }
0222:
0223: if (monitor.isCanceled())
0224: return Status.CANCEL_STATUS;
0225:
0226: getViewer().refresh(true);
0227:
0228: Tree tree = getTree();
0229:
0230: if (tree != null && !tree.isDisposed()) {
0231: updateStatusMessage();
0232: updateTitle();
0233: // Expand all if the list is small
0234: if (getCurrentMarkers().getSize() < 20) {
0235: getViewer().expandAll();
0236: } else {// Reexpand the old categories
0237: MarkerCategory[] categories = getMarkerAdapter()
0238: .getCategories();
0239: if (categories == null)
0240: categoriesToExpand.clear();
0241: else {
0242: if (categories.length == 1) {// Expand if there is
0243: // only
0244: // one
0245: getViewer().expandAll();
0246: categoriesToExpand.clear();
0247: if (monitor.isCanceled())
0248: return Status.CANCEL_STATUS;
0249: categoriesToExpand.add(categories[0]
0250: .getName());
0251: } else {
0252: Collection newCategories = new HashSet();
0253: for (int i = 0; i < categories.length; i++) {
0254: if (monitor.isCanceled())
0255: return Status.CANCEL_STATUS;
0256: MarkerCategory category = categories[i];
0257: if (categoriesToExpand
0258: .contains(category.getName())) {
0259: getViewer()
0260: .expandToLevel(
0261: category,
0262: AbstractTreeViewer.ALL_LEVELS);
0263: newCategories.add(category
0264: .getName());
0265: }
0266:
0267: }
0268: categoriesToExpand = newCategories;
0269: }
0270: }
0271:
0272: }
0273: }
0274:
0275: if (preservedSelection.size() > 0) {
0276:
0277: Collection newSelection = new ArrayList();
0278: ConcreteMarker[] markers = getCurrentMarkers()
0279: .toArray();
0280:
0281: for (int i = 0; i < markers.length; i++) {
0282: Iterator preserved = preservedSelection.iterator();
0283: while (preserved.hasNext()) {
0284: MarkerDescriptor next = (MarkerDescriptor) preserved
0285: .next();
0286: if (next.isEquivalentTo(markers[i])) {
0287: newSelection.add(markers[i]);
0288: continue;
0289: }
0290: }
0291: }
0292:
0293: getViewer()
0294: .setSelection(
0295: new StructuredSelection(newSelection
0296: .toArray()), true);
0297: preservedSelection.clear();
0298: }
0299: if (getViewer().getTree().getItemCount() > 0)
0300: getViewer().getTree().setTopItem(
0301: getViewer().getTree().getItem(0));
0302:
0303: return Status.OK_STATUS;
0304: }
0305:
0306: /**
0307: * Add the category to the list of expanded categories.
0308: *
0309: * @param category
0310: */
0311: public void addExpandedCategory(MarkerCategory category) {
0312: categoriesToExpand.add(category.getName());
0313:
0314: }
0315:
0316: /**
0317: * Remove the category from the list of expanded ones.
0318: *
0319: * @param category
0320: */
0321: public void removeExpandedCategory(MarkerCategory category) {
0322: categoriesToExpand.remove(category.getName());
0323:
0324: }
0325:
0326: /*
0327: * (non-Javadoc)
0328: *
0329: * @see org.eclipse.core.runtime.jobs.Job#belongsTo(java.lang.Object)
0330: */
0331: public boolean belongsTo(Object family) {
0332: return family == MARKER_UPDATE_FAMILY;
0333: }
0334:
0335: /**
0336: * Preserve the selection for reselection after the next update.
0337: *
0338: * @param selection
0339: */
0340: public void saveSelection(ISelection selection) {
0341: preservedSelection.clear();
0342: if (selection instanceof IStructuredSelection) {
0343: IStructuredSelection structured = (IStructuredSelection) selection;
0344: Iterator iterator = structured.iterator();
0345: while (iterator.hasNext()) {
0346: MarkerNode next = (MarkerNode) iterator.next();
0347: if (next.isConcrete()) {
0348: preservedSelection.add(new MarkerDescriptor(
0349: next.getConcreteRepresentative()));
0350: }
0351: }
0352: }
0353:
0354: }
0355:
0356: /*
0357: * (non-Javadoc)
0358: *
0359: * @see org.eclipse.ui.progress.WorkbenchJob#shouldRun()
0360: */
0361: public boolean shouldRun() {
0362: return !getMarkerAdapter().isBuilding();
0363: }
0364:
0365: }
0366:
0367: private UpdateJob updateJob = new UpdateJob();
0368:
0369: // A private field for keeping track of the number of markers
0370: // before the busy testing started
0371: private int preBusyMarkers = 0;
0372:
0373: protected Object[] focusElements;
0374:
0375: private Clipboard clipboard;
0376:
0377: IResourceChangeListener markerUpdateListener = new IResourceChangeListener() {
0378:
0379: /*
0380: * (non-Javadoc)
0381: *
0382: * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
0383: */
0384: public void resourceChanged(IResourceChangeEvent event) {
0385: if (!hasMarkerDelta(event))
0386: return;
0387:
0388: if (event.getType() == IResourceChangeEvent.POST_BUILD) {
0389: scheduleMarkerUpdate(Util.SHORT_DELAY);
0390: return;
0391: }
0392:
0393: // After 30 seconds do updates anyways
0394:
0395: IWorkbenchSiteProgressService progressService = getProgressService();
0396: if (progressService == null)
0397: markerProcessJob.schedule(Util.LONG_DELAY);
0398: else
0399: getProgressService().schedule(markerProcessJob,
0400: Util.LONG_DELAY);
0401:
0402: }
0403:
0404: /**
0405: * Returns whether or not the given even contains marker deltas for this
0406: * view.
0407: *
0408: * @param event
0409: * the resource change event
0410: * @return <code>true</code> if the event contains at least one
0411: * relevant marker delta
0412: * @since 3.3
0413: */
0414: private boolean hasMarkerDelta(IResourceChangeEvent event) {
0415: String[] markerTypes = getMarkerTypes();
0416: for (int i = 0; i < markerTypes.length; i++) {
0417: if (event.findMarkerDeltas(markerTypes[i], true).length > 0) {
0418: return true;
0419: }
0420: }
0421: return false;
0422: }
0423:
0424: };
0425:
0426: private class ContextProvider implements IContextProvider {
0427: public int getContextChangeMask() {
0428: return SELECTION;
0429: }
0430:
0431: public IContext getContext(Object target) {
0432: String contextId = null;
0433: // See if there is a context registered for the current selection
0434: ConcreteMarker marker = getSelectedConcreteMarker();
0435: if (marker != null) {
0436: contextId = IDE.getMarkerHelpRegistry().getHelp(
0437: marker.getMarker());
0438: }
0439:
0440: if (contextId == null) {
0441: contextId = getStaticContextId();
0442: }
0443: return HelpSystem.getContext(contextId);
0444: }
0445:
0446: /**
0447: * Return the currently selected concrete marker or <code>null</code>
0448: * if there isn't one.
0449: *
0450: * @return ConcreteMarker
0451: */
0452: private ConcreteMarker getSelectedConcreteMarker() {
0453:
0454: IStructuredSelection selection = (IStructuredSelection) getViewer()
0455: .getSelection();
0456: if (selection.isEmpty())
0457: return null;
0458:
0459: if (selection.getFirstElement() instanceof ConcreteMarker)
0460: return (ConcreteMarker) selection.getFirstElement();
0461: return null;
0462: }
0463:
0464: /*
0465: * (non-Javadoc)
0466: *
0467: * @see org.eclipse.help.IContextProvider#getSearchExpression(java.lang.Object)
0468: */
0469: public String getSearchExpression(Object target) {
0470: return null;
0471: }
0472: }
0473:
0474: private ContextProvider contextProvider = new ContextProvider();
0475:
0476: protected ActionCopyMarker copyAction;
0477:
0478: protected ActionPasteMarker pasteAction;
0479:
0480: protected SelectionProviderAction revealAction;
0481:
0482: protected SelectionProviderAction openAction;
0483:
0484: protected SelectionProviderAction deleteAction;
0485:
0486: protected SelectionProviderAction selectAllAction;
0487:
0488: protected SelectionProviderAction propertiesAction;
0489:
0490: protected UndoActionHandler undoAction;
0491:
0492: protected RedoActionHandler redoAction;
0493:
0494: private ISelectionListener focusListener = new ISelectionListener() {
0495: public void selectionChanged(IWorkbenchPart part,
0496: ISelection selection) {
0497: MarkerView.this .focusSelectionChanged(part, selection);
0498: }
0499: };
0500:
0501: private int totalMarkers = 0;
0502:
0503: private MarkerFilter[] markerFilters = new MarkerFilter[0];
0504:
0505: // A cache of the enabled filters
0506: private MarkerFilter[] enabledFilters = null;
0507:
0508: private MenuManager filtersMenu;
0509:
0510: private MenuManager showInMenu;
0511:
0512: private IPropertyChangeListener workingSetListener;
0513:
0514: private MarkerAdapter adapter;
0515:
0516: private IPropertyChangeListener preferenceListener;
0517:
0518: /**
0519: * Create a new instance of the receiver,
0520: */
0521: public MarkerView() {
0522: super ();
0523: preferenceListener = new IPropertyChangeListener() {
0524: /*
0525: * (non-Javadoc)
0526: *
0527: * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
0528: */
0529: public void propertyChange(PropertyChangeEvent event) {
0530: if (event.getProperty().equals(
0531: getFiltersPreferenceName())) {
0532: loadFiltersPreferences();
0533: clearEnabledFilters();
0534: refreshForFocusUpdate();
0535: }
0536: }
0537: };
0538: IDEWorkbenchPlugin.getDefault().getPreferenceStore()
0539: .addPropertyChangeListener(preferenceListener);
0540: }
0541:
0542: /**
0543: * Get the current markers for the receiver.
0544: *
0545: * @return MarkerList
0546: */
0547: public MarkerList getCurrentMarkers() {
0548: return getMarkerAdapter().getCurrentMarkers();
0549: }
0550:
0551: /**
0552: * Get the marker adapter for the receiver.
0553: *
0554: * @return MarkerAdapter
0555: */
0556: protected MarkerAdapter getMarkerAdapter() {
0557: return adapter;
0558: }
0559:
0560: /**
0561: * Update for the change in the contents.
0562: *
0563: * @param monitor
0564: */
0565: public void updateForContentsRefresh(IProgressMonitor monitor) {
0566: updateJob.cancel();
0567: getMarkerAdapter().buildAllMarkers(monitor);
0568: getProgressService().schedule(updateJob);
0569: }
0570:
0571: /*
0572: * (non-Javadoc)
0573: *
0574: * @see org.eclipse.ui.IViewPart#init(org.eclipse.ui.IViewSite,
0575: * org.eclipse.ui.IMemento)
0576: */
0577: public void init(IViewSite site, IMemento memento)
0578: throws PartInitException {
0579: super .init(site, memento);
0580: IWorkbenchSiteProgressService progressService = getProgressService();
0581: if (progressService != null) {
0582: getProgressService().showBusyForFamily(
0583: ResourcesPlugin.FAMILY_MANUAL_BUILD);
0584: getProgressService().showBusyForFamily(
0585: ResourcesPlugin.FAMILY_AUTO_BUILD);
0586: getProgressService()
0587: .showBusyForFamily(MARKER_UPDATE_FAMILY);
0588: }
0589: loadFiltersPreferences();
0590:
0591: }
0592:
0593: /**
0594: * Load the filters preference.
0595: */
0596: private void loadFiltersPreferences() {
0597:
0598: String preference = IDEWorkbenchPlugin.getDefault()
0599: .getPreferenceStore().getString(
0600: getFiltersPreferenceName());
0601:
0602: if (preference.equals(IPreferenceStore.STRING_DEFAULT_DEFAULT)) {
0603: createDefaultFilter();
0604: return;
0605: }
0606:
0607: StringReader reader = new StringReader(preference);
0608: try {
0609: restoreFilters(XMLMemento.createReadRoot(reader));
0610: } catch (WorkbenchException e) {
0611: IDEWorkbenchPlugin.log(e.getLocalizedMessage(), e);
0612: }
0613:
0614: }
0615:
0616: /**
0617: * Update for filter changes. Save the preference and clear the enabled
0618: * cache.
0619: */
0620: void updateForFilterChanges() {
0621:
0622: XMLMemento memento = XMLMemento
0623: .createWriteRoot(TAG_FILTERS_SECTION);
0624:
0625: writeFiltersSettings(memento);
0626:
0627: StringWriter writer = new StringWriter();
0628: try {
0629: memento.save(writer);
0630: } catch (IOException e) {
0631: IDEWorkbenchPlugin.getDefault().getLog().log(
0632: Util.errorStatus(e));
0633: }
0634:
0635: IDEWorkbenchPlugin.getDefault().getPreferenceStore().putValue(
0636: getFiltersPreferenceName(), writer.toString());
0637: IDEWorkbenchPlugin.getDefault().savePluginPreferences();
0638:
0639: clearEnabledFilters();
0640: refreshFilterMenu();
0641: refreshViewer();
0642: }
0643:
0644: /**
0645: * Write the filter settings to the memento.
0646: *
0647: * @param memento
0648: */
0649: protected void writeFiltersSettings(XMLMemento memento) {
0650: MarkerFilter[] filters = getUserFilters();
0651: for (int i = 0; i < filters.length; i++) {
0652: IMemento child = memento.createChild(TAG_FILTER_ENTRY,
0653: filters[i].getName());
0654: filters[i].saveFilterSettings(child);
0655: }
0656: }
0657:
0658: /**
0659: * Get the name of the filters preference for instances of the receiver.
0660: *
0661: * @return String
0662: */
0663: abstract String getFiltersPreferenceName();
0664:
0665: /**
0666: * Restore the filters from the mimento.
0667: *
0668: * @param memento
0669: */
0670: void restoreFilters(IMemento memento) {
0671:
0672: IMemento[] sections = null;
0673: if (memento != null) {
0674: sections = memento.getChildren(TAG_FILTER_ENTRY);
0675: }
0676:
0677: if (sections == null) {
0678: // Check if we have an old filter setting around
0679: IDialogSettings mainSettings = getDialogSettings();
0680: IDialogSettings filtersSection = mainSettings
0681: .getSection(OLD_FILTER_SECTION);
0682: if (filtersSection != null) {
0683: MarkerFilter markerFilter = createFilter(MarkerMessages.MarkerFilter_defaultFilterName);
0684: markerFilter.restoreFilterSettings(filtersSection);
0685: setFilters(new MarkerFilter[] { markerFilter });
0686: }
0687:
0688: } else {
0689: MarkerFilter[] newFilters = new MarkerFilter[sections.length];
0690:
0691: for (int i = 0; i < sections.length; i++) {
0692: newFilters[i] = createFilter(sections[i].getID());
0693: newFilters[i].restoreState(sections[i]);
0694: }
0695: setFilters(newFilters);
0696: }
0697:
0698: if (markerFilters.length == 0) {// Make sure there is at least a default
0699: createDefaultFilter();
0700: }
0701:
0702: }
0703:
0704: /**
0705: * Create a default filter for the receiver.
0706: *
0707: */
0708: private void createDefaultFilter() {
0709: MarkerFilter filter = createFilter(MarkerMessages.MarkerFilter_defaultFilterName);
0710: setFilters(new MarkerFilter[] { filter });
0711: }
0712:
0713: /**
0714: * Create a filter called name.
0715: *
0716: * @param name
0717: * @return MarkerFilter
0718: */
0719: protected abstract MarkerFilter createFilter(String name);
0720:
0721: /**
0722: * Return the memento tag for the receiver.
0723: *
0724: * @return String
0725: */
0726: protected abstract String getSectionTag();
0727:
0728: /*
0729: * (non-Javadoc)
0730: *
0731: * @see org.eclipse.ui.views.internal.tableview.TableView#createPartControl(org.eclipse.swt.widgets.Composite)
0732: */
0733: public void createPartControl(Composite parent) {
0734:
0735: clipboard = new Clipboard(parent.getDisplay());
0736: super .createPartControl(parent);
0737:
0738: initDragAndDrop();
0739:
0740: getSite().getPage().addSelectionListener(focusListener);
0741: focusSelectionChanged(getSite().getPage().getActivePart(),
0742: getSite().getPage().getSelection());
0743: PlatformUI.getWorkbench().getWorkingSetManager()
0744: .addPropertyChangeListener(getWorkingSetListener());
0745:
0746: // Set help on the view itself
0747: getViewer().getControl().addHelpListener(new HelpListener() {
0748: /*
0749: * (non-Javadoc)
0750: *
0751: * @see org.eclipse.swt.events.HelpListener#helpRequested(org.eclipse.swt.events.HelpEvent)
0752: */
0753: public void helpRequested(HelpEvent e) {
0754: IContext context = contextProvider
0755: .getContext(getViewer().getControl());
0756: PlatformUI.getWorkbench().getHelpSystem().displayHelp(
0757: context);
0758: }
0759: });
0760:
0761: // Hook up to the resource changes after all widget have been created
0762: ResourcesPlugin.getWorkspace().addResourceChangeListener(
0763: markerUpdateListener,
0764: IResourceChangeEvent.POST_CHANGE
0765: | IResourceChangeEvent.PRE_BUILD
0766: | IResourceChangeEvent.POST_BUILD);
0767: }
0768:
0769: /*
0770: * (non-Javadoc)
0771: *
0772: * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
0773: */
0774: public Object getAdapter(Class adaptable) {
0775: if (adaptable.equals(IContextProvider.class)) {
0776: return contextProvider;
0777: }
0778: if (adaptable.equals(IShowInSource.class)) {
0779: return new IShowInSource() {
0780: public ShowInContext getShowInContext() {
0781: ISelection selection = getViewer().getSelection();
0782: if (!(selection instanceof IStructuredSelection)) {
0783: return null;
0784: }
0785: IStructuredSelection structured = (IStructuredSelection) selection;
0786: Iterator markerIterator = structured.iterator();
0787: List newSelection = new ArrayList();
0788: while (markerIterator.hasNext()) {
0789: ConcreteMarker element = (ConcreteMarker) markerIterator
0790: .next();
0791: newSelection.add(element.getResource());
0792: }
0793: return new ShowInContext(getViewer().getInput(),
0794: new StructuredSelection(newSelection));
0795: }
0796:
0797: };
0798: }
0799: return super .getAdapter(adaptable);
0800: }
0801:
0802: /*
0803: * (non-Javadoc)
0804: *
0805: * @see org.eclipse.ui.views.markers.internal.TableView#viewerSelectionChanged(org.eclipse.jface.viewers.IStructuredSelection)
0806: */
0807: protected void viewerSelectionChanged(IStructuredSelection selection) {
0808:
0809: Object[] rawSelection = selection.toArray();
0810:
0811: List markers = new ArrayList();
0812:
0813: for (int idx = 0; idx < rawSelection.length; idx++) {
0814:
0815: if (rawSelection[idx] instanceof ConcreteMarker)
0816: markers.add(((ConcreteMarker) rawSelection[idx])
0817: .getMarker());
0818: }
0819:
0820: setSelection(new StructuredSelection(markers));
0821:
0822: updateStatusMessage(selection);
0823: }
0824:
0825: /*
0826: * (non-Javadoc)
0827: *
0828: * @see org.eclipse.ui.views.internal.tableview.TableView#dispose()
0829: */
0830: public void dispose() {
0831: super .dispose();
0832: cancelJobs();
0833:
0834: ResourcesPlugin.getWorkspace().removeResourceChangeListener(
0835: markerUpdateListener);
0836: PlatformUI.getWorkbench().getWorkingSetManager()
0837: .removePropertyChangeListener(workingSetListener);
0838: IDEWorkbenchPlugin.getDefault().getPreferenceStore()
0839: .removePropertyChangeListener(preferenceListener);
0840: getSite().getPage().removeSelectionListener(focusListener);
0841:
0842: // dispose of selection provider actions (may not have been created yet
0843: // if createPartControls was never called)
0844: if (openAction != null) {
0845: openAction.dispose();
0846: copyAction.dispose();
0847: selectAllAction.dispose();
0848: deleteAction.dispose();
0849: revealAction.dispose();
0850: propertiesAction.dispose();
0851: undoAction.dispose();
0852: redoAction.dispose();
0853: clipboard.dispose();
0854: }
0855: if (showInMenu != null) {
0856: showInMenu.dispose();
0857: }
0858: }
0859:
0860: /*
0861: * (non-Javadoc)
0862: *
0863: * @see org.eclipse.ui.views.internal.tableview.TableView#createActions()
0864: */
0865: protected void createActions() {
0866: revealAction = new ActionRevealMarker(this , getViewer());
0867: openAction = new ActionOpenMarker(this , getViewer());
0868: copyAction = new ActionCopyMarker(this , getViewer());
0869: copyAction.setClipboard(clipboard);
0870: copyAction.setProperties(getSortingFields());
0871: pasteAction = new ActionPasteMarker(this , getViewer(),
0872: getMarkerName());
0873: pasteAction.setClipboard(clipboard);
0874: pasteAction.setPastableTypes(getMarkerTypes());
0875: deleteAction = new ActionRemoveMarker(this , getViewer(),
0876: getMarkerName());
0877: selectAllAction = new ActionSelectAll(this );
0878: propertiesAction = new ActionMarkerProperties(this ,
0879: getViewer(), getMarkerName());
0880:
0881: IUndoContext undoContext = getUndoContext();
0882: undoAction = new UndoActionHandler(getSite(), undoContext);
0883: redoAction = new RedoActionHandler(getSite(), undoContext);
0884:
0885: super .createActions();
0886:
0887: setFilterAction(new FiltersAction(this ));
0888:
0889: setPreferencesAction(new ViewPreferencesAction() {
0890: /*
0891: * (non-Javadoc)
0892: *
0893: * @see org.eclipse.ui.preferences.ViewPreferencesAction#openViewPreferencesDialog()
0894: */
0895: public void openViewPreferencesDialog() {
0896: openPreferencesDialog(
0897: getMarkerEnablementPreferenceName(),
0898: getMarkerLimitPreferenceName());
0899:
0900: }
0901:
0902: });
0903: }
0904:
0905: /**
0906: * Open a dialog to set the preferences.
0907: *
0908: * @param markerEnablementPreferenceName
0909: * @param markerLimitPreferenceName
0910: */
0911: private void openPreferencesDialog(
0912: String markerEnablementPreferenceName,
0913: String markerLimitPreferenceName) {
0914:
0915: Dialog dialog = new MarkerViewPreferenceDialog(getSite()
0916: .getWorkbenchWindow().getShell(),
0917: markerEnablementPreferenceName,
0918: markerLimitPreferenceName,
0919: MarkerMessages.MarkerPreferences_DialogTitle);
0920: if (dialog.open() == Window.OK) {
0921: refreshViewer();
0922: }
0923:
0924: }
0925:
0926: /**
0927: * Get the name of the marker enablement preference.
0928: *
0929: * @return String
0930: */
0931: abstract String getMarkerLimitPreferenceName();
0932:
0933: abstract String[] getMarkerTypes();
0934:
0935: /*
0936: * (non-Javadoc)
0937: *
0938: * @see org.eclipse.ui.views.internal.tableview.TableView#initToolBar(org.eclipse.jface.action.IToolBarManager)
0939: */
0940: protected void initToolBar(IToolBarManager tbm) {
0941: tbm.add(deleteAction);
0942: tbm.add(getFilterAction());
0943: tbm.update(false);
0944: }
0945:
0946: /*
0947: * (non-Javadoc)
0948: *
0949: * @see org.eclipse.ui.views.internal.tableview.TableView#registerGlobalActions(org.eclipse.ui.IActionBars)
0950: */
0951: protected void registerGlobalActions(IActionBars actionBars) {
0952: actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(),
0953: copyAction);
0954: actionBars.setGlobalActionHandler(ActionFactory.PASTE.getId(),
0955: pasteAction);
0956: actionBars.setGlobalActionHandler(ActionFactory.DELETE.getId(),
0957: deleteAction);
0958: actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL
0959: .getId(), selectAllAction);
0960: actionBars.setGlobalActionHandler(ActionFactory.PROPERTIES
0961: .getId(), propertiesAction);
0962: actionBars.setGlobalActionHandler(ActionFactory.UNDO.getId(),
0963: undoAction);
0964: actionBars.setGlobalActionHandler(ActionFactory.REDO.getId(),
0965: redoAction);
0966:
0967: copyAction.setActionDefinitionId("org.eclipse.ui.edit.copy"); //$NON-NLS-1$
0968: pasteAction.setActionDefinitionId("org.eclipse.ui.edit.paste"); //$NON-NLS-1$
0969: deleteAction
0970: .setActionDefinitionId("org.eclipse.ui.edit.delete"); //$NON-NLS-1$
0971: selectAllAction
0972: .setActionDefinitionId("org.eclipse.ui.edit.selectAll"); //$NON-NLS-1$
0973: propertiesAction
0974: .setActionDefinitionId("org.eclipse.ui.file.properties"); //$NON-NLS-1$
0975: undoAction.setActionDefinitionId("org.eclipse.ui.edit.undo"); //$NON-NLS-1$
0976: redoAction.setActionDefinitionId("org.eclipse.ui.edit.redo"); //$NON-NLS-1$
0977: }
0978:
0979: protected void initDragAndDrop() {
0980: int operations = DND.DROP_COPY;
0981: Transfer[] transferTypes = new Transfer[] {
0982: MarkerTransfer.getInstance(),
0983: TextTransfer.getInstance() };
0984: DragSourceListener listener = new DragSourceAdapter() {
0985: public void dragSetData(DragSourceEvent event) {
0986: performDragSetData(event);
0987: }
0988:
0989: public void dragFinished(DragSourceEvent event) {
0990: }
0991: };
0992:
0993: getViewer().addDragSupport(operations, transferTypes, listener);
0994: }
0995:
0996: /**
0997: * The user is attempting to drag marker data. Add the appropriate data to
0998: * the event depending on the transfer type.
0999: */
1000: private void performDragSetData(DragSourceEvent event) {
1001: if (MarkerTransfer.getInstance()
1002: .isSupportedType(event.dataType)) {
1003:
1004: event.data = getSelectedMarkers();
1005: return;
1006: }
1007: if (TextTransfer.getInstance().isSupportedType(event.dataType)) {
1008: List selection = ((IStructuredSelection) getViewer()
1009: .getSelection()).toList();
1010: try {
1011: IMarker[] markers = new IMarker[selection.size()];
1012: selection.toArray(markers);
1013: if (markers != null) {
1014: event.data = copyAction.createMarkerReport(markers);
1015: }
1016: } catch (ArrayStoreException e) {
1017: }
1018: }
1019: }
1020:
1021: /**
1022: * Get the array of selected markers.
1023: *
1024: * @return IMarker[]
1025: */
1026: private IMarker[] getSelectedMarkers() {
1027: Object[] selection = ((IStructuredSelection) getViewer()
1028: .getSelection()).toArray();
1029: ArrayList markers = new ArrayList();
1030: for (int i = 0; i < selection.length; i++) {
1031: if (selection[i] instanceof ConcreteMarker) {
1032: markers
1033: .add(((ConcreteMarker) selection[i])
1034: .getMarker());
1035: }
1036: }
1037: return (IMarker[]) markers.toArray(new IMarker[markers.size()]);
1038: }
1039:
1040: /*
1041: * (non-Javadoc)
1042: *
1043: * @see org.eclipse.ui.views.internal.tableview.TableView#fillContextMenu(org.eclipse.jface.action.IMenuManager)
1044: */
1045: protected void fillContextMenu(IMenuManager manager) {
1046: if (manager == null) {
1047: return;
1048: }
1049: manager.add(openAction);
1050: createShowInMenu(manager);
1051: manager.add(new Separator());
1052: manager.add(copyAction);
1053: pasteAction.updateEnablement();
1054: manager.add(pasteAction);
1055:
1056: if (canBeEditable()) {
1057: manager.add(deleteAction);
1058: }
1059: manager.add(selectAllAction);
1060: fillContextMenuAdditions(manager);
1061: manager.add(new Separator(
1062: IWorkbenchActionConstants.MB_ADDITIONS));
1063: manager.add(new Separator());
1064: manager.add(propertiesAction);
1065: }
1066:
1067: /**
1068: * Return whether or not any of the types in the receiver can be editable.
1069: *
1070: * @return <code>true</code> if it is possible to have an editable marker
1071: * in this view.
1072: */
1073: boolean canBeEditable() {
1074: return true;
1075: }
1076:
1077: /**
1078: * Fill the context menu for the receiver.
1079: *
1080: * @param manager
1081: */
1082: abstract void fillContextMenuAdditions(IMenuManager manager);
1083:
1084: /**
1085: * Get the filters for the receiver.
1086: *
1087: * @return MarkerFilter[]
1088: */
1089: protected final MarkerFilter[] getUserFilters() {
1090: return markerFilters;
1091: }
1092:
1093: /*
1094: * (non-Javadoc)
1095: *
1096: * @see org.eclipse.ui.views.internal.tableview.TableView#handleOpenEvent(org.eclipse.jface.viewers.OpenEvent)
1097: */
1098: protected void handleOpenEvent(OpenEvent event) {
1099: if (openAction.isEnabled()) {
1100: openAction.run();
1101: }
1102: }
1103:
1104: /*
1105: * (non-Javadoc)
1106: *
1107: * @see org.eclipse.ui.views.internal.tableview.TableView#saveSelection(org.eclipse.ui.IMemento)
1108: */
1109: protected void saveSelection(IMemento memento) {
1110: IStructuredSelection selection = (IStructuredSelection) getViewer()
1111: .getSelection();
1112: IMemento selectionMem = memento.createChild(TAG_SELECTION);
1113: for (Iterator iterator = selection.iterator(); iterator
1114: .hasNext();) {
1115: Object next = iterator.next();
1116: if (!(next instanceof ConcreteMarker)) {
1117: continue;
1118: }
1119: ConcreteMarker marker = (ConcreteMarker) next;
1120: IMemento elementMem = selectionMem.createChild(TAG_MARKER);
1121: elementMem.putString(TAG_RESOURCE, marker.getMarker()
1122: .getResource().getFullPath().toString());
1123: elementMem.putString(TAG_ID, String.valueOf(marker
1124: .getMarker().getId()));
1125: }
1126: }
1127:
1128: protected abstract String[] getRootTypes();
1129:
1130: /**
1131: * @param part
1132: * @param selection
1133: */
1134: protected void focusSelectionChanged(IWorkbenchPart part,
1135: ISelection selection) {
1136:
1137: List selectedElements = new ArrayList();
1138: if (part instanceof IEditorPart) {
1139: IEditorPart editor = (IEditorPart) part;
1140: IFile file = ResourceUtil.getFile(editor.getEditorInput());
1141: if (file == null) {
1142: IEditorInput editorInput = editor.getEditorInput();
1143: if (editorInput != null) {
1144: Object mapping = editorInput
1145: .getAdapter(ResourceMapping.class);
1146: if (mapping != null) {
1147: selectedElements.add(mapping);
1148: }
1149: }
1150: } else {
1151: selectedElements.add(file);
1152: }
1153: } else {
1154: if (selection instanceof IStructuredSelection) {
1155: for (Iterator iterator = ((IStructuredSelection) selection)
1156: .iterator(); iterator.hasNext();) {
1157: Object object = iterator.next();
1158: if (object instanceof IAdaptable) {
1159: ITaskListResourceAdapter taskListResourceAdapter;
1160: Object adapter = ((IAdaptable) object)
1161: .getAdapter(ITaskListResourceAdapter.class);
1162: if (adapter != null
1163: && adapter instanceof ITaskListResourceAdapter) {
1164: taskListResourceAdapter = (ITaskListResourceAdapter) adapter;
1165: } else {
1166: taskListResourceAdapter = DefaultMarkerResourceAdapter
1167: .getDefault();
1168: }
1169:
1170: IResource resource = taskListResourceAdapter
1171: .getAffectedResource((IAdaptable) object);
1172: if (resource == null) {
1173: Object mapping = ((IAdaptable) object)
1174: .getAdapter(ResourceMapping.class);
1175: if (mapping != null) {
1176: selectedElements.add(mapping);
1177: }
1178: } else {
1179: selectedElements.add(resource);
1180: }
1181: }
1182: }
1183: }
1184: }
1185: updateFocusMarkers(selectedElements.toArray());
1186: }
1187:
1188: /**
1189: * Update the focus resources of the filters.
1190: *
1191: * @param elements
1192: */
1193: protected final void updateFilterSelection(Object[] elements) {
1194:
1195: Collection resourceCollection = new ArrayList();
1196: for (int i = 0; i < elements.length; i++) {
1197: if (elements[i] instanceof IResource) {
1198: resourceCollection.add(elements[i]);
1199: } else {
1200: addResources(resourceCollection,
1201: ((ResourceMapping) elements[i]));
1202: }
1203: }
1204:
1205: IResource[] resources = new IResource[resourceCollection.size()];
1206: resourceCollection.toArray(resources);
1207:
1208: for (int i = 0; i < markerFilters.length; i++) {
1209: markerFilters[i].setFocusResource(resources);
1210: }
1211:
1212: Iterator systemFilters = MarkerSupportRegistry.getInstance()
1213: .getRegisteredFilters().iterator();
1214:
1215: while (systemFilters.hasNext()) {
1216: MarkerFilter filter = (MarkerFilter) systemFilters.next();
1217: filter.setFocusResource(resources);
1218:
1219: }
1220:
1221: }
1222:
1223: /**
1224: * Add the resources for the mapping to resources.
1225: *
1226: * @param resources
1227: * @param mapping
1228: */
1229: private void addResources(Collection resources,
1230: ResourceMapping mapping) {
1231: try {
1232: ResourceTraversal[] traversals = mapping.getTraversals(
1233: ResourceMappingContext.LOCAL_CONTEXT,
1234: new NullProgressMonitor());
1235: for (int i = 0; i < traversals.length; i++) {
1236: ResourceTraversal traversal = traversals[i];
1237: IResource[] result = traversal.getResources();
1238: for (int j = 0; j < result.length; j++) {
1239: resources.add(result[j]);
1240: }
1241: }
1242: } catch (CoreException e) {
1243: Util.log(e);
1244: return;
1245: }
1246:
1247: }
1248:
1249: protected abstract String getStaticContextId();
1250:
1251: /**
1252: * Update the focus markers for the supplied elements.
1253: *
1254: * @param elements
1255: */
1256: void updateFocusMarkers(Object[] elements) {
1257: boolean updateNeeded = updateNeeded(focusElements, elements);
1258: if (updateNeeded) {
1259: focusElements = elements;
1260: refreshForFocusUpdate();
1261: }
1262: }
1263:
1264: private boolean updateNeeded(Object[] oldElements,
1265: Object[] newElements) {
1266: // determine if an update if refiltering is required
1267: MarkerFilter[] filters = getEnabledFilters();
1268: boolean updateNeeded = false;
1269:
1270: for (int i = 0; i < filters.length; i++) {
1271: MarkerFilter filter = filters[i];
1272: if (!filter.isEnabled()) {
1273: continue;
1274: }
1275:
1276: int onResource = filter.getOnResource();
1277: if (onResource == MarkerFilter.ON_ANY
1278: || onResource == MarkerFilter.ON_WORKING_SET) {
1279: continue;
1280: }
1281: if (newElements == null || newElements.length < 1) {
1282: continue;
1283: }
1284: if (oldElements == null || oldElements.length < 1) {
1285: return true;
1286: }
1287: if (Arrays.equals(oldElements, newElements)) {
1288: continue;
1289: }
1290: if (onResource == MarkerFilter.ON_ANY_IN_SAME_CONTAINER) {
1291: Collection oldProjects = MarkerFilter
1292: .getProjectsAsCollection(oldElements);
1293: Collection newProjects = MarkerFilter
1294: .getProjectsAsCollection(newElements);
1295:
1296: if (oldProjects.size() == newProjects.size()) {
1297: if (newProjects.containsAll(oldProjects)) {
1298: continue;
1299: }
1300: }
1301:
1302: return true;
1303: }
1304: updateNeeded = true;// We are updating as there is nothing to stop
1305: // us
1306: }
1307:
1308: return updateNeeded;
1309: }
1310:
1311: void updateTitle() {
1312: String status = Util.EMPTY_STRING;
1313: int filteredCount = getCurrentMarkers().getItemCount();
1314: int totalCount = getTotalMarkers();
1315: if (filteredCount == totalCount) {
1316: status = NLS.bind(MarkerMessages.filter_itemsMessage,
1317: new Integer(totalCount));
1318: } else {
1319: status = NLS
1320: .bind(MarkerMessages.filter_matchedMessage,
1321: new Integer(filteredCount), new Integer(
1322: totalCount));
1323: }
1324: setContentDescription(status);
1325: }
1326:
1327: /**
1328: * Updates the message displayed in the status line. This method is invoked
1329: * in the following cases:
1330: * <ul>
1331: * <li>when this view is first created</li>
1332: * <li>when new elements are added</li>
1333: * <li>when something is deleted</li>
1334: * <li>when the filters change</li>
1335: * </ul>
1336: * <p>
1337: * By default, this method calls
1338: * <code>updateStatusMessage(IStructuredSelection)</code> with the current
1339: * selection or <code>null</code>. Classes wishing to override this
1340: * functionality, should just override the method
1341: * <code>updateStatusMessage(IStructuredSelection)</code>.
1342: * </p>
1343: */
1344: protected void updateStatusMessage() {
1345: ISelection selection = getViewer().getSelection();
1346:
1347: if (selection instanceof IStructuredSelection) {
1348: updateStatusMessage((IStructuredSelection) selection);
1349: } else {
1350: updateStatusMessage(null);
1351: }
1352: }
1353:
1354: /**
1355: * Updates that message displayed in the status line. If the selection
1356: * parameter is <code>null</code> or its size is 0, the status area is
1357: * blanked out. If only 1 marker is selected, the status area is updated
1358: * with the contents of the message attribute of this marker. In other cases
1359: * (more than one marker is selected) the status area indicates how many
1360: * items have been selected.
1361: * <p>
1362: * This method may be overwritten.
1363: * </p>
1364: * <p>
1365: * This method is called whenever a selection changes in this view.
1366: * </p>
1367: *
1368: * @param selection
1369: * a valid selection or <code>null</code>
1370: */
1371: protected void updateStatusMessage(IStructuredSelection selection) {
1372: String message = ""; //$NON-NLS-1$
1373:
1374: if (selection == null || selection.size() == 0) {
1375: // Show stats on all items in the view
1376: message = updateSummaryVisible();
1377: } else if (selection.size() == 1) {
1378: // Use the Message attribute of the marker
1379: Object first = selection.getFirstElement();
1380: if (first instanceof ConcreteMarker) {
1381: message = ((ConcreteMarker) first).getDescription();
1382: }
1383: } else if (selection.size() > 1) {
1384: // Show stats on only those items in the selection
1385: message = updateSummarySelected(selection);
1386: }
1387: getViewSite().getActionBars().getStatusLineManager()
1388: .setMessage(message);
1389: }
1390:
1391: /**
1392: * @param selection
1393: * @return the summary status message
1394: */
1395: protected String updateSummarySelected(
1396: IStructuredSelection selection) {
1397: // Show how many items selected
1398: return MessageFormat.format(
1399: MarkerMessages.marker_statusSummarySelected,
1400: new Object[] { new Integer(selection.size()) });
1401: }
1402:
1403: /**
1404: * @return the update summary
1405: */
1406: protected String updateSummaryVisible() {
1407: return ""; //$NON-NLS-1$
1408: }
1409:
1410: /**
1411: * Open a dialog on the filters
1412: *
1413: */
1414: public final void openFiltersDialog() {
1415:
1416: DialogMarkerFilter dialog = createFiltersDialog();
1417:
1418: if (dialog.open() == Window.OK) {
1419:
1420: MarkerFilter[] result = dialog.getFilters();
1421: if (result == null) {
1422: return;
1423: }
1424: if (result.length == 0) {
1425: setFilters(new MarkerFilter[] { createFilter(MarkerMessages.MarkerFilter_defaultFilterName) });
1426: } else {
1427: setFilters(result);
1428: }
1429:
1430: updateForFilterChanges();
1431: }
1432: }
1433:
1434: /**
1435: * Refresh the contents of the viewer.
1436: */
1437: public void refreshViewer() {
1438: scheduleMarkerUpdate(Util.SHORT_DELAY);
1439: }
1440:
1441: /**
1442: * Set the filters to newFilters.
1443: *
1444: * @param newFilters
1445: */
1446: void setFilters(MarkerFilter[] newFilters) {
1447: markerFilters = newFilters;
1448: }
1449:
1450: /**
1451: * Clear the cache of enabled filters.
1452: *
1453: */
1454: void clearEnabledFilters() {
1455: enabledFilters = null;
1456: }
1457:
1458: /**
1459: * Refresh the contents of the filter sub menu.
1460: */
1461: private void refreshFilterMenu() {
1462: if (filtersMenu == null) {
1463: return;
1464: }
1465: filtersMenu.removeAll();
1466: MarkerFilter[] filters = getAllFilters();
1467: for (int i = 0; i < filters.length; i++) {
1468: filtersMenu
1469: .add(new FilterEnablementAction(filters[i], this ));
1470: }
1471:
1472: }
1473:
1474: /**
1475: * Open a filter dialog on the receiver.
1476: */
1477: protected abstract DialogMarkerFilter createFiltersDialog();
1478:
1479: /**
1480: * Given a selection of IMarker, reveals the corresponding elements in the
1481: * viewer
1482: *
1483: * @param structuredSelection
1484: * @param reveal
1485: */
1486: public void setSelection(IStructuredSelection structuredSelection,
1487: boolean reveal) {
1488: TreeViewer viewer = getViewer();
1489:
1490: List newSelection = new ArrayList(structuredSelection.size());
1491:
1492: for (Iterator i = structuredSelection.iterator(); i.hasNext();) {
1493: Object next = i.next();
1494: if (next instanceof IMarker) {
1495: ConcreteMarker marker = getCurrentMarkers().getMarker(
1496: (IMarker) next);
1497: if (marker != null) {
1498: newSelection.add(marker);
1499: }
1500: }
1501: }
1502:
1503: if (viewer != null) {
1504: viewer.setSelection(new StructuredSelection(newSelection),
1505: reveal);
1506: }
1507: }
1508:
1509: protected MarkerList getVisibleMarkers() {
1510: return getCurrentMarkers();
1511: }
1512:
1513: /**
1514: * Returns the total number of markers. Should not be called while the
1515: * marker list is still updating.
1516: *
1517: * @return the total number of markers in the workspace (including
1518: * everything that doesn't pass the filters)
1519: */
1520: int getTotalMarkers() {
1521: // The number of visible markers should never exceed the total number of
1522: // markers in
1523: // the workspace. If this assertation fails, it probably indicates some
1524: // sort of concurrency problem
1525: // (most likely, getTotalMarkers was called while we were still
1526: // computing the marker lists)
1527: // Assert.isTrue(totalMarkers >= currentMarkers.getItemCount());
1528:
1529: return totalMarkers;
1530: }
1531:
1532: /*
1533: * (non-Javadoc)
1534: *
1535: * @see org.eclipse.ui.part.WorkbenchPart#showBusy(boolean)
1536: */
1537: public void showBusy(boolean busy) {
1538: super .showBusy(busy);
1539:
1540: if (busy) {
1541: preBusyMarkers = totalMarkers;
1542: } else {// Only bold if there has been a change in count
1543: if (totalMarkers != preBusyMarkers) {
1544: getProgressService().warnOfContentChange();
1545: }
1546: }
1547:
1548: }
1549:
1550: /**
1551: * Get the filters that are currently enabled.
1552: *
1553: * @return MarkerFilter[]
1554: */
1555: MarkerFilter[] getEnabledFilters() {
1556:
1557: if (enabledFilters == null) {
1558: Collection filters = findEnabledFilters();
1559:
1560: enabledFilters = new MarkerFilter[filters.size()];
1561: filters.toArray(enabledFilters);
1562: }
1563: return enabledFilters;
1564:
1565: }
1566:
1567: /**
1568: * Find the filters enabled in the view.
1569: *
1570: * @return Collection of MarkerFilter
1571: */
1572: protected Collection findEnabledFilters() {
1573: MarkerFilter[] allFilters = getAllFilters();
1574: ArrayList filters = new ArrayList(0);
1575: for (int i = 0; i < allFilters.length; i++) {
1576: if (allFilters[i].isEnabled()) {
1577: filters.add(allFilters[i]);
1578: }
1579: }
1580: return filters;
1581: }
1582:
1583: /**
1584: * Get all of the filters applied to the receiver.
1585: *
1586: * @return MarkerFilter[]
1587: */
1588: MarkerFilter[] getAllFilters() {
1589: return getUserFilters();
1590: }
1591:
1592: /*
1593: * (non-Javadoc)
1594: *
1595: * @see org.eclipse.ui.views.markers.internal.TableView#addDropDownContributions(org.eclipse.jface.action.IMenuManager)
1596: */
1597: void addDropDownContributions(IMenuManager menu) {
1598: super .addDropDownContributions(menu);
1599:
1600: menu.add(new Separator(MENU_FILTERS_GROUP));
1601: // Don't add in the filters until they are set
1602: filtersMenu = new MenuManager(
1603: MarkerMessages.filtersSubMenu_title);
1604: refreshFilterMenu();
1605: menu.appendToGroup(MENU_FILTERS_GROUP, filtersMenu);
1606: }
1607:
1608: /**
1609: * Create the show in menu if there is a single selection.
1610: *
1611: * @param menu
1612: */
1613: void createShowInMenu(IMenuManager menu) {
1614: ISelection selection = getViewer().getSelection();
1615: if (!(selection instanceof IStructuredSelection)) {
1616: return;
1617: }
1618:
1619: IStructuredSelection structured = (IStructuredSelection) selection;
1620: if (!Util.isSingleConcreteSelection(structured)) {
1621: return;
1622: }
1623:
1624: menu.add(new Separator(MENU_SHOW_IN_GROUP));
1625: // Don't add in the filters until they are set
1626:
1627: String showInLabel = IDEWorkbenchMessages.Workbench_showIn;
1628: IBindingService bindingService = (IBindingService) PlatformUI
1629: .getWorkbench().getAdapter(IBindingService.class);
1630: if (bindingService != null) {
1631: String keyBinding = bindingService
1632: .getBestActiveBindingFormattedFor("org.eclipse.ui.navigate.showInQuickMenu"); //$NON-NLS-1$
1633: if (keyBinding != null) {
1634: showInLabel += '\t' + keyBinding;
1635: }
1636: }
1637: showInMenu = new MenuManager(showInLabel);
1638: showInMenu.add(ContributionItemFactory.VIEWS_SHOW_IN
1639: .create(getViewSite().getWorkbenchWindow()));
1640:
1641: menu.appendToGroup(MENU_SHOW_IN_GROUP, showInMenu);
1642:
1643: }
1644:
1645: /**
1646: * Refresh the marker counts
1647: *
1648: * @param monitor
1649: */
1650: void refreshMarkerCounts(IProgressMonitor monitor) {
1651: monitor.subTask(MarkerMessages.MarkerView_refreshing_counts);
1652: try {
1653: totalMarkers = MarkerList.compute(getMarkerTypes()).length;
1654: } catch (CoreException e) {
1655: Util.log(e);
1656: return;
1657: }
1658:
1659: }
1660:
1661: /**
1662: * Returns the marker limit or -1 if unlimited
1663: *
1664: * @return int
1665: */
1666: int getMarkerLimit() {
1667:
1668: // If limits are enabled return it. Otherwise return -1
1669: if (IDEWorkbenchPlugin.getDefault().getPreferenceStore()
1670: .getBoolean(getMarkerEnablementPreferenceName())) {
1671: return IDEWorkbenchPlugin.getDefault().getPreferenceStore()
1672: .getInt(getMarkerLimitPreferenceName());
1673:
1674: }
1675: return -1;
1676:
1677: }
1678:
1679: /**
1680: * Get the name of the marker limit preference.
1681: *
1682: * @return String
1683: */
1684: abstract String getMarkerEnablementPreferenceName();
1685:
1686: /*
1687: * (non-Javadoc)
1688: *
1689: * @see org.eclipse.ui.views.markers.internal.TableView#createViewerInput()
1690: */
1691: Object createViewerInput() {
1692: adapter = new MarkerAdapter(this );
1693: return adapter;
1694: }
1695:
1696: /**
1697: * Add a listener for the end of the update.
1698: *
1699: * @param listener
1700: */
1701: public void addUpdateFinishListener(IJobChangeListener listener) {
1702: updateJob.addJobChangeListener(listener);
1703:
1704: }
1705:
1706: /**
1707: * Remove a listener for the end of the update.
1708: *
1709: * @param listener
1710: */
1711: public void removeUpdateFinishListener(IJobChangeListener listener) {
1712: updateJob.removeJobChangeListener(listener);
1713:
1714: }
1715:
1716: /**
1717: * Create a listener for working set changes.
1718: *
1719: * @return IPropertyChangeListener
1720: */
1721: private IPropertyChangeListener getWorkingSetListener() {
1722: workingSetListener = new IPropertyChangeListener() {
1723: /*
1724: * (non-Javadoc)
1725: *
1726: * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
1727: */
1728: public void propertyChange(PropertyChangeEvent event) {
1729: clearEnabledFilters();
1730: refreshViewer();
1731:
1732: }
1733: };
1734: return workingSetListener;
1735: }
1736:
1737: /**
1738: * Schedule an update of the markers with a delay of time
1739: *
1740: * @param time
1741: */
1742: void scheduleMarkerUpdate(int time) {
1743: cancelJobs();
1744: getProgressService().schedule(markerProcessJob, time);
1745: }
1746:
1747: /**
1748: * Cancel the pending jobs in the receiver.
1749: */
1750: private void cancelJobs() {
1751: markerProcessJob.cancel();
1752: updateJob.cancel();
1753: }
1754:
1755: /*
1756: * (non-Javadoc)
1757: *
1758: * @see org.eclipse.ui.views.markers.internal.TableView#createTree(org.eclipse.swt.widgets.Composite)
1759: */
1760: protected Tree createTree(Composite parent) {
1761: Tree tree = super .createTree(parent);
1762: tree.addTreeListener(new TreeAdapter() {
1763: /*
1764: * (non-Javadoc)
1765: *
1766: * @see org.eclipse.swt.events.TreeAdapter#treeCollapsed(org.eclipse.swt.events.TreeEvent)
1767: */
1768: public void treeCollapsed(TreeEvent e) {
1769: updateJob
1770: .removeExpandedCategory((MarkerCategory) e.item
1771: .getData());
1772: }
1773:
1774: /*
1775: * (non-Javadoc)
1776: *
1777: * @see org.eclipse.swt.events.TreeAdapter#treeExpanded(org.eclipse.swt.events.TreeEvent)
1778: */
1779: public void treeExpanded(TreeEvent e) {
1780: updateJob.addExpandedCategory((MarkerCategory) e.item
1781: .getData());
1782: }
1783: });
1784:
1785: return tree;
1786: }
1787:
1788: /**
1789: * The focus elements have changed. Update accordingly.
1790: */
1791: private void refreshForFocusUpdate() {
1792: if (focusElements != null) {
1793: updateFilterSelection(focusElements);
1794: refreshViewer();
1795: }
1796: }
1797:
1798: /**
1799: * Save the current selection in the update for reselection after update.
1800: */
1801: protected void preserveSelection() {
1802: updateJob.saveSelection(getViewer().getSelection());
1803:
1804: }
1805:
1806: /**
1807: * Return the string name of the specific type of marker shown in this view.
1808: */
1809: protected abstract String getMarkerName();
1810:
1811: /**
1812: * Return the undo context associated with operations performed in this
1813: * view. By default, return the workspace undo context. Subclasses should
1814: * override if a more specific undo context should be used.
1815: */
1816: protected IUndoContext getUndoContext() {
1817: return (IUndoContext) ResourcesPlugin.getWorkspace()
1818: .getAdapter(IUndoContext.class);
1819: }
1820:
1821: }
|