blob: 7fbab03fdc648e66b1bb01d3dbf81730e9dd98a2 [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;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.mylar.internal.core.util.MylarStatusHandler;
import org.eclipse.mylar.internal.ui.actions.AbstractApplyMylarAction;
import org.eclipse.mylar.provisional.core.IMylarContext;
import org.eclipse.mylar.provisional.core.IMylarContextListener;
import org.eclipse.mylar.provisional.core.IMylarElement;
import org.eclipse.mylar.provisional.core.IMylarStructureBridge;
import org.eclipse.mylar.provisional.core.MylarPlugin;
import org.eclipse.mylar.provisional.ui.MylarUiPlugin;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;
/**
* Encapsualted the element refresh and expansion state policy for all viewers
* showing Mylar context.
*
* @author Mik Kersten
*/
public class MylarViewerManager implements IMylarContextListener, IPropertyChangeListener {
private List<StructuredViewer> managedViewers = new ArrayList<StructuredViewer>();
private List<StructuredViewer> filteredViewers = new ArrayList<StructuredViewer>();
private List<AbstractApplyMylarAction> managedActions = new ArrayList<AbstractApplyMylarAction>();
private Map<StructuredViewer, BrowseFilteredListener> listenerMap = new HashMap<StructuredViewer, BrowseFilteredListener>();
private Map<IViewPart, StructuredViewer> partToViewerMap = new HashMap<IViewPart, StructuredViewer>();
/**
* For testing.
*/
private boolean syncRefreshMode = false;
private AbstractPartTracker VIEWER_PART_TRACKER = new AbstractPartTracker() {
@Override
public void partActivated(IWorkbenchPart part) {
if (partToViewerMap.containsKey(part)) {
StructuredViewer viewer = partToViewerMap.get(part);
refreshViewer(null, false, viewer);
}
}
@Override
public void partBroughtToTop(IWorkbenchPart part) {
}
@Override
public void partClosed(IWorkbenchPart part) {
// ignore
}
@Override
public void partDeactivated(IWorkbenchPart part) {
// ignore
}
@Override
public void partOpened(IWorkbenchPart part) {
// ignore
}
};
public MylarViewerManager() {
MylarUiPlugin.getPrefs().addPropertyChangeListener(this);
VIEWER_PART_TRACKER.install(PlatformUI.getWorkbench());
}
public void dispose() {
VIEWER_PART_TRACKER.dispose(PlatformUI.getWorkbench());
}
public void addManagedAction(AbstractApplyMylarAction action) {
managedActions.add(action);
}
public void removeManagedAction(AbstractApplyMylarAction action) {
managedActions.remove(action);
}
public void addManagedViewer(StructuredViewer viewer, IViewPart viewPart) {
if (!managedViewers.contains(viewer)) {
managedViewers.add(viewer);
partToViewerMap.put(viewPart, viewer);
BrowseFilteredListener listener = new BrowseFilteredListener(viewer);
listenerMap.put(viewer, listener);
viewer.getControl().addMouseListener(listener);
viewer.getControl().addKeyListener(listener);
}
}
public void removeManagedViewer(StructuredViewer viewer, IViewPart viewPart) {
managedViewers.remove(viewer);
partToViewerMap.remove(viewPart);
BrowseFilteredListener listener = listenerMap.get(viewer);
if (listener != null && viewer != null && !viewer.getControl().isDisposed()) {
viewer.getControl().removeMouseListener(listener);
viewer.getControl().removeKeyListener(listener);
}
}
public void addFilteredViewer(StructuredViewer viewer) {
if (!filteredViewers.contains(viewer)) {
filteredViewers.add(viewer);
}
}
public void removeFilteredViewer(StructuredViewer viewer) {
filteredViewers.remove(viewer);
}
public void contextActivated(IMylarContext context) {
if (context.getActiveNode() != null) {
for (AbstractApplyMylarAction action : managedActions) {
action.update(true);
}
}
refreshViewers();
}
public void contextDeactivated(IMylarContext context) {
for (AbstractApplyMylarAction action : managedActions) {
action.update(false);
}
refreshViewers();
}
public void presentationSettingsChanging(UpdateKind kind) {
// ignore
}
public void presentationSettingsChanged(UpdateKind kind) {
refreshViewers();
}
protected void refreshViewers() {
List<IMylarElement> toRefresh = Collections.emptyList();
refreshViewers(toRefresh, true);
}
protected void refreshViewers(IMylarElement node, boolean updateLabels) {
List<IMylarElement> toRefresh = new ArrayList<IMylarElement>();
toRefresh.add(node);
refreshViewers(toRefresh, updateLabels);
}
public void interestChanged(final List<IMylarElement> nodes) {
refreshViewers(nodes, false);
}
protected void refreshViewers(final List<IMylarElement> nodesToRefresh, final boolean updateLabels) {
if (syncRefreshMode) {
internalRefresh(nodesToRefresh, updateLabels);
} else {
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
public void run() {
internalRefresh(nodesToRefresh, updateLabels);
}
});
}
}
private void internalRefresh(final List<IMylarElement> nodesToRefresh, final boolean updateLabels) {
try {
for (StructuredViewer viewer : new ArrayList<StructuredViewer>(managedViewers)) {
refreshViewer(nodesToRefresh, updateLabels, viewer);
}
} catch (Throwable t) {
MylarStatusHandler.fail(t, "could not refresh viewer", false);
}
}
private void refreshViewer(final List<IMylarElement> nodesToRefresh, final boolean minor, StructuredViewer viewer) {
if (viewer == null) {
return;
} else if (viewer.getControl().isDisposed()) {
managedViewers.remove(viewer);
} else { //if (viewer.getControl().isVisible()) {
if (nodesToRefresh == null || nodesToRefresh.isEmpty()) {
if (!minor) {
viewer.refresh(false);
updateExpansionState(viewer, null);
} else {
viewer.getControl().setRedraw(false);
viewer.refresh(true);
updateExpansionState(viewer, null);
viewer.getControl().setRedraw(true);
}
} else {
if (filteredViewers.contains(viewer)) {
viewer.getControl().setRedraw(false);
viewer.refresh(minor);
updateExpansionState(viewer, null);
viewer.getControl().setRedraw(true);
} else { // don't need to worry about content changes
viewer.getControl().setRedraw(false);
for (IMylarElement node : nodesToRefresh) {
IMylarStructureBridge structureBridge = MylarPlugin.getDefault().getStructureBridge(
node.getContentType());
Object objectToRefresh = structureBridge.getObjectForHandle(node.getHandleIdentifier());
if (objectToRefresh != null) {
viewer.update(objectToRefresh, null);
updateExpansionState(viewer, objectToRefresh);
}
}
viewer.getControl().setRedraw(true);
}
}
}
}
private void updateExpansionState(StructuredViewer viewer, Object objectToRefresh) {
if (viewer instanceof TreeViewer && filteredViewers.contains(viewer)) {
TreeViewer treeViewer = (TreeViewer)viewer;
if (objectToRefresh == null) {
treeViewer.expandAll();
} else {
treeViewer.expandToLevel(objectToRefresh, TreeViewer.ALL_LEVELS);
}
}
}
public void nodeDeleted(IMylarElement node) {
IMylarStructureBridge structureBridge = MylarPlugin.getDefault().getStructureBridge(node.getContentType());
IMylarElement parent = MylarPlugin.getContextManager().getElement(
structureBridge.getParentHandle(node.getHandleIdentifier()));
ArrayList<IMylarElement> toRefresh = new ArrayList<IMylarElement>();
if (parent != null) {
toRefresh.add(parent);
refreshViewers(toRefresh, false);
}
}
public void landmarkAdded(IMylarElement node) {
refreshViewers(node, true);
}
public void landmarkRemoved(IMylarElement node) {
refreshViewers(node, true);
}
public void edgesChanged(IMylarElement node) {
// ignore
}
public void propertyChange(PropertyChangeEvent event) {
if (MylarUiPrefContstants.INTEREST_FILTER_EXCLUSION.equals(event.getProperty())) {
refreshViewers();
}
}
/**
* Set to true for testing
*/
public void setSyncRefreshMode(boolean syncRefreshMode) {
this.syncRefreshMode = syncRefreshMode;
}
}