/*******************************************************************************
* Copyright (c) 2004, 2010 BREDEX GmbH.
* 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:
* BREDEX GmbH - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.jubula.client.ui.rcp.views;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jubula.client.core.businessprocess.db.NodeBP;
import org.eclipse.jubula.client.core.events.DataEventDispatcher;
import org.eclipse.jubula.client.core.events.DataEventDispatcher.DataState;
import org.eclipse.jubula.client.core.events.DataEventDispatcher.IProblemPropagationListener;
import org.eclipse.jubula.client.core.events.DataEventDispatcher.UpdateState;
import org.eclipse.jubula.client.core.model.IAUTMainPO;
import org.eclipse.jubula.client.core.model.ICategoryPO;
import org.eclipse.jubula.client.core.model.IExecTestCasePO;
import org.eclipse.jubula.client.core.model.INodePO;
import org.eclipse.jubula.client.core.model.IPersistentObject;
import org.eclipse.jubula.client.core.model.IProjectPO;
import org.eclipse.jubula.client.core.model.IReusedProjectPO;
import org.eclipse.jubula.client.core.model.ISpecObjContPO;
import org.eclipse.jubula.client.core.model.ISpecTestCasePO;
import org.eclipse.jubula.client.core.model.ITestSuitePO;
import org.eclipse.jubula.client.core.persistence.GeneralStorage;
import org.eclipse.jubula.client.ui.constants.ContextHelpIds;
import org.eclipse.jubula.client.ui.provider.DecoratingCellLabelProvider;
import org.eclipse.jubula.client.ui.rcp.Plugin;
import org.eclipse.jubula.client.ui.rcp.actions.CutTreeItemActionTCBrowser;
import org.eclipse.jubula.client.ui.rcp.actions.PasteTreeItemActionTCBrowser;
import org.eclipse.jubula.client.ui.rcp.constants.RCPCommandIDs;
import org.eclipse.jubula.client.ui.rcp.controllers.MultipleTCBTracker;
import org.eclipse.jubula.client.ui.rcp.controllers.dnd.LocalSelectionClipboardTransfer;
import org.eclipse.jubula.client.ui.rcp.controllers.dnd.LocalSelectionTransfer;
import org.eclipse.jubula.client.ui.rcp.controllers.dnd.TCBrowserDndSupport;
import org.eclipse.jubula.client.ui.rcp.controllers.dnd.TestSpecDropTargetListener;
import org.eclipse.jubula.client.ui.rcp.controllers.dnd.TreeViewerContainerDragSourceListener;
import org.eclipse.jubula.client.ui.rcp.provider.contentprovider.TestCaseBrowserContentProvider;
import org.eclipse.jubula.client.ui.rcp.provider.labelprovider.TestCaseBrowserLabelProvider;
import org.eclipse.jubula.client.ui.utils.CommandHelper;
import org.eclipse.jubula.client.ui.views.IJBPart;
import org.eclipse.jubula.client.ui.views.ITreeViewerContainer;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.menus.CommandContributionItem;
/**
* @author BREDEX GmbH
* @created 05.07.2004
*/
public class TestCaseBrowser extends AbstractJBTreeView
implements ITreeViewerContainer, IJBPart, IProblemPropagationListener {
/** New-menu ID */
public static final String NEW_ID = PlatformUI.PLUGIN_ID + ".NewSubMenu"; //$NON-NLS-1$
/** Identifies the workbench plug-in */
public static final String OPEN_WITH_ID = PlatformUI.PLUGIN_ID + ".OpenWithSubMenu"; //$NON-NLS-1$
/** Add-Submenu ID */
public static final String ADD_ID = PlatformUI.PLUGIN_ID + ".AddSubMenu"; //$NON-NLS-1$
/** The action to cut TreeItems */
private CutTreeItemActionTCBrowser m_cutTreeItemAction;
/** The action to paste TreeItems */
private PasteTreeItemActionTCBrowser m_pasteTreeItemAction;
/** The action listener of the treeViewer */
private CutAndPasteEnablementListener m_actionListener;
/** <code>m_doubleClickListener</code> */
private final DoubleClickListener m_doubleClickListener =
new DoubleClickListener();
/**
* {@inheritDoc}
*/
public void createPartControl(Composite parent) {
m_cutTreeItemAction = new CutTreeItemActionTCBrowser();
m_pasteTreeItemAction = new PasteTreeItemActionTCBrowser();
super.createPartControl(parent);
getViewSite().getActionBars().getToolBarManager()
.add(CommandHelper.createContributionItem(
RCPCommandIDs.SET_MAIN_VIEW_INSTANCE, null, null,
CommandContributionItem.STYLE_PUSH));
getViewSite().getActionBars().getToolBarManager()
.add(CommandHelper.createContributionItem(
RCPCommandIDs.COLLAPSE_ALL, null, null,
CommandContributionItem.STYLE_PUSH));
ColumnViewerToolTipSupport.enableFor(getTreeViewer());
getTreeViewer().setContentProvider(
new TestCaseBrowserContentProvider());
DecoratingCellLabelProvider lp = new DecoratingCellLabelProvider(
new TestCaseBrowserLabelProvider(), Plugin.getDefault()
.getWorkbench().getDecoratorManager()
.getLabelDecorator());
getTreeViewer().setLabelProvider(lp);
int ops = DND.DROP_MOVE;
Transfer[] transfers = new Transfer[] {LocalSelectionTransfer
.getInstance()};
getTreeViewer().addDragSupport(ops, transfers,
new TreeViewerContainerDragSourceListener(getTreeViewer()));
getTreeViewer().addDropSupport(ops, transfers,
new TestSpecDropTargetListener(this));
registerContextMenu();
Plugin.getHelpSystem().setHelp(getTreeViewer().getControl(),
ContextHelpIds.TEST_SPEC_VIEW);
configureActionBars();
if (GeneralStorage.getInstance().getProject() != null) {
handleProjectLoaded();
}
// add this TCB to the tracker
MultipleTCBTracker.getInstance().addTCB(this);
getSite().setSelectionProvider(getTreeViewer());
DataEventDispatcher.getInstance().addProblemPropagationListener(this);
}
/**
* Registers global action handlers and listeners.
*/
private void configureActionBars() {
getTreeFilterText().addFocusListener(new FocusListener() {
/** the default cut action */
private IAction m_defaultCutAction = getViewSite()
.getActionBars().getGlobalActionHandler(
ActionFactory.CUT.getId());
/** the default paste action */
private IAction m_defaultPasteAction = getViewSite()
.getActionBars().getGlobalActionHandler(
ActionFactory.PASTE.getId());
public void focusGained(FocusEvent e) {
getViewSite().getActionBars().setGlobalActionHandler(
ActionFactory.CUT.getId(), m_defaultCutAction);
getViewSite().getActionBars().setGlobalActionHandler(
ActionFactory.PASTE.getId(), m_defaultPasteAction);
getViewSite().getActionBars().updateActionBars();
}
public void focusLost(FocusEvent e) {
getViewSite().getActionBars().setGlobalActionHandler(
ActionFactory.CUT.getId(), m_cutTreeItemAction);
getViewSite().getActionBars().setGlobalActionHandler(
ActionFactory.PASTE.getId(), m_pasteTreeItemAction);
getViewSite().getActionBars().updateActionBars();
}
});
getViewSite().getActionBars().setGlobalActionHandler(
ActionFactory.CUT.getId(), m_cutTreeItemAction);
getViewSite().getActionBars().setGlobalActionHandler(
ActionFactory.PASTE.getId(), m_pasteTreeItemAction);
getViewSite().getWorkbenchWindow().getSelectionService()
.addSelectionListener(getActionListener());
getViewSite().getActionBars().updateActionBars();
}
/** {@inheritDoc} */
protected void createContextMenu(IMenuManager mgr) {
mgr.add(new GroupMarker("defaultTestCaseBrowserMarker")); //$NON-NLS-1$
}
/**
* Adds DoubleClick-Support to Treeview. Adds SelectionChanged-Support to
* TreeView.
*/
protected void addTreeListener() {
getTreeViewer().addDoubleClickListener(m_doubleClickListener);
setActionListener(new CutAndPasteEnablementListener());
}
/**
* Sets the focus and shows the status line.
*/
public void setFocus() {
getTreeViewer().getControl().setFocus();
Plugin.showStatusLine(this);
}
/**
* @return the actual selection
*/
IStructuredSelection getActualSelection() {
ISelection selection =
getViewSite().getSelectionProvider().getSelection();
return selection instanceof IStructuredSelection
? (IStructuredSelection)selection : StructuredSelection.EMPTY;
}
/** {@inheritDoc} */
public void dispose() {
try {
DataEventDispatcher ded = DataEventDispatcher.getInstance();
ded.removeDataChangedListener(this);
ded.removeProblemPropagationListener(this);
getViewSite().getWorkbenchWindow().getSelectionService()
.removeSelectionListener(getActionListener());
getTreeViewer().removeDoubleClickListener(m_doubleClickListener);
} finally {
MultipleTCBTracker.getInstance().removeTCB(this);
super.dispose();
}
}
/**
* {@inheritDoc}
*/
protected void rebuildTree() {
IProjectPO activeProject = GeneralStorage.getInstance().getProject();
if (activeProject != null) {
getTreeViewer().setInput(
new ISpecObjContPO[] {activeProject.getSpecObjCont()});
getTreeViewer().expandToLevel(DEFAULT_EXPANSION);
} else {
getTreeViewer().setInput(null);
}
}
/**
* @author BREDEX GmbH
* @created Jan 22, 2007
*/
private final class DoubleClickListener implements IDoubleClickListener {
/** {@inheritDoc} */
public void doubleClick(DoubleClickEvent event) {
IStructuredSelection selection = getActualSelection();
Object firstElement = selection.getFirstElement();
String commandId;
if (firstElement instanceof ISpecObjContPO
|| firstElement instanceof ICategoryPO) {
commandId = RCPCommandIDs.NEW_TESTCASE;
} else if (firstElement instanceof IExecTestCasePO) {
commandId = RCPCommandIDs.OPEN_SPECIFICATION;
} else {
commandId = RCPCommandIDs.OPEN_TESTCASE_EDITOR;
}
CommandHelper.executeCommand(commandId, getSite());
}
}
/**
* Listener to en-/disable actions pertaining to this view.
* @author BREDEX GmbH
* @created 02.03.2006
*/
public final class CutAndPasteEnablementListener
implements ISelectionListener {
/**
* en-/disable cut-action
* @param selList actual selection list
*/
private void enableCutAction(INodePO[] selList) {
m_cutTreeItemAction.setEnabled(false);
for (INodePO guiNode : selList) {
if (!(guiNode instanceof ICategoryPO
|| guiNode instanceof ISpecTestCasePO)
|| !NodeBP.isEditable(guiNode)) {
m_cutTreeItemAction.setEnabled(false);
return;
}
}
m_cutTreeItemAction.setEnabled(true);
}
/**
* en-/disable cut-action
* @param selList actual selection list
*/
private void enablePasteAction(INodePO[] selList) {
m_pasteTreeItemAction.setEnabled(false);
Object cbContents = getClipboard().getContents(
LocalSelectionClipboardTransfer.getInstance());
for (INodePO node : selList) {
if (!(node instanceof ICategoryPO
|| node instanceof ISpecTestCasePO
|| node instanceof IProjectPO)
|| !NodeBP.isEditable(node)
|| !(cbContents instanceof IStructuredSelection)
|| !TCBrowserDndSupport.canMove(
(IStructuredSelection)cbContents, node)) {
m_pasteTreeItemAction.setEnabled(false);
return;
}
}
m_pasteTreeItemAction.setEnabled(true);
}
/**
* {@inheritDoc}
*/
public void selectionChanged(IWorkbenchPart part,
ISelection selection) {
if (!(selection instanceof IStructuredSelection)) {
// e.g. in Jubula plugin-version you can open an java editor,
// that reacts on org.eclipse.jface.text.TextSelection, which
// is not a StructuredSelection
return;
}
boolean isThisPart = (part == TestCaseBrowser.this);
final boolean isNullProject = (GeneralStorage.getInstance()
.getProject() == null);
if (isNullProject || (selection == null || selection.isEmpty())) {
m_cutTreeItemAction.setEnabled(false);
m_pasteTreeItemAction.setEnabled(false);
return;
}
if (isThisPart) {
IStructuredSelection sel = (IStructuredSelection)selection;
Object[] selectedElements = sel.toArray();
INodePO[] selectedNodes = new INodePO[selectedElements.length];
for (int i = 0; i < selectedElements.length; i++) {
if (selectedElements[i] instanceof INodePO) {
selectedNodes[i] = (INodePO)selectedElements[i];
} else {
m_cutTreeItemAction.setEnabled(false);
m_pasteTreeItemAction.setEnabled(false);
return;
}
}
enableCutAction(selectedNodes);
enablePasteAction(selectedNodes);
}
}
}
/** {@inheritDoc} */
public void handleDataChanged(final IPersistentObject po,
final DataState dataState, final UpdateState updateState) {
Plugin.getDisplay().syncExec(new Runnable() {
public void run() {
// changes on the aut do not affect this view
if ((po instanceof IAUTMainPO)
|| (po instanceof ITestSuitePO)) {
return;
}
if (updateState == UpdateState.onlyInEditor) {
return;
}
if (po instanceof IReusedProjectPO) {
// For right now, refresh the entire tree
handleProjectLoaded();
return;
}
switch (dataState) {
case Added:
handleDataAdded(po, new NullProgressMonitor());
break;
case Deleted:
handleDataDeleted(po);
break;
case Renamed:
handleDataRenamed(po);
break;
case StructureModified:
handleDataStructureModified(po);
break;
default:
break;
}
}
});
}
/**
* @param po The persistent object for which the structure has changed
*/
private void handleDataStructureModified(final IPersistentObject po) {
if (po instanceof INodePO) {
final TreeViewer tv = getTreeViewer();
try {
tv.getTree().getParent().setRedraw(false);
// retrieve tree state
Object[] expandedElements = tv.getExpandedElements();
ISelection selection = tv.getSelection();
// update elements
if (po instanceof IProjectPO) {
rebuildTree();
}
// refresh tree viewer
tv.refresh();
// restore tree state
tv.setExpandedElements(expandedElements);
tv.setSelection(selection);
} finally {
tv.getTree().getParent().setRedraw(true);
}
}
}
/**
* @param po The persistent object that was renamed
*/
private void handleDataRenamed(final IPersistentObject po) {
if ((po instanceof ISpecTestCasePO || po instanceof ICategoryPO
|| po instanceof IExecTestCasePO)) {
getTreeViewer().refresh(true);
}
}
/**
* @param po The persistent object that was deleted
*/
private void handleDataDeleted(final IPersistentObject po) {
if (po instanceof ISpecTestCasePO
|| po instanceof ICategoryPO) {
if (getTreeViewer() != null) {
Plugin.getDisplay().syncExec(new Runnable() {
public void run() {
getTreeViewer().refresh();
}
});
}
} else if (po instanceof IProjectPO) {
Plugin.getDisplay().syncExec(new Runnable() {
public void run() {
getTreeViewer().setInput(null);
getTreeViewer().refresh();
}
});
}
}
/**
* @param po The persistent object that was added
* @param monitor The progress monitor for this potentially long-running
* operation.
*/
private void handleDataAdded(final IPersistentObject po,
IProgressMonitor monitor) {
if (po instanceof ISpecTestCasePO
|| po instanceof ICategoryPO) {
getTreeViewer().refresh();
getTreeViewer().expandToLevel(getTreeViewer().getAutoExpandLevel());
getTreeViewer().setSelection(new StructuredSelection(po), true);
} else if (po instanceof IProjectPO) {
handleProjectLoaded();
}
}
/**
* @param title
* the title
*/
public void setViewTitle(String title) {
super.setPartName(title);
}
/**
* @return the actionListener
*/
public CutAndPasteEnablementListener getActionListener() {
return m_actionListener;
}
/**
* @param actionListener
* the actionListener to set
*/
private void setActionListener(
CutAndPasteEnablementListener actionListener) {
m_actionListener = actionListener;
}
@Override
public void problemPropagationFinished() {
final IWorkbench workbench = PlatformUI.getWorkbench();
Plugin.getDisplay().syncExec(new Runnable() {
public void run() {
getTreeViewer().refresh();
}
});
}
}