package org.bundlemaker.core.ui.view.stage.view;
import java.util.Collections;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import org.bundlemaker.core.analysis.IAnalysisModelModifiedListener;
import org.bundlemaker.core.analysis.IBundleMakerArtifact;
import org.bundlemaker.core.analysis.IResourceArtifact;
import org.bundlemaker.core.analysis.IRootArtifact;
import org.bundlemaker.core.analysis.IVirtualRoot;
import org.bundlemaker.core.selection.IArtifactSelection;
import org.bundlemaker.core.selection.IArtifactSelectionListener;
import org.bundlemaker.core.selection.Selection;
import org.bundlemaker.core.selection.stage.ArtifactStageAddMode;
import org.bundlemaker.core.selection.stage.ArtifactStageChangedEvent;
import org.bundlemaker.core.selection.stage.IArtifactStageChangeListener;
import org.bundlemaker.core.ui.artifact.ArtifactImages;
import org.bundlemaker.core.ui.artifact.CommonNavigatorUtils;
import org.bundlemaker.core.ui.artifact.tree.ArtifactTreeLabelProvider;
import org.bundlemaker.core.ui.artifact.tree.ArtifactTreeViewerSorter;
import org.bundlemaker.core.ui.view.stage.actions.AddModeActionGroup;
import org.bundlemaker.core.ui.view.stage.actions.StageIcons;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.util.LocalSelectionTransfer;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IColorProvider;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.navigator.CommonNavigator;
import org.eclipse.ui.part.DrillDownAdapter;
import org.eclipse.ui.part.ViewPart;
/**
* @author Nils Hartmann (nils@nilshartmann.net)
*
*/
public class StageView extends ViewPart {
/**
* The ID of the view as specified by the extension.
*/
public static final String ID = "org.bundlemaker.core.ui.stage.StageView";
protected final List<IBundleMakerArtifact> EMPTY_ARTIFACTS = Collections.emptyList();
private final IArtifactSelectionListener _artifactSelectionListener = new IArtifactSelectionListener() {
@Override
public void artifactSelectionChanged(
IArtifactSelection event) {
refreshTreeContent(event);
}
};
private final IArtifactStageChangeListener _artifactStageChangeListener = new IArtifactStageChangeListener() {
@Override
public void artifactStateChanged(
ArtifactStageChangedEvent event) {
artifactStageConfigurationChanged();
}
};
private final IAnalysisModelModifiedListener _modifiedListener = new IAnalysisModelModifiedListener() {
@Override
public void analysisModelModified() {
final IArtifactSelection selection = Selection
.instance()
.getArtifactSelectionService()
.getSelection(
Selection.ARTIFACT_STAGE_SELECTION_ID);
Display display = Display.getCurrent();
if (display != null) {
display.asyncExec(new Runnable() {
@Override
public void run() {
refreshTreeContent(selection);
}
});
}
}
};
private List<IBundleMakerArtifact> _effectiveSelectedArtifacts = Collections.emptyList();
private TreeViewer _treeViewer;
private DrillDownAdapter drillDownAdapter;
private Action _autoExpandAction;
private ClearStageAction _clearStageAction;
private RemoveFromStageAction _removeArtifactsAction;
private RevealInProjectExplorerAction _revealInProjectExplorerAction;
private boolean _autoExpand = true;
private AddModeActionGroup _addModeActionGroup;
private ArtifactStageContentProvider _artifactStageContentProvider;
/**
* The constructor.
*/
public StageView() {
}
/**
* This is a callback that will allow us to create the viewer and initialize it.
*/
@Override
public void createPartControl(Composite parent) {
_artifactStageContentProvider = new ArtifactStageContentProvider();
_treeViewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.NONE);
_treeViewer.setUseHashlookup(true);
_treeViewer.getTree().setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true));
_treeViewer.setSorter(new ArtifactTreeViewerSorter());
_treeViewer.setContentProvider(_artifactStageContentProvider);
_treeViewer.setLabelProvider(new StageViewLabelProvider());
_treeViewer.addDoubleClickListener(new IDoubleClickListener() {
@Override
public void doubleClick(DoubleClickEvent event) {
//
IStructuredSelection structuredSelection = (IStructuredSelection) event.getSelection();
if (structuredSelection.size() == 1) {
Object object = structuredSelection.getFirstElement();
_treeViewer.setExpandedState(object, !_treeViewer.getExpandedState(object));
}
}
});
int operations = DND.DROP_MOVE;
Transfer[] transferTypes = new Transfer[] { LocalSelectionTransfer.getTransfer() };
// _tre|eViewer.addDragSupport(operations, transferTypes, new ArtifactTreeDragAdapter(treeViewer));
_treeViewer.addDropSupport(operations, transferTypes, new ArtifactStageTreeDropAdapter(_treeViewer));
getSite().setSelectionProvider(_treeViewer);
// viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL |
// SWT.V_SCROLL);
// drillDownAdapter = new DrillDownAdapter(viewer);
// viewer.setContentProvider(new ViewContentProvider());
// viewer.setLabelProvider(new ViewLabelProvider());
// viewer.setSorter(new NameSorter());
// viewer.setInput(getViewSite());
makeActions();
hookContextMenu();
hookDoubleClickAction();
contributeToActionBars();
Selection.instance().getArtifactStage().addArtifactStageChangeListener(_artifactStageChangeListener);
Selection.instance().getArtifactSelectionService()
.addArtifactSelectionListener(Selection.ARTIFACT_STAGE_SELECTION_ID, _artifactSelectionListener);
IArtifactSelection selection = Selection.instance().getArtifactSelectionService()
.getSelection(Selection.ARTIFACT_STAGE_SELECTION_ID);
refreshTreeContent(selection);
}
private void refreshTreeContent(IArtifactSelection selection) {
unregisterArtifactModelModifiedListener();
if (selection == null) {
_effectiveSelectedArtifacts = Collections.emptyList();
} else {
_effectiveSelectedArtifacts = selection.getEffectiveSelectedArtifacts();
}
//
// set redraw to false
_treeViewer.getTree().setRedraw(false);
if (_effectiveSelectedArtifacts.size() > 0) {
Map<IBundleMakerArtifact, ArtifactHolder> artifactHolderCache = new Hashtable<IBundleMakerArtifact, ArtifactHolder>();
IRootArtifact root = null;
for (IBundleMakerArtifact artifact : _effectiveSelectedArtifacts) {
if (artifactHolderCache.containsKey(artifact)) {
// no need to walk up further, as artifact including it's parent already
// have been added
continue;
}
ArtifactHolder currentArtifactHolder = new ArtifactHolder();
if (root == null && artifact.isInstanceOf(IRootArtifact.class)) {
root = (IRootArtifact) artifact;
}
artifactHolderCache.put(artifact, currentArtifactHolder);
IBundleMakerArtifact parent = artifact.getParent();
IBundleMakerArtifact currentArtifact = artifact;
while (parent != null) {
ArtifactHolder parentHolder = artifactHolderCache.get(parent);
if (parentHolder != null) {
parentHolder.addChild(currentArtifact);
// no need to walk up the tree any longer
break;
} else {
parentHolder = new ArtifactHolder();
parentHolder.addChild(currentArtifact);
artifactHolderCache.put(parent, parentHolder);
}
if (root == null && parent.isInstanceOf(IRootArtifact.class)) {
root = (IRootArtifact) parent;
}
currentArtifactHolder = parentHolder;
currentArtifact = parent;
parent = parent.getParent();
}
}
// set the artifacts
// ArtifactHolder virtualRootHolder = new ArtifactHolder();
// virtualRootHolder.addChild(root);
// Content-Provider must be updated before new input is set!!!
_artifactStageContentProvider.setChildrenCache(artifactHolderCache);
_treeViewer.setInput(root);
}
// set empty list
else {
_artifactStageContentProvider.setChildrenCache(null);
_treeViewer.setInput(_effectiveSelectedArtifacts);
}
if (isAutoExpand()) {
_treeViewer.expandAll();
}
// redraw again
_treeViewer.getTree().setRedraw(true);
refreshEnablement();
registerArtifactModelModifiedListener();
}
/**
*
*/
private void unregisterArtifactModelModifiedListener() {
if (_effectiveSelectedArtifacts != null && _effectiveSelectedArtifacts.size() > 0) {
IBundleMakerArtifact artifact = _effectiveSelectedArtifacts.get(0);
artifact.getRoot().removeAnalysisModelModifiedListener(_modifiedListener);
}
}
private void registerArtifactModelModifiedListener() {
if (_effectiveSelectedArtifacts != null && _effectiveSelectedArtifacts.size() > 0) {
IBundleMakerArtifact artifact = _effectiveSelectedArtifacts.get(0);
artifact.getRoot().addAnalysisModelModifiedListener(_modifiedListener);
}
}
private void hookContextMenu() {
MenuManager menuMgr = new MenuManager("#PopupMenu");
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener() {
@Override
public void menuAboutToShow(IMenuManager manager) {
StageView.this.fillContextMenu(manager);
}
});
Menu menu = menuMgr.createContextMenu(_treeViewer.getControl());
_treeViewer.getControl().setMenu(menu);
getSite().registerContextMenu(menuMgr, _treeViewer);
}
private void contributeToActionBars() {
IActionBars bars = getViewSite().getActionBars();
fillLocalPullDown(bars.getMenuManager());
fillLocalToolBar(bars.getToolBarManager());
}
private void fillLocalPullDown(IMenuManager manager) {
_addModeActionGroup.fill(manager);
manager.add(new Separator());
manager.add(_removeArtifactsAction);
manager.add(_clearStageAction);
manager.add(new Separator());
manager.add(_autoExpandAction);
// manager.add(action1);
// manager.add(action2);
}
private void fillContextMenu(IMenuManager manager) {
refreshEnablement();
manager.add(_revealInProjectExplorerAction);
manager.add(_removeArtifactsAction);
// manager.add(action1);
// manager.add(action2);
// manager.add(new Separator());
// drillDownAdapter.addNavigationActions(manager);
// // Other plug-ins can contribute there actions here
// manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
}
private void fillLocalToolBar(IToolBarManager manager) {
manager.add(_removeArtifactsAction);
manager.add(_clearStageAction);
manager.add(new Separator());
_addModeActionGroup.fill(manager);
// manager.add(_pinStageAction);
// drillDownAdapter.addNavigationActions(manager);
}
private void makeActions() {
_autoExpandAction = new AutoExpandAction();
_clearStageAction = new ClearStageAction();
_revealInProjectExplorerAction = new RevealInProjectExplorerAction();
_removeArtifactsAction = new RemoveFromStageAction();
_addModeActionGroup = new AddModeActionGroup();
_treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
refreshEnablement();
}
});
refreshEnablement();
}
@Override
public void dispose() {
Selection.instance().getArtifactStage().removeArtifactStageChangeListener(_artifactStageChangeListener);
Selection.instance().getArtifactSelectionService().removeArtifactSelectionListener(_artifactSelectionListener);
super.dispose();
}
protected void refreshEnablement() {
IStructuredSelection selection = (IStructuredSelection) _treeViewer.getSelection();
boolean autoAddMode = Selection.instance().getArtifactStage().getAddMode().isAutoAddMode();
_removeArtifactsAction.setEnabled(!(autoAddMode || selection.isEmpty()));
_clearStageAction.setEnabled(!_effectiveSelectedArtifacts.isEmpty());
_revealInProjectExplorerAction.setEnabled(!selection.isEmpty());
}
/**
* @return the autoExpand
*/
public boolean isAutoExpand() {
return _autoExpand;
}
/**
* @param autoExpand
* the autoExpand to set
*/
public void setAutoExpand(boolean autoExpand) {
_autoExpand = autoExpand;
if (_autoExpand) {
_treeViewer.expandAll();
}
}
private void hookDoubleClickAction() {
_treeViewer.addDoubleClickListener(new IDoubleClickListener() {
@Override
public void doubleClick(DoubleClickEvent event) {
// doubleClickAction.run();
}
});
}
/**
* Passing the focus request to the viewer's control.
*/
@Override
public void setFocus() {
_treeViewer.getControl().setFocus();
}
protected void artifactStageConfigurationChanged() {
_addModeActionGroup.update();
refreshEnablement();
}
protected ArtifactStageAddMode getAddMode() {
return Selection.instance().getArtifactStage().getAddMode();
}
class AutoExpandAction extends Action {
public AutoExpandAction() {
super("Auto Expand", IAction.AS_CHECK_BOX);
setToolTipText("Auto expand selection tree");
// setImageDescriptor(TransformationHistoryImages.PIN_SELECTION.getImageDescriptor());
update();
}
@Override
public void run() {
setAutoExpand(isChecked());
}
public void update() {
setChecked(isAutoExpand());
}
}
class ClearStageAction extends Action {
ClearStageAction() {
super("Clear Stage", IAction.AS_PUSH_BUTTON);
setImageDescriptor(StageIcons.CLEAR_STAGE.getImageDescriptor());
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.action.Action#run()
*/
@Override
public void run() {
Selection.instance().getArtifactStage().setStagedArtifacts(null);
}
}
class RevealInProjectExplorerAction extends Action {
public RevealInProjectExplorerAction() {
super("Reveal in Project Explorer", IAction.AS_PUSH_BUTTON);
}
@Override
public void run() {
IStructuredSelection selection = (IStructuredSelection) _treeViewer.getSelection();
if (selection == null || selection.isEmpty()) {
return;
}
CommonNavigator projectExplorer = CommonNavigatorUtils
.findCommonNavigator(CommonNavigatorUtils.PROJECT_EXPLORER_VIEW_ID);
if (projectExplorer != null) {
projectExplorer.getCommonViewer().setSelection(selection, true);
}
}
}
class RemoveFromStageAction extends Action {
RemoveFromStageAction() {
super("Remove from Stage", IAction.AS_PUSH_BUTTON);
setImageDescriptor(StageIcons.REMOVE_FROM_STAGE.getImageDescriptor());
}
@Override
public void run() {
IStructuredSelection selection = (IStructuredSelection) _treeViewer.getSelection();
if (selection == null || selection.isEmpty()) {
return;
}
LinkedHashSet<IBundleMakerArtifact> artifacts = new LinkedHashSet<IBundleMakerArtifact>();
@SuppressWarnings("unchecked")
Iterator<IBundleMakerArtifact> iterator = selection.iterator();
while (iterator.hasNext()) {
IBundleMakerArtifact artifact = iterator.next();
artifacts.add(artifact);
}
Selection.instance().getArtifactStage().removeStagedArtifacts(artifacts);
}
}
class StageViewLabelProvider extends ArtifactTreeLabelProvider implements IColorProvider {
@Override
public Color getForeground(Object element) {
boolean stagedArtifact = false;
if (element instanceof IBundleMakerArtifact) {
IBundleMakerArtifact bundleMakerArtifact = (IBundleMakerArtifact) element;
if (bundleMakerArtifact instanceof IVirtualRoot) {
bundleMakerArtifact = bundleMakerArtifact.getRoot();
}
stagedArtifact = _effectiveSelectedArtifacts.contains(bundleMakerArtifact);
}
//
if (stagedArtifact) {
return Display.getCurrent().getSystemColor(SWT.COLOR_BLACK);
}
//
return Display.getCurrent().getSystemColor(SWT.COLOR_GRAY);
}
@Override
public Color getBackground(Object element) {
return null;
}
protected boolean isStaged(IBundleMakerArtifact bundleMakerArtifact) {
return _effectiveSelectedArtifacts.contains(bundleMakerArtifact);
}
@Override
protected Image getImageForRootArtifact(IBundleMakerArtifact rootArtifact) {
if (!isStaged(rootArtifact)) {
return ArtifactImages.ROOT_ARTIFACT_DISABLED_ICON.getImage();
}
return super.getImageForRootArtifact(rootArtifact);
}
@Override
protected Image getImageForGroupArtifact(IBundleMakerArtifact groupArtifact) {
if (!isStaged(groupArtifact)) {
return ArtifactImages.GROUP_ARTIFACT_DISABLED_ICON.getImage();
}
return super.getImageForGroupArtifact(groupArtifact);
}
@Override
protected Image getImageForModuleArtifact(IBundleMakerArtifact moduleArtifact) {
if (!isStaged(moduleArtifact)) {
return ArtifactImages.MODULE_ARTIFACT_DISABLED_ICON.getImage();
}
return super.getImageForModuleArtifact(moduleArtifact);
}
@Override
protected Image getImageForPackageArtifact(IBundleMakerArtifact packageArtifact) {
if (!isStaged(packageArtifact)) {
return ArtifactImages.PACKAGE_ARTIFACT_DISABLED_ICON.getImage();
}
return super.getImageForPackageArtifact(packageArtifact);
}
@Override
protected Image getImageForResourceArtifact(IResourceArtifact resourceArtifact) {
if (!isStaged(resourceArtifact)) {
return ArtifactImages.RESOURCE_ARTIFACT_DISABLED_ICON.getImage();
}
return super.getImageForResourceArtifact(resourceArtifact);
}
}
}