/*******************************************************************************
* Copyright (c) 2009 Johannes Utzig.
* 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:
* Johannes Utzig - initial API and implementation
*******************************************************************************/
package org.eclipse.buckminster.ui.dependency.visualizer.viewer;
import java.util.List;
import org.eclipse.buckminster.core.cspec.model.CSpec;
import org.eclipse.buckminster.core.metadata.model.BOMNode;
import org.eclipse.buckminster.ui.actions.ViewChosenCSpecAction;
import org.eclipse.buckminster.ui.dependency.visualizer.Messages;
import org.eclipse.buckminster.ui.dependency.visualizer.controls.listener.IViewerSettingChangeListener;
import org.eclipse.buckminster.ui.dependency.visualizer.controls.listener.ViewerSettingChangeEvent;
import org.eclipse.buckminster.ui.dependency.visualizer.viewer.provider.DependencyContentProvider;
import org.eclipse.buckminster.ui.dependency.visualizer.viewer.provider.DependencyLabelProvider;
import org.eclipse.buckminster.ui.dependency.visualizer.viewer.provider.IDependencyVisualizationLabelProvider;
import org.eclipse.buckminster.ui.dependency.visualizer.viewer.provider.IRelationshipProvider;
import org.eclipse.buckminster.ui.dependency.visualizer.viewer.provider.SimpleDependencyVisualizationLabelProvider;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.zest.core.viewers.GraphViewer;
import org.eclipse.zest.core.widgets.ZestStyles;
import org.eclipse.zest.layouts.LayoutAlgorithm;
public class DependencyViewer extends GraphViewer implements IViewerSettingChangeListener {
private IDependencyVisualizationLabelProvider labelProvider;
public DependencyViewer(Composite composite, int style) {
super(composite, SWT.NONE);
// setLayoutAlgorithm(new
// RadialLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING));
// setLayoutAlgorithm(new
// TreeLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING));
setConnectionStyle(ZestStyles.CONNECTIONS_DIRECTED);
// labelProvider = new HighlightDependencyLableProvider(this, null);
labelProvider = new SimpleDependencyVisualizationLabelProvider(new DependencyLabelProvider(), this);
setLabelProvider(labelProvider);
setContentProvider(new DependencyContentProvider());
getGraphControl().addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
labelProvider.dispose();
}
});
addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
ISelection selection = event.getSelection();
if (selection.isEmpty())
labelProvider.highlightSelection(null);
if (selection instanceof IStructuredSelection) {
IStructuredSelection sel = (IStructuredSelection) selection;
Object o = sel.getFirstElement();
if (o instanceof BOMNode) {
BOMNode node = (BOMNode) o;
labelProvider.highlightSelection(node);
}
}
// labelProvider.highlightSelection(selection)setCurrentSelection(((IStructuredSelection)event.getSelection()).getFirstElement(),
// ((IStructuredSelection)event.getSelection()).getFirstElement());
}
});
addDoubleClickListener(new IDoubleClickListener() {
@Override
public void doubleClick(DoubleClickEvent event) {
Object o = ((IStructuredSelection) event.getSelection()).getFirstElement();
if (o instanceof BOMNode) {
BOMNode node = (BOMNode) o;
// Bug 291963 - NPE when clicking on an unresolved node
if (node.getResolution() != null && node.getResolution().getCSpec() != null) {
DirtyViewCSpecAction action = new DirtyViewCSpecAction();
action.run(node.getResolution().getCSpec(), PlatformUI.getWorkbench().getActiveWorkbenchWindow());
}
}
}
});
}
/**
* calls {@link GraphViewer#setInput(Object)} and
* {@link IDependencyVisualizationLabelProvider#setRoot(BOMNode)}
*
* @param input
* - a list of boms with (currently) exactly one {@link BOMNode}
*/
public void setInputAndRoot(List<? extends BOMNode> input) {
if (input.size() != 1)
throw new IllegalArgumentException(Messages.ListMustContainExactlyOneBom);
labelProvider.clear();
setInput(input);
BOMNode node = input.get(0);
labelProvider.setRoot(node);
labelProvider.highlightSelection(null);
}
/**
* overriden to inform the {@link IDependencyVisualizationLabelProvider}
* about the new selection
*/
@Override
public void setSelection(ISelection selection, boolean reveal) {
super.setSelection(selection, reveal);
if (selection.isEmpty())
labelProvider.highlightSelection(null);
if (selection instanceof IStructuredSelection) {
IStructuredSelection sel = (IStructuredSelection) selection;
Object o = sel.getFirstElement();
if (o instanceof BOMNode) {
BOMNode node = (BOMNode) o;
labelProvider.highlightSelection(node);
}
}
}
@Override
public void viewerSettingChanged(ViewerSettingChangeEvent event) {
switch (event.getType()) {
case PATH_HIGHLIGHTING:
setRelationshipProvider((IRelationshipProvider) event.getData());
break;
case FILTER_ADDED:
addFilter((ViewerFilter) event.getData());
applyLayout();
break;
case FILTER_REMOVED:
removeFilter((ViewerFilter) event.getData());
applyLayout();
break;
case LAYOUT_CHANGED:
setLayoutAlgorithm((LayoutAlgorithm) event.getData());
applyLayout();
default:
break;
}
}
/**
* sets the {@link IRelationshipProvider} that is responsible for
* highlighting interesting paths on selection
*
* @param provider
*/
private void setRelationshipProvider(IRelationshipProvider provider) {
labelProvider.setRelationshipProvider(provider);
}
}
// XXX: this is a hack. The CSpecEditorInput is not exported
// so ViewChosenCspecAction is subclassed instead to view a cspec
class DirtyViewCSpecAction extends ViewChosenCSpecAction {
@Override
public void run(CSpec cspec, IWorkbenchWindow wbWin) {
super.run(cspec, wbWin);
}
}