/******************************************************************************* * Copyright (c) 2012, 2015 Wind River Systems, Inc. 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: * Wind River Systems - initial API and implementation *******************************************************************************/ package org.eclipse.tcf.te.launch.ui.viewer.dnd; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import org.eclipse.cdt.utils.elf.Elf.Attribute; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Platform; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationType; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.core.ILaunchMode; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.debug.ui.ILaunchGroup; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.util.LocalSelectionTransfer; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.TransferData; import org.eclipse.tcf.te.core.cdt.elf.ElfUtils; import org.eclipse.tcf.te.launch.core.bindings.LaunchConfigTypeBindingsManager; import org.eclipse.tcf.te.launch.core.lm.LaunchConfigHelper; import org.eclipse.tcf.te.launch.core.lm.LaunchManager; import org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchManagerDelegate; import org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchSpecification; import org.eclipse.tcf.te.launch.core.persistence.launchcontext.LaunchContextsPersistenceDelegate; import org.eclipse.tcf.te.launch.core.selection.LaunchSelection; import org.eclipse.tcf.te.launch.core.selection.ProjectSelectionContext; import org.eclipse.tcf.te.launch.core.selection.RemoteSelectionContext; import org.eclipse.tcf.te.launch.core.selection.interfaces.ILaunchSelection; import org.eclipse.tcf.te.launch.core.selection.interfaces.ISelectionContext; import org.eclipse.tcf.te.launch.ui.activator.UIPlugin; import org.eclipse.tcf.te.launch.ui.model.LaunchModel; import org.eclipse.tcf.te.launch.ui.model.LaunchNode; import org.eclipse.tcf.te.launch.ui.nls.Messages; import org.eclipse.tcf.te.runtime.model.interfaces.IModelNode; import org.eclipse.tcf.te.ui.jface.dialogs.OptionalMessageDialog; import org.eclipse.tcf.te.ui.views.Managers; import org.eclipse.tcf.te.ui.views.ViewsUtil; import org.eclipse.tcf.te.ui.views.interfaces.ICategory; import org.eclipse.tcf.te.ui.views.interfaces.IRoot; import org.eclipse.tcf.te.ui.views.interfaces.IUIConstants; import org.eclipse.ui.dialogs.ListDialog; import org.eclipse.ui.navigator.CommonDropAdapter; /** * Common DND operation implementations. */ public class CommonDnD { /** * If the current selection is draggable. * * @param selection The currently selected nodes. * @return true if it is draggable. */ public boolean isDraggable(IStructuredSelection selection) { if (selection == null || selection.isEmpty()) { return false; } Object[] objects = selection.toArray(); for (Object object : objects) { if (!isDraggableObject(translateObject(object))) { return false; } } return true; } /** * Translate the object. * @param object * @return */ private Object translateObject(Object object) { if (object == null || object instanceof LaunchNode || object instanceof IModelNode || object instanceof ICategory) { return object; } IResource resource = (IResource)Platform.getAdapterManager().loadAdapter(object, IResource.class.getName()); if (resource != null) { IPath location = resource.getLocation(); if (location != null) { try { int elfType = ElfUtils.getELFType(location.toFile()); if (elfType == Attribute.ELF_TYPE_EXE || elfType == Attribute.ELF_TYPE_OBJ) { return resource; } } catch (Exception e) { } } } return null; } /** * If the specified object is a draggable element. * * @param object The object to be dragged. * @return true if it is draggable. */ private boolean isDraggableObject(Object object) { return (object instanceof LaunchNode && ((LaunchNode)object).getLaunchConfiguration() != null) || (!(object instanceof LaunchNode) && object instanceof IModelNode) || object instanceof IResource; } /** * Validate dropping when the elements being dragged are local selection. * * @param dropAdapter The common drop adapter. * @param target The target object. * @param operation The DnD operation. * @param transferType The transfered data type. * * @return true if it is valid for dropping. */ public boolean isValidDnD(CommonDropAdapter dropAdapter, Object target, int operation, TransferData transferType) { boolean valid = false; int overrideOperation = -1; IStructuredSelection selection = null; if (LocalSelectionTransfer.getTransfer().isSupportedType(transferType)) { LocalSelectionTransfer transfer = LocalSelectionTransfer.getTransfer(); selection = (IStructuredSelection) transfer.getSelection(); } if (selection == null) { return false; } boolean allow = true; target = translateObject(target); Iterator<?> iterator = selection.iterator(); boolean isCopy = (operation & DND.DROP_COPY) != 0; while (iterator.hasNext() && allow) { Object from = translateObject(iterator.next()); if (from instanceof LaunchNode) { LaunchNode fromNode = (LaunchNode)from; if (target instanceof LaunchNode) { // LaunchNode toNode = (LaunchNode)target; allow = false; } else if (target instanceof IModelNode) { IModelNode toContext = (IModelNode)target; allow &= internalValidate(fromNode, null, toContext, true, isCopy); } else if (target instanceof IResource) { IResource toResource = (IResource)target; allow &= internalValidate(fromNode, toResource, null, true, isCopy); } else if (target instanceof ICategory) { ICategory toCategory = (ICategory)target; overrideOperation = DND.DROP_LINK; allow &= fromNode.getLaunchConfiguration() != null && IUIConstants.ID_CAT_FAVORITES.equals(toCategory.getId()) && !Managers.getCategoryManager().belongsTo(toCategory.getId(), LaunchModel.getCategoryId(fromNode.getLaunchConfiguration())); } else if (target instanceof IRoot) { allow &= fromNode.getModel().getModelRoot() instanceof ICategory && fromNode.getLaunchConfiguration() != null && Managers.getCategoryManager().belongsTo(((ICategory)fromNode.getModel().getModelRoot()).getId(), LaunchModel.getCategoryId(fromNode.getLaunchConfiguration())); } else { allow = false; } } else if (from instanceof IModelNode) { IModelNode fromContext = (IModelNode)from; if (target instanceof LaunchNode) { LaunchNode toNode = (LaunchNode)target; overrideOperation = DND.DROP_MOVE; allow &= internalValidate(toNode, null, fromContext, true, false); } else { allow = false; } } else if (from instanceof IResource) { IResource fromResource = (IResource)from; if (target instanceof LaunchNode) { LaunchNode toNode = (LaunchNode)target; allow &= internalValidate(toNode, fromResource, null, !isCopy, false); } else if (target instanceof IModelNode) { IModelNode toContext = (IModelNode)target; ILaunchSelection launchSel = new LaunchSelection(null, new ISelectionContext[]{ new RemoteSelectionContext(toContext, new Object[]{toContext}, true), new ProjectSelectionContext(fromResource.getProject(), new Object[]{fromResource.getLocation()}, true) }); String[] typeIds = LaunchConfigTypeBindingsManager.getInstance().getValidLaunchConfigTypes(launchSel); allow &= typeIds != null && typeIds.length > 0; } else { allow = false; } } else { allow = false; } } valid = allow; if (dropAdapter != null && valid) { if (overrideOperation > -1) { dropAdapter.overrideOperation(overrideOperation); } } return valid; } private boolean internalValidate(LaunchNode node, IResource resource, IModelNode context, boolean replaceData, boolean duplicateConfig) { if (node.getLaunchConfiguration() == null) { return false; } if (resource != null) { if (!LaunchConfigTypeBindingsManager.getInstance().isValidLaunchConfigType( node.getLaunchConfigurationType().getIdentifier(), new LaunchSelection(null, new ProjectSelectionContext(resource.getProject(), new Object[]{resource.getLocation()}, true)))) { return false; } } if (context != null) { if (!LaunchConfigTypeBindingsManager.getInstance().isValidLaunchConfigType( node.getLaunchConfigurationType().getIdentifier(), new LaunchSelection(null, new RemoteSelectionContext(context, true)))) { return false; } IModelNode[] oldContexts = LaunchContextsPersistenceDelegate.getLaunchContexts(node.getLaunchConfiguration()); if (oldContexts != null && Arrays.asList(oldContexts).contains(context) && !duplicateConfig) { return false; } } return true; } /** * Perform the drop operation over dragged selection. * * @param dropAdapter The common drop adapter. * @param target The target Object to be moved to. * @param operation The current DnD operation. * @param selection The local selection being dropped. * @return true if the dropping is successful. */ public boolean doDnD(CommonDropAdapter dropAdapter, Object target, int operation, IStructuredSelection selection) { boolean success = true; target = translateObject(target); Iterator<?> iterator = selection.iterator(); boolean isCopy = (operation & DND.DROP_COPY) != 0; while (iterator.hasNext()) { Object from = translateObject(iterator.next()); if (from instanceof LaunchNode) { LaunchNode fromNode = (LaunchNode)from; if (target instanceof LaunchNode) { // LaunchNode toNode = (LaunchNode)target; success = false; } else if (target instanceof IModelNode) { IModelNode toContext = (IModelNode)target; success &= internalDrop(fromNode, null, toContext, true, isCopy); } else if (target instanceof IResource) { IResource toResource = (IResource)target; success &= internalDrop(fromNode, toResource, null, true, isCopy); } else if (target instanceof ICategory) { ICategory toCategory = (ICategory)target; success &= Managers.getCategoryManager().add(toCategory.getId(), LaunchModel.getCategoryId(fromNode.getLaunchConfiguration())); } else if (target instanceof IRoot) { success &= Managers.getCategoryManager().remove(((ICategory)fromNode.getModel().getModelRoot()).getId(), LaunchModel.getCategoryId(fromNode.getLaunchConfiguration())); } else { success = false; } } else if (from instanceof IModelNode) { IModelNode fromContext = (IModelNode)from; if (target instanceof LaunchNode) { LaunchNode toNode = (LaunchNode)target; success &= internalDrop(toNode, null, fromContext, true, false); } else { success = false; } } else if (from instanceof IResource) { IResource fromResource = (IResource)from; if (target instanceof LaunchNode) { LaunchNode toNode = (LaunchNode)target; success &= internalDrop(toNode, fromResource, null, !isCopy, false); } else if (target instanceof IModelNode) { IModelNode toContext = (IModelNode)target; ILaunchSelection launchSel = new LaunchSelection(null, new ISelectionContext[]{ new RemoteSelectionContext(toContext, new Object[]{toContext}, true), new ProjectSelectionContext(fromResource.getProject(), new Object[]{fromResource.getLocation()}, true) }); String[] typeIds = LaunchConfigTypeBindingsManager.getInstance().getValidLaunchConfigTypes(launchSel); if (typeIds != null && typeIds.length > 0) { String typeId = null; if (typeIds.length == 1) { typeId = typeIds[0]; } else { typeId = askForLaunchType(typeIds); } if (typeId != null) { ILaunchConfigurationType type = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurationType(typeId); String[] modes = LaunchConfigHelper.getLaunchConfigTypeModes(type, false); if (modes != null && modes.length > 0) { String mode = null; if (modes.length == 1) { mode = modes[0]; } else { mode = askForLaunchMode(type, modes); } if (mode != null) { success &= openLaunchConfigDialog(type, mode, new LaunchSelection(mode, launchSel.getSelectedContexts())); } } } } } else { success = false; } } else { success = false; } } // Fire a refresh of the view ViewsUtil.refresh(IUIConstants.ID_EXPLORER); return success; } private String askForLaunchType(String[] typeIds) { List<ILaunchConfigurationType> types = new ArrayList<ILaunchConfigurationType>(); for (String typeId : typeIds) { types.add(DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurationType(typeId)); } ListDialog dialog = new ListDialog(UIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell()); dialog.setTitle(Messages.CommonDnD_launchType_dialog_title); dialog.setMessage(Messages.CommonDnD_launchType_dialog_message); dialog.setInput(types.toArray()); dialog.setContentProvider(new ArrayContentProvider()); dialog.setLabelProvider(new LabelProvider() { @Override public String getText(Object element) { return ((ILaunchConfigurationType)element).getName(); } }); dialog.setInitialSelections(new Object[]{types.get(0)}); if (dialog.open() == Window.OK) { return ((ILaunchConfigurationType)dialog.getResult()[0]).getIdentifier(); } return null; } private String askForLaunchMode(ILaunchConfigurationType type, String[] modes) { List<String> modeLabels = new ArrayList<String>(); int defaultIndex = 0; for (String mode : modes) { ILaunchMode launchMode = DebugPlugin.getDefault().getLaunchManager().getLaunchMode(mode); modeLabels.add(launchMode.getLabel()); if (mode.equals(ILaunchManager.DEBUG_MODE)) { defaultIndex = modeLabels.size()-1; } } if (modeLabels.size() > 0) { modeLabels.add(IDialogConstants.CANCEL_LABEL); OptionalMessageDialog dialog = new OptionalMessageDialog( UIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell(), Messages.CommonDnD_launchMode_dialog_title, null, NLS.bind(Messages.CommonDnD_launchMode_dialog_message, type.getName()), MessageDialog.QUESTION, modeLabels.toArray(new String[modeLabels.size()]), defaultIndex, null, null); int result = dialog.open(); if (result >= IDialogConstants.INTERNAL_ID) { return modes[result - IDialogConstants.INTERNAL_ID]; } } return null; } private boolean openLaunchConfigDialog(ILaunchConfigurationType type, String mode, ILaunchSelection launchSel) { try { ILaunchManagerDelegate delegate = LaunchManager.getInstance().getLaunchManagerDelegate(type, mode); if (delegate != null) { // create an empty launch configuration specification to initialize all attributes with their default defaults. ILaunchSpecification launchSpec = delegate.getLaunchSpecification(type.getIdentifier(), launchSel); // initialize the new launch config. // ignore validation result of launch spec - init as much attributes as possible if (launchSpec != null) { ILaunchConfiguration[] launchConfigs = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurations(type); launchConfigs = delegate.getMatchingLaunchConfigurations(launchSpec, launchConfigs); ILaunchConfiguration config = launchConfigs != null && launchConfigs.length > 0 ? launchConfigs[0] : null; config = LaunchManager.getInstance().createOrUpdateLaunchConfiguration(config, launchSpec); ILaunchGroup launchGroup = DebugUITools.getLaunchGroup(config, mode); DebugUITools.openLaunchConfigurationDialogOnGroup(UIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell(), new StructuredSelection(config), launchGroup.getIdentifier()); return true; } } } catch (Exception e) { return false; } return false; } private boolean internalDrop(LaunchNode node, IResource resource, IModelNode context, boolean replaceData, boolean duplicateConfig) { try { ILaunchManagerDelegate delegate = LaunchManager.getInstance().getLaunchManagerDelegate(node.getLaunchConfigurationType(), ""); //$NON-NLS-1$ ILaunchConfigurationWorkingCopy wc = node.getLaunchConfiguration().getWorkingCopy(); if (resource != null) { delegate.updateLaunchConfig(wc, new ProjectSelectionContext(resource.getProject(), new Object[]{resource.getLocation()}, true), replaceData); } if (context != null) { delegate.updateLaunchConfig(wc, new RemoteSelectionContext(context, new Object[]{context}, true), replaceData); } if (duplicateConfig) { wc = wc.copy(LaunchConfigHelper.getUniqueLaunchConfigName(delegate.getDefaultLaunchName(wc))); } else { String newName = LaunchConfigHelper.getUniqueLaunchConfigName(delegate.getDefaultLaunchName(wc)).replaceAll("\\([0-9]+\\)$", "").trim(); //$NON-NLS-1$ //$NON-NLS-2$ String oldName = wc.getName().replaceAll("\\([0-9]+\\)$", "").trim(); //$NON-NLS-1$ //$NON-NLS-2$; if (!newName.equals(oldName)) { wc.rename(LaunchConfigHelper.getUniqueLaunchConfigName(newName)); } } wc.doSave(); return true; } catch (Exception e) { return false; } } }