blob: 27f6fb3f8dd47d212c123a79561fca30f7151d64 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004 - 2006 University Of British Columbia 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:
* University Of British Columbia - initial API and implementation
*******************************************************************************/
package org.eclipse.mylar.internal.ui.actions;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.mylar.internal.core.util.MylarStatusHandler;
import org.eclipse.mylar.internal.ui.MylarImages;
import org.eclipse.mylar.provisional.core.MylarPlugin;
import org.eclipse.mylar.provisional.ui.InterestFilter;
import org.eclipse.mylar.provisional.ui.MylarUiPlugin;
import org.eclipse.swt.widgets.Event;
import org.eclipse.ui.IActionDelegate2;
import org.eclipse.ui.IViewActionDelegate;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
import org.eclipse.ui.PlatformUI;
/**
* Extending this class makes it possible to apply Mylar management to a
* structured view (e.g. to provide interest-based filtering).
*
* @author Mik Kersten
*/
public abstract class AbstractApplyMylarAction extends Action implements IViewActionDelegate, IActionDelegate2 {
private static final String ACTION_LABEL = "Apply Mylar";
public static final String PREF_ID_PREFIX = "org.eclipse.mylar.ui.interest.filter.";
protected String globalPrefId;
protected IAction initAction = null;
protected final InterestFilter interestFilter;
protected IViewPart viewPart;
protected Map<StructuredViewer, List<ViewerFilter>> previousFilters = new WeakHashMap<StructuredViewer, List<ViewerFilter>>();
private static Map<IViewPart, AbstractApplyMylarAction> partMap = new WeakHashMap<IViewPart, AbstractApplyMylarAction>();
public static AbstractApplyMylarAction getActionForPart(IViewPart part) {
return partMap.get(part);
}
public IViewPart getPartForAction() {
if (viewPart == null) {
if (this instanceof IWorkbenchWindowActionDelegate) {
throw new RuntimeException("not supported on IWorkbenchWindowActionDelegate");
} else {
throw new RuntimeException("error: viewPart is null");
}
}
return viewPart;
}
public AbstractApplyMylarAction(InterestFilter interestFilter) {
super();
this.interestFilter = interestFilter;
setText(ACTION_LABEL);
setToolTipText(ACTION_LABEL);
setImageDescriptor(MylarImages.INTEREST_FILTERING);
}
public void init(IAction action) {
initAction = action;
setChecked(action.isChecked());
}
public void init(IViewPart view) {
String id = view.getSite().getId();
globalPrefId = PREF_ID_PREFIX + id;
viewPart = view;
partMap.put(view, this);
}
public void run(IAction action) {
setChecked(action.isChecked());
valueChanged(action, action.isChecked(), true);
}
/**
* Don't update if the preference has not been initialized.
*/
public void update() {
if (globalPrefId != null) {
update(MylarPlugin.getDefault().getPreferenceStore().getBoolean(globalPrefId));
}
}
/**
* This operation is expensive.
*/
public void update(boolean on) {
valueChanged(initAction, on, false);
}
protected void valueChanged(IAction action, final boolean on, boolean store) {
if (PlatformUI.getWorkbench().isClosing()) {
return;
}
try {
MylarPlugin.getContextManager().setContextCapturePaused(true);
setChecked(on);
action.setChecked(on);
if (store && MylarPlugin.getDefault() != null) {
MylarPlugin.getDefault().getPreferenceStore().setValue(globalPrefId, on);
}
for (StructuredViewer viewer : getViewers()) {
if (viewPart != null && !viewer.getControl().isDisposed()) {
MylarUiPlugin.getDefault().getViewerManager().addManagedViewer(viewer, viewPart);
}
updateInterestFilter(on, viewer);
}
} catch (Throwable t) {
MylarStatusHandler.fail(t, "Could not install viewer manager on: " + globalPrefId, false);
} finally {
MylarPlugin.getContextManager().setContextCapturePaused(false);
}
}
/**
* Public for testing
*/
public void updateInterestFilter(final boolean on, StructuredViewer viewer) {
if (viewer != null) {
if (on) {
installInterestFilter(viewer);
MylarUiPlugin.getDefault().getViewerManager().addFilteredViewer(viewer);
} else {
MylarUiPlugin.getDefault().getViewerManager().removeFilteredViewer(viewer);
uninstallInterestFilter(viewer);
}
}
}
/**
* Public for testing
*/
public abstract List<StructuredViewer> getViewers();
/**
* @return filters that should not be removed when the interest filter is
* installed
*/
public abstract List<Class> getPreservedFilters();
protected boolean installInterestFilter(StructuredViewer viewer) {
if (viewer == null) {
MylarStatusHandler.log("The viewer to install InterestFilter is null", this);
return false;
} else if (viewer.getControl().isDisposed()) {
// TODO: do this with part listener, not lazily?
MylarUiPlugin.getDefault().getViewerManager().removeManagedViewer(viewer, viewPart);
return false;
}
try {
viewer.getControl().setRedraw(false);
previousFilters.put(viewer, Arrays.asList(viewer.getFilters()));
List<Class> excludedFilters = getPreservedFilters();
for (ViewerFilter filter : previousFilters.get(viewer)) {
if (!excludedFilters.contains(filter.getClass())) {
try {
viewer.removeFilter(filter);
} catch (Throwable t) {
MylarStatusHandler.fail(t, "Failed to remove filter: " + filter, false);
}
}
}
viewer.addFilter(interestFilter);
if (viewer instanceof TreeViewer) {
((TreeViewer) viewer).expandAll();
}
viewer.getControl().setRedraw(true);
return true;
} catch (Throwable t) {
MylarStatusHandler.fail(t, "Could not install viewer filter on: " + globalPrefId, false);
}
return false;
}
protected void uninstallInterestFilter(StructuredViewer viewer) {
if (viewer == null) {
MylarStatusHandler.log("Could not uninstall interest filter", this);
return;
} else if (viewer.getControl().isDisposed()) {
// TODO: do this with part listener, not lazily?
MylarUiPlugin.getDefault().getViewerManager().removeManagedViewer(viewer, viewPart);
return;
}
viewer.getControl().setRedraw(false);
List<Class> excludedFilters = getPreservedFilters();
if (previousFilters.containsKey(viewer)) {
for (ViewerFilter filter : previousFilters.get(viewer)) {
if (!excludedFilters.contains(filter.getClass())) {
try {
viewer.addFilter(filter);
} catch (Throwable t) {
MylarStatusHandler.fail(t, "Failed to remove filter: " + filter, false);
}
}
}
previousFilters.remove(viewer);
}
// previousFilters.remove(key)();
for (ViewerFilter filter : Arrays.asList(viewer.getFilters())) {
if (filter instanceof InterestFilter) {
viewer.removeFilter(interestFilter);
}
}
viewer.getControl().setRedraw(true);
}
public void selectionChanged(IAction action, ISelection selection) {
// ignore
}
public void dispose() {
partMap.remove(getPartForAction());
if (viewPart != null && !PlatformUI.getWorkbench().isClosing()) {
for (StructuredViewer viewer : getViewers()) {
MylarUiPlugin.getDefault().getViewerManager().removeManagedViewer(viewer, viewPart);
}
}
}
public void runWithEvent(IAction action, Event event) {
run(action);
}
public String getGlobalPrefId() {
return globalPrefId;
}
/**
* For testing.
*/
public InterestFilter getInterestFilter() {
return interestFilter;
}
}