Bug 522593 - [9] Allow drag and drop of entries between modulepath and
classpath nodes

Change-Id: Id666c8708210037174546d2f5d400d52a68a5aa8
Signed-off-by: Vikas Chandra <Vikas.Chandra@in.ibm.com>
Bug 522593 - [9] Allow drag and drop of entries between modulepath and
classpath nodes

Change-Id: Ida1ba66d93f8398b6de36f646970b90d24a16ae4
Signed-off-by: Vikas Chandra <Vikas.Chandra@in.ibm.com>
Fix for container CPE -Bug 522593 - [9] Allow drag and drop of entries
between modulepath and classpath nodes 

Change-Id: I881f2fc0317b0119d502db722b417d3769f67022
Signed-off-by: Vikas Chandra <Vikas.Chandra@in.ibm.com>
Review comments of Bug 522593 - [9] Allow drag and drop of entries
between modulepath and classpath nodes

Change-Id: Ibc2c6c6b8f55bf82dc886a8365dbbb87ad1e9841
Signed-off-by: Vikas Chandra <Vikas.Chandra@in.ibm.com>
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/CPListElement.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/CPListElement.java
index fb98e8e..505f67f 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/CPListElement.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/CPListElement.java
@@ -1023,6 +1023,17 @@
 	}
 	
 	public void updateExtraAttributeOfClasspathEntry() {
+		if (fChildren != null) {
+			for (int i= 0; i < fChildren.size(); i++) {
+				Object curr= fChildren.get(i);
+				if (curr instanceof CPListElementAttribute) {
+					CPListElementAttribute elem= (CPListElementAttribute) curr;
+					String key= elem.getKey();
+					if (MODULE.equals(key))
+						return;
+				}
+			}
+		}
 		this.createAttributeElement(MODULE, new ModuleEncapsulationDetail[0], true);
 		//refresh the cached classpath entry
 		fCachedEntry= null;
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/LibrariesWorkbookPage.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/LibrariesWorkbookPage.java
index 062cd96..b00f587 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/LibrariesWorkbookPage.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/LibrariesWorkbookPage.java
@@ -21,10 +21,20 @@
 import java.util.Map;
 
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DragSourceEvent;
+import org.eclipse.swt.dnd.DragSourceListener;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.dnd.FileTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.dnd.TransferData;
 import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Item;
 import org.eclipse.swt.widgets.Shell;
 
 import org.eclipse.core.runtime.CoreException;
@@ -42,12 +52,15 @@
 import org.eclipse.jface.dialogs.IDialogConstants;
 import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.jface.layout.PixelConverter;
+import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.ViewerDropAdapter;
 import org.eclipse.jface.window.Window;
 import org.eclipse.jface.wizard.WizardDialog;
 
 import org.eclipse.ui.IImportWizard;
 import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.part.ResourceTransfer;
 import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
 
 import org.eclipse.jdt.core.IAccessRule;
@@ -105,6 +118,9 @@
 
 	private final int IDX_REPLACE= 10;
 
+	private boolean dragDropEnabled;
+	private Object draggedItemsLibrary;
+	
 	public LibrariesWorkbookPage(CheckedListDialogField<CPListElement> classPathList, IWorkbenchPreferenceContainer pageContainer) {
 		fClassPathList= classPathList;
 		fPageContainer= pageContainer;
@@ -200,8 +216,164 @@
 		fLibrariesList.enableButton(IDX_ADDJAR, false);
 		fLibrariesList.enableButton(IDX_ADDLIB, false);
 		fLibrariesList.enableButton(IDX_ADDVAR, false);
+		
+		if (!dragDropEnabled) {
+			enableDragDropSupport();
+		}
+		
 	}
 	
+	private void enableDragDropSupport() {
+		dragDropEnabled= true;
+		int ops= DND.DROP_MOVE | DND.DROP_DEFAULT;
+		Transfer[] transfers= new Transfer[] { ResourceTransfer.getInstance(), FileTransfer.getInstance() };
+		fLibrariesList.getTreeViewer().addDragSupport(DND.DROP_MOVE | DND.DROP_COPY, transfers, new DragSourceListener() {
+			@Override
+			public void dragStart(DragSourceEvent event) {
+				IStructuredSelection ssel= (IStructuredSelection) fLibrariesList.getTreeViewer().getSelection();
+				if (ssel == null || ssel.isEmpty()) {
+					event.doit= false;
+				}
+				if (ssel != null) {
+					Object[] ele= ssel.toArray();
+					for (Object element : ele) {
+						// dont start drag on root nodes
+						if (element instanceof RootCPListElement) {
+							event.doit= false;
+							break;
+						}
+						if (element instanceof CPListElement) {
+							CPListElement cpe= (CPListElement) element;
+							if (cpe.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
+								IPath path= cpe.getPath();
+								if (path != null) {
+									IVMInstall vmInstall= JavaRuntime.getVMInstall(path);
+									if (vmInstall != null) {
+										event.doit= false;
+										break;
+									}
+								}
+							}
+						}
+
+					}
+				}
+			}
+
+			@Override
+			public void dragSetData(DragSourceEvent event) {
+				IStructuredSelection ssel= (IStructuredSelection) fLibrariesList.getTreeViewer().getSelection();
+				event.data= ssel.toArray();
+				draggedItemsLibrary= ssel.toArray();
+			}
+
+			@Override
+			public void dragFinished(DragSourceEvent event) {
+				draggedItemsLibrary= null;
+			}
+		});
+
+		fLibrariesList.getTreeViewer().addDropSupport(ops, transfers, new ViewerDropAdapter(fLibrariesList.getTreeViewer()) {
+			@Override
+			public void dragEnter(DropTargetEvent event) {
+				Object target= determineTarget(event);
+				if (target == null && event.detail == DND.DROP_COPY) {
+					event.detail= DND.DROP_MOVE;
+				}
+				super.dragEnter(event);
+			}
+
+			@Override
+			public void dragOperationChanged(DropTargetEvent event) {
+				Object target= determineTarget(event);
+				if (target == null && event.detail == DND.DROP_COPY) {
+					event.detail= DND.DROP_MOVE;
+				}
+				super.dragOperationChanged(event);
+			}
+
+			@Override
+			public void dragOver(DropTargetEvent event) {
+				Object target= determineTarget(event);
+				if (target == null && event.detail == DND.DROP_COPY) {
+					event.detail= DND.DROP_MOVE;
+				}
+				super.dragOver(event);
+			}
+
+			@Override
+			protected int determineLocation(DropTargetEvent event) {
+				if (!(event.item instanceof Item)) {
+					return LOCATION_NONE;
+				}
+				Item item= (Item) event.item;
+				Point coordinates= new Point(event.x, event.y);
+				coordinates= getViewer().getControl().toControl(coordinates);
+				if (item != null) {
+					Rectangle bounds= getBounds(item);
+					if (bounds == null) {
+						return LOCATION_NONE;
+					}
+				}
+				return LOCATION_ON;
+			}
+
+			@Override
+			public boolean performDrop(Object data) {
+				Object[] objects= (data == null) ? (Object[]) draggedItemsLibrary : (Object[]) data;
+				if (objects == null)
+					return false;
+				Object target= getCurrentTarget();
+				if (target instanceof RootCPListElement) {
+					for (Object object : objects) {
+						if (!(object instanceof CPListElement))
+							return false;
+						if(object instanceof RootCPListElement)
+							return false;
+						boolean contains= ((RootCPListElement) target).getChildren().contains(object);
+						if (contains == true)
+							return false;
+						RootCPListElement rootNode= (RootCPListElement) target;
+						boolean isModular= rootNode.isModulePathRootNode();
+						RootNodeChange direction= RootNodeChange.fromOldAndNew(!isModular, isModular);
+						if (direction != RootNodeChange.NoChange) {
+							// pre-process container items while moving to modulepath
+							CPListElement cpe= (CPListElement) object;
+							if (cpe.getEntryKind() == IClasspathEntry.CPE_CONTAINER && isModular) {
+								IClasspathEntry entry= cpe.getClasspathEntry();
+								IClasspathAttribute[] extraAttributes= entry.getExtraAttributes();
+								boolean hasModAttr= false;
+								for (IClasspathAttribute attr : extraAttributes) {
+									if (IClasspathAttribute.MODULE.equals(attr.getName())) {
+										hasModAttr= true;
+										break;
+									}
+								}
+								if (!hasModAttr) {
+									cpe.updateExtraAttributeOfClasspathEntry();
+								}
+							}
+
+							moveCPElementAcrossNode(fLibrariesList, (CPListElement) object, direction);
+						}
+						((CPListElement) object).setAttribute(IClasspathAttribute.MODULE, isModular ? new ModuleEncapsulationDetail[0] : null);
+					}
+					return true;
+
+				}
+				return false;
+			}
+
+			@Override
+			public boolean validateDrop(Object target, int operation, TransferData transferType) {
+				return (target instanceof RootCPListElement);
+			}
+
+		});
+
+
+	}
+
 	boolean hasRootNodes(){
 		if (fLibrariesList == null)
 			return false;
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ProjectsWorkbookPage.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ProjectsWorkbookPage.java
index 3fc6731..8f56064 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ProjectsWorkbookPage.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/wizards/buildpaths/ProjectsWorkbookPage.java
@@ -16,18 +16,31 @@
 import java.util.List;
 
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DragSourceEvent;
+import org.eclipse.swt.dnd.DragSourceListener;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.dnd.FileTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.dnd.TransferData;
 import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Item;
 import org.eclipse.swt.widgets.Shell;
 
 import org.eclipse.jface.layout.PixelConverter;
 import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.ViewerDropAdapter;
 import org.eclipse.jface.window.Window;
 
 import org.eclipse.ui.dialogs.ListSelectionDialog;
+import org.eclipse.ui.part.ResourceTransfer;
 import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
 
 import org.eclipse.jdt.core.IAccessRule;
@@ -66,6 +79,9 @@
 	private Control fSWTControl;
 
 	private final IWorkbenchPreferenceContainer fPageContainer;
+	
+	private boolean dragDropEnabled;
+	private Object draggedItemsProject;
 
 	public ProjectsWorkbookPage(ListDialogField<CPListElement> classPathList, IWorkbenchPreferenceContainer pageContainer) {
 		fClassPathList= classPathList;
@@ -160,6 +176,127 @@
 		
 		fProjectsList.setElements(checkedProjects);
 		fProjectsList.enableButton(IDX_ADDPROJECT, false);
+		if (!dragDropEnabled) {
+			enableDragDropSupport();
+		}
+	}
+	
+	private void enableDragDropSupport() {
+		dragDropEnabled= true;
+		int ops= DND.DROP_MOVE | DND.DROP_DEFAULT;
+		Transfer[] transfers= new Transfer[] { ResourceTransfer.getInstance(), FileTransfer.getInstance() };
+
+		fProjectsList.getTreeViewer().addDragSupport(DND.DROP_MOVE | DND.DROP_COPY, transfers, new DragSourceListener() {
+			@Override
+			public void dragStart(DragSourceEvent event) {
+				IStructuredSelection ssel= (IStructuredSelection) fProjectsList.getTreeViewer().getSelection();
+				if (ssel == null || ssel.isEmpty()) {
+					event.doit= false;
+				}
+				if (ssel != null) {
+					Object[] ele= ssel.toArray();
+					for (Object element : ele) {
+						if (element instanceof RootCPListElement) {
+							event.doit= false;
+							break;
+						}
+					}
+				}
+			}
+
+			@Override
+			public void dragSetData(DragSourceEvent event) {
+				IStructuredSelection ssel= (IStructuredSelection) fProjectsList.getTreeViewer().getSelection();
+				event.data= ssel.toArray();
+				draggedItemsProject= ssel.toArray();
+			}
+
+			@Override
+			public void dragFinished(DragSourceEvent event) {
+				draggedItemsProject= null;
+			}
+		});
+
+		fProjectsList.getTreeViewer().addDropSupport(ops, transfers, new ViewerDropAdapter(fProjectsList.getTreeViewer()) {
+			@Override
+			public void dragEnter(DropTargetEvent event) {
+				Object target= determineTarget(event);
+				if (target == null && event.detail == DND.DROP_COPY) {
+					event.detail= DND.DROP_MOVE;
+				}
+				super.dragEnter(event);
+			}
+
+			@Override
+			public void dragOperationChanged(DropTargetEvent event) {
+				Object target= determineTarget(event);
+				if (target == null && event.detail == DND.DROP_COPY) {
+					event.detail= DND.DROP_MOVE;
+				}
+				super.dragOperationChanged(event);
+			}
+
+			@Override
+			public void dragOver(DropTargetEvent event) {
+				Object target= determineTarget(event);
+				if (target == null && event.detail == DND.DROP_COPY) {
+					event.detail= DND.DROP_MOVE;
+				}
+				super.dragOver(event);
+			}
+
+			@Override
+			protected int determineLocation(DropTargetEvent event) {
+				if (!(event.item instanceof Item)) {
+					return LOCATION_NONE;
+				}
+				Item item= (Item) event.item;
+				Point coordinates= new Point(event.x, event.y);
+				coordinates= getViewer().getControl().toControl(coordinates);
+				if (item != null) {
+					Rectangle bounds= getBounds(item);
+					if (bounds == null) {
+						return LOCATION_NONE;
+					}
+				}
+				return LOCATION_ON;
+			}
+
+			@Override
+			public boolean performDrop(Object data) {
+				Object[] objects= (data == null) ? (Object[]) draggedItemsProject : (Object[]) data;
+				if (objects == null)
+					return false;
+				Object target= getCurrentTarget();
+				if (target instanceof RootCPListElement) {
+					for (Object object : objects) {
+						if (!(object instanceof CPListElement))
+							return false;
+						if(object instanceof RootCPListElement)
+							return false;
+						boolean contains= ((RootCPListElement) target).getChildren().contains(object);
+						if (contains == true)
+							return false;
+						RootCPListElement rootNode= (RootCPListElement) target;
+						boolean isModular= rootNode.isModulePathRootNode();
+						RootNodeChange direction= RootNodeChange.fromOldAndNew(!isModular, isModular);
+						if (direction != RootNodeChange.NoChange) {
+							moveCPElementAcrossNode(fProjectsList, (CPListElement) object, direction);
+						}
+						((CPListElement) object).setAttribute(IClasspathAttribute.MODULE, isModular ? new ModuleEncapsulationDetail[0] : null);
+					}
+					return true;
+
+				}
+				return false;
+			}
+
+			@Override
+			public boolean validateDrop(Object target, int operation, TransferData transferType) {
+				return (target instanceof RootCPListElement);
+			}
+		});
+
 	}
 
 	// -------- UI creation ---------