171852: Breakdown level editing
diff --git a/plugins/org.eclipse.epf.authoring.ui/src/org/eclipse/epf/authoring/ui/actions/IndentAction.java b/plugins/org.eclipse.epf.authoring.ui/src/org/eclipse/epf/authoring/ui/actions/IndentAction.java
new file mode 100755
index 0000000..8b0b4eb
--- /dev/null
+++ b/plugins/org.eclipse.epf.authoring.ui/src/org/eclipse/epf/authoring/ui/actions/IndentAction.java
@@ -0,0 +1,232 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2007 IBM Corporation 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:
+// IBM Corporation - initial implementation
+//------------------------------------------------------------------------------
+package org.eclipse.epf.authoring.ui.actions;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.emf.common.command.AbstractCommand;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.command.UnexecutableCommand;
+import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
+import org.eclipse.emf.edit.domain.IEditingDomainProvider;
+import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
+import org.eclipse.emf.edit.ui.action.CommandActionHandler;
+import org.eclipse.epf.authoring.ui.editors.ProcessEditor;
+import org.eclipse.epf.library.edit.command.IResourceAwareCommand;
+import org.eclipse.epf.library.edit.util.TngUtil;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.uma.Activity;
+import org.eclipse.epf.uma.BreakdownElement;
+import org.eclipse.epf.uma.Descriptor;
+import org.eclipse.epf.uma.Process;
+import org.eclipse.epf.uma.ProcessPackage;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.ui.IWorkbenchPart;
+
+/**
+ * Update suppression information from base elements
+ * 
+ * @author Phong Nguyen Le
+ * @since  1.2
+ */
+public class IndentAction extends
+		CommandActionHandler implements IWorkbenchPartAction {
+
+	public static class IndentCommand extends AbstractCommand implements IResourceAwareCommand {
+		
+		private Collection<BreakdownElement> elements;
+		private AdapterFactory adapterFactory;
+		private Set modifiedResources;
+		private BreakdownElement element;
+		private Activity oldParent;
+		private Activity newParent;
+		private int oldIndex;
+
+		public IndentCommand(Collection<BreakdownElement> collection, AdapterFactory adapterFactory) {
+			this.elements = collection;
+			this.adapterFactory = adapterFactory;
+			setLabel(LABEL);
+		}
+
+		public Collection getModifiedResources() {
+			if(modifiedResources == null) {
+				Process proc = null;
+				for (Iterator<BreakdownElement> iter = elements.iterator(); proc == null && iter.hasNext();) {
+					BreakdownElement e = iter.next();
+					proc = TngUtil.getOwningProcess(e);
+				}
+				if(proc != null) {
+					Resource resource = proc.eResource();
+					if(resource != null) {
+						modifiedResources = Collections.singleton(proc.eResource());
+					}
+				}
+				if(modifiedResources == null) {
+					modifiedResources = Collections.EMPTY_SET;
+				}
+			}
+			return modifiedResources;
+		}
+		
+		@Override
+		protected boolean prepare() {
+			element = elements.iterator().next();
+			oldParent = element.getSuperActivities();
+			if(oldParent == null) {
+				return false;
+			}
+			oldIndex = oldParent.getBreakdownElements().indexOf(element);
+			ITreeItemContentProvider ip = (ITreeItemContentProvider) adapterFactory.adapt(oldParent, 
+					ITreeItemContentProvider.class);
+			List<Object> children = new LinkedList<Object>(ip.getChildren(oldParent));
+			int index = children.indexOf(element);
+			if(index > 0) {
+				Object prev = children.get(index - 1);
+				if(prev instanceof Activity) {
+					newParent = (Activity) prev;
+					return true;
+				}
+			}
+			return false;
+		}
+
+		public void execute() {
+			newParent.getBreakdownElements().add(element);
+			// move the process pacakge of the activity to new parent package
+			//
+			if(element instanceof Activity) {
+				ProcessPackage parentPkg = (ProcessPackage) newParent.eContainer();
+				parentPkg.getChildPackages().add(element.eContainer());
+			}
+		}
+
+		public void redo() {
+			execute();
+		}
+		
+		@Override
+		public void undo() {
+			oldParent.getBreakdownElements().add(oldIndex, element);
+			if(element instanceof Activity) {
+				ProcessPackage parentPkg = (ProcessPackage) oldParent.eContainer();
+				parentPkg.getChildPackages().add(element.eContainer());
+			}
+		}
+		
+		@Override
+		public Collection getAffectedObjects() {
+			return elements;
+		}
+	}
+
+	private static final String LABEL = "Indent";
+
+	private ProcessEditor editor;
+
+	/**
+	 * Creates an instance
+	 * @param text
+	 */
+	public IndentAction(String text) {
+		super(null, text);
+	}
+	
+	/**
+	 * Creates an instance
+	 *
+	 */
+	public IndentAction() {
+		this(LABEL);
+		setImageDescriptor(RichTextImages.IMG_DESC_INDENT);
+		setDisabledImageDescriptor(RichTextImages.DISABLED_IMG_DESC_INDENT);
+		setToolTipText(LABEL);
+	}
+	
+	/**
+	 * @see org.eclipse.emf.edit.ui.action.CommandActionHandler#updateSelection(org.eclipse.jface.viewers.IStructuredSelection)
+	 */
+	public boolean updateSelection(IStructuredSelection selection) {
+		// support indent only one activity for now
+		//
+		if(selection.size() == 1) {
+			Object e = selection.getFirstElement();
+			if(e instanceof Activity || e instanceof Descriptor) {
+				return super.updateSelection(selection);
+			}
+		}
+		return false;
+		
+		//TODO: support indent multiple activities in selection
+//		ArrayList<Activity> list = new ArrayList<Activity>();
+//		for (Iterator iter = selection.iterator(); iter.hasNext();) {
+//			Object element = iter.next();
+//			if(element instanceof Activity) {
+//				list.add((Activity) element);
+//			}
+//		}
+//		if(list.isEmpty()) {
+//			return false;
+//		}
+//		return super.updateSelection(new StructuredSelection(list));
+	}
+	
+	/**
+	 * @see org.eclipse.emf.edit.ui.action.CommandActionHandler#createCommand(java.util.Collection)
+	 */
+	public Command createCommand(Collection selection) {
+		if(domain instanceof AdapterFactoryEditingDomain) {
+			return new IndentCommand(selection, ((AdapterFactoryEditingDomain)domain).getAdapterFactory());
+		}
+		return UnexecutableCommand.INSTANCE;
+	}	
+
+	/**
+	 * @see org.eclipse.epf.authoring.ui.actions.IWorkbenchPartAction#setActiveWorkbenchPart(org.eclipse.ui.IWorkbenchPart)
+	 */
+	public void setActiveWorkbenchPart(IWorkbenchPart workbenchPart) {
+		if(workbenchPart instanceof IEditingDomainProvider) {
+			domain = ((IEditingDomainProvider)workbenchPart).getEditingDomain();
+		}
+		if(workbenchPart instanceof ProcessEditor) {
+			editor = (ProcessEditor) workbenchPart;
+		}		
+		else if(workbenchPart == null) {
+			editor = null;
+		}
+	}	
+	
+	private void superRun() {
+		super.run();
+	}
+	
+	/**
+	 * @see org.eclipse.emf.edit.ui.action.CommandActionHandler#run()
+	 */
+	public void run() {
+		BusyIndicator.showWhile(editor.getEditorSite()
+				.getShell().getDisplay(), new Runnable() {
+
+					public void run() {
+						superRun();
+					}
+			
+		});
+	}
+	
+}
diff --git a/plugins/org.eclipse.epf.authoring.ui/src/org/eclipse/epf/authoring/ui/actions/OutdentAction.java b/plugins/org.eclipse.epf.authoring.ui/src/org/eclipse/epf/authoring/ui/actions/OutdentAction.java
new file mode 100755
index 0000000..49d9d84
--- /dev/null
+++ b/plugins/org.eclipse.epf.authoring.ui/src/org/eclipse/epf/authoring/ui/actions/OutdentAction.java
@@ -0,0 +1,307 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2007 IBM Corporation 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:
+// IBM Corporation - initial implementation
+//------------------------------------------------------------------------------
+package org.eclipse.epf.authoring.ui.actions;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.emf.common.command.AbstractCommand;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.command.UnexecutableCommand;
+import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.common.util.UniqueEList;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
+import org.eclipse.emf.edit.domain.IEditingDomainProvider;
+import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
+import org.eclipse.emf.edit.ui.action.CommandActionHandler;
+import org.eclipse.epf.authoring.ui.editors.ProcessEditor;
+import org.eclipse.epf.library.edit.TngAdapterFactory;
+import org.eclipse.epf.library.edit.command.IResourceAwareCommand;
+import org.eclipse.epf.library.edit.util.ProcessUtil;
+import org.eclipse.epf.library.edit.util.TngUtil;
+import org.eclipse.epf.richtext.RichTextImages;
+import org.eclipse.epf.uma.Activity;
+import org.eclipse.epf.uma.BreakdownElement;
+import org.eclipse.epf.uma.Descriptor;
+import org.eclipse.epf.uma.Process;
+import org.eclipse.epf.uma.ProcessPackage;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.ui.IWorkbenchPart;
+
+/**
+ * Update suppression information from base elements
+ * 
+ * @author Phong Nguyen Le
+ * @since  1.2
+ */
+public class OutdentAction extends
+		CommandActionHandler implements IWorkbenchPartAction {
+	public static class OutdentCommand extends AbstractCommand implements IResourceAwareCommand {
+		private static final AdapterFactory[] ADAPTER_FACTORIES = {
+			TngAdapterFactory.INSTANCE.getWBS_ComposedAdapterFactory(),
+			TngAdapterFactory.INSTANCE.getOBS_ComposedAdapterFactory(),
+			TngAdapterFactory.INSTANCE.getWBS_ComposedAdapterFactory()
+		};
+		
+		private Collection<BreakdownElement> elements;
+		private Set modifiedResources;
+		private BreakdownElement element;
+		private Activity oldParent;
+		private Activity newParent;
+		private int oldIndex;
+		private int newIndex;
+		private List<Object> newChildren;
+
+		private AdapterFactory adapterFactory;
+
+		public OutdentCommand(Collection<BreakdownElement> collection, AdapterFactory adapterFactory) {
+			this.elements = collection;
+			this.adapterFactory = adapterFactory;
+			setLabel(LABEL);
+		}
+		
+		@Override
+		public void dispose() {
+			if(newChildren != null) {
+				newChildren.clear();
+				newChildren = null;
+			}
+			
+			super.dispose();
+		}
+
+		public Collection getModifiedResources() {
+			if(modifiedResources == null) {
+				Process proc = null;
+				for (Iterator<BreakdownElement> iter = elements.iterator(); proc == null && iter.hasNext();) {
+					BreakdownElement e = iter.next();
+					proc = TngUtil.getOwningProcess(e);
+				}
+				if(proc != null) {
+					Resource resource = proc.eResource();
+					if(resource != null) {
+						modifiedResources = Collections.singleton(proc.eResource());
+					}
+				}
+				if(modifiedResources == null) {
+					modifiedResources = Collections.EMPTY_SET;
+				}
+			}
+			return modifiedResources;
+		}
+		
+		@Override
+		protected boolean prepare() {
+			element = elements.iterator().next();
+			oldParent = element.getSuperActivities();
+			if(oldParent == null) {
+				return false;
+			}
+			oldIndex = oldParent.getBreakdownElements().indexOf(element);
+			Map<List<Object>, Integer> childrenToStartIndexMap = new HashMap<List<Object>, Integer>();
+			AdapterFactory[] adapterFactories;
+			if(element instanceof Activity) {
+				adapterFactories = ADAPTER_FACTORIES;
+			}
+			else {
+				adapterFactories = new AdapterFactory[] {
+					adapterFactory	
+				};
+			}
+			for (int i = 0; i < adapterFactories.length; i++) {
+				AdapterFactory adapterFactory = adapterFactories[i];
+				ITreeItemContentProvider ip = (ITreeItemContentProvider) adapterFactory.adapt(oldParent, 
+						ITreeItemContentProvider.class);
+				List<Object> children = new ArrayList<Object>(ip.getChildren(oldParent));
+				int index = children.indexOf(element);
+				int size = children.size();
+				int newChildrenFromIndex = index + 1;
+				if(newChildrenFromIndex < size) {
+					for(int j = newChildrenFromIndex; j < size; j++) {
+						Object child = children.get(j);
+						if(ProcessUtil.isInherited(child)) {
+							// cannot outdent activity that have inherited sibling below it
+							//
+							return false;
+						}
+					}
+					childrenToStartIndexMap.put(children, Integer.valueOf(newChildrenFromIndex));
+				}
+			}
+			if(!(element instanceof Activity) && !childrenToStartIndexMap.isEmpty()) {
+				return false;
+			}
+			newParent = oldParent.getSuperActivities();
+			if(newParent != null) {
+				newIndex = newParent.getBreakdownElements().indexOf(oldParent) + 1;
+				if(!childrenToStartIndexMap.isEmpty()) {
+					newChildren = new UniqueEList();
+					for (Iterator<Map.Entry<List<Object>, Integer>> iter = childrenToStartIndexMap.entrySet().iterator(); iter.hasNext();) {
+						Map.Entry<List<Object>, Integer> entry = iter.next();
+						List children = entry.getKey();
+						newChildren.addAll(children.subList(entry.getValue().intValue(), children.size()));
+					}
+				}
+				return true;
+			}
+			return false;
+		}
+
+		public void execute() {
+			newParent.getBreakdownElements().add(newIndex, element);
+			if(element instanceof Activity) {
+				ProcessPackage parentPkg = (ProcessPackage) newParent.eContainer();
+				parentPkg.getChildPackages().add(element.eContainer());
+
+				if(newChildren != null) {
+					((Activity)element).getBreakdownElements().addAll(newChildren);			
+					// move the process pacakge of the activity to new parent package
+					//
+					for (Iterator iter = newChildren.iterator(); iter.hasNext();) {
+						Object child = iter.next();
+						if(child instanceof Activity) {
+							parentPkg.getChildPackages().add(((Activity)child).eContainer());
+						}
+					}
+				}
+			}
+		}
+
+		public void redo() {
+			execute();
+		}
+		
+		@Override
+		public void undo() {
+			oldParent.getBreakdownElements().add(oldIndex, element);
+			if(element instanceof Activity) {
+				ProcessPackage parentPkg = (ProcessPackage) oldParent.eContainer();
+				parentPkg.getChildPackages().add(element.eContainer());
+				if(newChildren != null) {
+					((Activity) element).getBreakdownElements().removeAll(newChildren);
+					for (Iterator iter = newChildren.iterator(); iter.hasNext();) {
+						Object child = iter.next();
+						if(child instanceof Activity) {
+							parentPkg.getChildPackages().add(((Activity)child).eContainer());
+						}
+					}
+				}
+			}
+		}
+		
+		@Override
+		public Collection getAffectedObjects() {
+			return elements;
+		}
+	}
+
+	private static final String LABEL = "Outdent";
+
+	private ProcessEditor editor;
+
+	/**
+	 * Creates an instance
+	 * @param text
+	 */
+	public OutdentAction(String text) {
+		super(null, text);
+	}
+	
+	/**
+	 * Creates an instance
+	 *
+	 */
+	public OutdentAction() {
+		this(LABEL);
+		setImageDescriptor(RichTextImages.IMG_DESC_OUTDENT);
+		setDisabledImageDescriptor(RichTextImages.DISABLED_IMG_DESC_OUTDENT);
+		setToolTipText(LABEL);
+	}
+	
+	/**
+	 * @see org.eclipse.emf.edit.ui.action.CommandActionHandler#updateSelection(org.eclipse.jface.viewers.IStructuredSelection)
+	 */
+	public boolean updateSelection(IStructuredSelection selection) {
+		// support indent only one activity for now
+		//
+		if(selection.size() == 1) {
+			Object e = selection.getFirstElement();
+			if(e instanceof Activity || e instanceof Descriptor) {
+				return super.updateSelection(selection);
+			}
+		}
+		return false;
+		
+		//TODO: support indent multiple activities in selection
+//		ArrayList<Activity> list = new ArrayList<Activity>();
+//		for (Iterator iter = selection.iterator(); iter.hasNext();) {
+//			Object element = iter.next();
+//			if(element instanceof Activity) {
+//				list.add((Activity) element);
+//			}
+//		}
+//		if(list.isEmpty()) {
+//			return false;
+//		}
+//		return super.updateSelection(new StructuredSelection(list));
+	}
+	
+	/**
+	 * @see org.eclipse.emf.edit.ui.action.CommandActionHandler#createCommand(java.util.Collection)
+	 */
+	public Command createCommand(Collection selection) {
+		if(domain instanceof AdapterFactoryEditingDomain) {
+			return new OutdentCommand(selection, ((AdapterFactoryEditingDomain)domain).getAdapterFactory());
+		}
+		return UnexecutableCommand.INSTANCE;
+	}	
+
+	/**
+	 * @see org.eclipse.epf.authoring.ui.actions.IWorkbenchPartAction#setActiveWorkbenchPart(org.eclipse.ui.IWorkbenchPart)
+	 */
+	public void setActiveWorkbenchPart(IWorkbenchPart workbenchPart) {
+		if(workbenchPart instanceof IEditingDomainProvider) {
+			domain = ((IEditingDomainProvider)workbenchPart).getEditingDomain();
+		}
+		if(workbenchPart instanceof ProcessEditor) {
+			editor = (ProcessEditor) workbenchPart;
+		}		
+		else if(workbenchPart == null) {
+			editor = null;
+		}
+	}	
+	
+	private void superRun() {
+		super.run();
+	}
+	
+	/**
+	 * @see org.eclipse.emf.edit.ui.action.CommandActionHandler#run()
+	 */
+	public void run() {
+		BusyIndicator.showWhile(editor.getEditorSite()
+				.getShell().getDisplay(), new Runnable() {
+
+					public void run() {
+						superRun();
+					}
+			
+		});
+	}
+}
diff --git a/plugins/org.eclipse.epf.authoring.ui/src/org/eclipse/epf/authoring/ui/editors/MethodElementEditor.java b/plugins/org.eclipse.epf.authoring.ui/src/org/eclipse/epf/authoring/ui/editors/MethodElementEditor.java
index cc0111f..2993850 100755
--- a/plugins/org.eclipse.epf.authoring.ui/src/org/eclipse/epf/authoring/ui/editors/MethodElementEditor.java
+++ b/plugins/org.eclipse.epf.authoring.ui/src/org/eclipse/epf/authoring/ui/editors/MethodElementEditor.java
@@ -1207,6 +1207,8 @@
 			// check for modifiable
 			//
 			Collection<Resource> modifiedResources = getModifiedResources();
+			
+			ArrayList<Resource> resourcesToSave = new ArrayList<Resource>(modifiedResources);
 
 			// update version info in library resource if needed by adding
 			// library resource to collection
@@ -1234,11 +1236,11 @@
 						}
 					}
 				}
-				modifiedResources.addAll(resourcesToUpdateVersionInfo);
+				resourcesToSave.addAll(resourcesToUpdateVersionInfo);
 			}
 
 			IStatus status = UserInteractionHelper.checkModify(
-					modifiedResources, getSite().getShell());
+					resourcesToSave, getSite().getShell());
 			if (!status.isOK()) {
 				handleError(status);
 				return;
@@ -1246,7 +1248,7 @@
 
 			// check for out-of-synch
 			//
-			if (checkFileChanged(modifiedResources)) {
+			if (checkFileChanged(resourcesToSave)) {
 				String title = LibraryEditResources.update_outofsynch_title;
 				String msg = LibraryEditResources.update_outofsynch_msg;
 				if (!AuthoringUIPlugin.getDefault().getMsgDialog()
@@ -1282,7 +1284,7 @@
 
 			// Save.
 			//
-			for (Iterator iter = modifiedResources.iterator(); iter.hasNext();) {
+			for (Iterator iter = resourcesToSave.iterator(); iter.hasNext();) {
 				Resource resource = (Resource) iter.next();
 				try {
 					persister.save(resource);
diff --git a/plugins/org.eclipse.epf.authoring.ui/src/org/eclipse/epf/authoring/ui/editors/ProcessEditor.java b/plugins/org.eclipse.epf.authoring.ui/src/org/eclipse/epf/authoring/ui/editors/ProcessEditor.java
index 42d99cb..b86d747 100755
--- a/plugins/org.eclipse.epf.authoring.ui/src/org/eclipse/epf/authoring/ui/editors/ProcessEditor.java
+++ b/plugins/org.eclipse.epf.authoring.ui/src/org/eclipse/epf/authoring/ui/editors/ProcessEditor.java
@@ -66,13 +66,16 @@
 import org.eclipse.emf.edit.ui.action.EditingDomainActionBarContributor;
 import org.eclipse.emf.edit.ui.action.PasteAction;
 import org.eclipse.emf.edit.ui.dnd.LocalTransfer;
+import org.eclipse.emf.edit.ui.dnd.ViewerDragAdapter;
 import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider;
 import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
 import org.eclipse.epf.authoring.ui.AuthoringUIPlugin;
 import org.eclipse.epf.authoring.ui.AuthoringUIResources;
 import org.eclipse.epf.authoring.ui.actions.IWorkbenchPartAction;
+import org.eclipse.epf.authoring.ui.actions.IndentAction;
 import org.eclipse.epf.authoring.ui.actions.LibraryValidateAction;
 import org.eclipse.epf.authoring.ui.actions.MethodLibraryActionBarContributor;
+import org.eclipse.epf.authoring.ui.actions.OutdentAction;
 import org.eclipse.epf.authoring.ui.actions.ProcessAutoSynchronizeAction;
 import org.eclipse.epf.authoring.ui.actions.SynchronizationAction;
 import org.eclipse.epf.authoring.ui.actions.UpdateSuppressionFromBaseAction;
@@ -1659,6 +1662,10 @@
 
 		private boolean oldLocked;
 
+		private Action indentAction = new IndentAction();
+
+		private Action outdentAction = new OutdentAction();
+
 		public BSActionBarContributor() {
 			super(AuthoringUIResources.ProcessEditor);
 			
@@ -1675,7 +1682,7 @@
 							"full/etool16/move_down_disabled.gif")); //$NON-NLS-1$
 			showInLibraryView.setDisabledImageDescriptor(AuthoringUIPlugin
 					.getDefault().getImageDescriptor(
-							"full/etool16/show_linked_element_disabled.gif")); //$NON-NLS-1$
+							"full/etool16/show_linked_element_disabled.gif")); //$NON-NLS-1$			
 		}
 		
 		private static PreferencesHint getDiagramPreferencesHint(int diagramType) {
@@ -1710,6 +1717,8 @@
 			registerAction(autoSynchronize);
 			registerAction(manualSynchronizeAction);
 			registerAction(updateSuppressionFromBaseAction);
+			registerAction(indentAction);
+			registerAction(outdentAction);
 		}
 
 		/**
@@ -1972,6 +1981,8 @@
 					.setToolTipText(AuthoringUIResources.ProcessEditor_Action_ShowLinkedElementinLibraryView); 
 			toolBarManager.add(moveUpAction);
 			toolBarManager.add(moveDownAction);
+			toolBarManager.add(indentAction);
+			toolBarManager.add(outdentAction);
 			toolBarManager.add(showInLibraryView);
 		}				
 
@@ -2059,14 +2070,15 @@
 			}
 
 			if ((selectedBreakdownElement != null) && (bsItemProvider != null)) {
-				if (moveUpAction.isEnabled()) {
-					menuManager.insertBefore("fixed-additions", moveUpAction); //$NON-NLS-1$
-				}
-				if (moveDownAction.isEnabled()) {
-					menuManager.insertBefore("fixed-additions", moveDownAction); //$NON-NLS-1$
-				}
+				menuManager.insertBefore("fixed-additions", moveUpAction); //$NON-NLS-1$
+				menuManager.insertBefore("fixed-additions", moveDownAction); //$NON-NLS-1$
 			}
 
+			// Indent/outdent
+			//
+			menuManager.insertBefore("fixed-additions", indentAction); //$NON-NLS-1$				
+			menuManager.insertBefore("fixed-additions", outdentAction); //$NON-NLS-1$
+
 			menuManager.appendToGroup("open", showInLibraryView); //$NON-NLS-1$
 
 			if ((selectedActivity != null) && (bsItemProvider != null)) {
@@ -2089,7 +2101,7 @@
 				reuseSubMenu.add(extendActivityAction);
 				reuseSubMenu.add(deepCopyActivityAction);
 
-				menuManager.insertBefore(IWorkbenchActionConstants.MB_ADDITIONS, reuseSubMenu); 
+				menuManager.insertBefore(IWorkbenchActionConstants.MB_ADDITIONS, reuseSubMenu); 				
 			}
 
 			if (autoSynchronize.isEnabled()) {
@@ -3580,10 +3592,15 @@
 			}
 		});
 
-		int dndOperations = DND.DROP_LINK | DND.DROP_COPY;
+		int dndOperations = DND.DROP_LINK | DND.DROP_COPY | DND.DROP_MOVE;
 		Transfer[] transfers = new Transfer[] { LocalTransfer.getInstance() };
 		viewer.addDropSupport(dndOperations, transfers,
 				new ProcessEditorDropAdapter(editingDomain, viewer));
+		
+		dndOperations = DND.DROP_MOVE | DND.DROP_COPY;
+		transfers = new Transfer[] { LocalTransfer.getInstance() };
+		viewer.addDragSupport(dndOperations, transfers, new ViewerDragAdapter(viewer));
+
 	}
 
 	private void setCurrentViewer(Viewer viewer) {
diff --git a/plugins/org.eclipse.epf.authoring.ui/src/org/eclipse/epf/authoring/ui/forms/ProcessBreakdownStructureFormPage.java b/plugins/org.eclipse.epf.authoring.ui/src/org/eclipse/epf/authoring/ui/forms/ProcessBreakdownStructureFormPage.java
index 861e6b1..da936a4 100755
--- a/plugins/org.eclipse.epf.authoring.ui/src/org/eclipse/epf/authoring/ui/forms/ProcessBreakdownStructureFormPage.java
+++ b/plugins/org.eclipse.epf.authoring.ui/src/org/eclipse/epf/authoring/ui/forms/ProcessBreakdownStructureFormPage.java
@@ -655,11 +655,11 @@
 		viewer.setAutoExpandLevel(3);
 		viewer.setInput(process);
 
-		// int dndOperations = DND.DROP_COPY | DND.DROP_MOVE ;
-		// Transfer[] transfers = new Transfer[] { TNGObjTransfer.getInstance()
-		// };
-		// tableTreeViewer.addDropSupport(DND.DROP_MOVE, transfers, new
-		// BSTabDropAdapter(tableTreeViewer));
+//		 int dndOperations = DND.DROP_COPY | DND.DROP_MOVE ;
+//		 Transfer[] transfers = new Transfer[] { TNGObjTransfer.getInstance()
+//		 };
+//		 tableTreeViewer.addDropSupport(DND.DROP_MOVE, transfers, new
+//		 BSTabDropAdapter(tableTreeViewer));
 
 		// BSEditorView.getView().createContextMenuFor(tableTreeViewer);
 		// return tableTreeViewer.getControl();
diff --git a/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/command/FullyRevertibleCommandStack.java b/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/command/FullyRevertibleCommandStack.java
index 368d35b..f25f67e 100755
--- a/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/command/FullyRevertibleCommandStack.java
+++ b/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/command/FullyRevertibleCommandStack.java
@@ -12,13 +12,13 @@
 
 import java.util.EventObject;
 import java.util.Iterator;
+import java.util.Set;
 
 import org.eclipse.emf.common.CommonPlugin;
 import org.eclipse.emf.common.command.BasicCommandStack;
 import org.eclipse.emf.common.command.Command;
 import org.eclipse.emf.common.command.CommandStackListener;
 import org.eclipse.emf.common.util.WrappedException;
-import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.resource.Resource;
 import org.eclipse.epf.library.edit.LibraryEditResources;
 import org.eclipse.epf.library.edit.process.command.BSDragAndDropCommand;
@@ -54,6 +54,16 @@
 	public void setErrorReporter(IErrorReporter errReporter) {
 		this.errReporter = errReporter;
 	}
+	
+	private void registerAsModifier(Command command) {
+		Set<Resource> modifiedResources = TngUtil.getModifiedResources(command);
+		if(!modifiedResources.isEmpty()) {
+			for (Iterator iter = modifiedResources.iterator(); iter.hasNext();) {
+				Resource resource = (Resource) iter.next();
+				actionMgr.registerAsModifierOf(resource);
+			}
+		}
+	}
 
 	public boolean doExecute(Command command) {
 		if (!command.canUndo())
@@ -82,19 +92,8 @@
 		}
 		
 		boolean ret = getMostRecentCommand() != null;
-		if (ret && actionMgr != null) {
-			if (command instanceof IResourceAwareCommand) {
-				for (Iterator iter = ((IResourceAwareCommand) command)
-						.getModifiedResources().iterator(); iter.hasNext();) {
-					Resource resource = (Resource) iter.next();
-					actionMgr.registerAsModifierOf(resource);
-				}
-			} else {
-				EObject modified = TngUtil.getOwner(command);
-				if (modified != null) {
-					actionMgr.registerAsModifierOf(modified);
-				}
-			}
+		if (ret && actionMgr != null) {			
+			registerAsModifier(command);
 		}
 		notifyListeners(new CommandStackChangedEvent(this,
 				CommandStackChangedEvent.EXECUTED));
diff --git a/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/command/ResourceAwareDragAndDropCommand.java b/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/command/ResourceAwareDragAndDropCommand.java
new file mode 100755
index 0000000..1c4df55
--- /dev/null
+++ b/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/command/ResourceAwareDragAndDropCommand.java
@@ -0,0 +1,78 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2007 IBM Corporation 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:
+// IBM Corporation - initial implementation
+//------------------------------------------------------------------------------
+package org.eclipse.epf.library.edit.command;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.edit.command.DragAndDropCommand;
+import org.eclipse.emf.edit.domain.EditingDomain;
+import org.eclipse.epf.library.edit.util.TngUtil;
+
+/**
+ * @author Phong Nguyen Le
+ * @sine 1.2
+ */
+public class ResourceAwareDragAndDropCommand extends DragAndDropCommand 
+implements IResourceAwareCommand
+{
+
+	private Set<Resource> modifiedResources;
+
+	/**
+	 * @param domain
+	 * @param owner
+	 * @param location
+	 * @param operations
+	 * @param operation
+	 * @param collection
+	 */
+	public ResourceAwareDragAndDropCommand(EditingDomain domain, Object owner,
+			float location, int operations, int operation, Collection collection) {
+		super(domain, owner, location, operations, operation, collection);
+	}
+
+	/**
+	 * @param domain
+	 * @param owner
+	 * @param location
+	 * @param operations
+	 * @param operation
+	 * @param collection
+	 * @param optimize
+	 */
+	public ResourceAwareDragAndDropCommand(EditingDomain domain, Object owner,
+			float location, int operations, int operation,
+			Collection collection, boolean optimize) {
+		super(domain, owner, location, operations, operation, collection,
+				optimize);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.ibm.library.edit.command.IResourceAwareCommand#getModifiedResources()
+	 */
+	public Collection getModifiedResources() {
+		if(modifiedResources == null) {
+			if(dropCommand != null) {
+				modifiedResources = TngUtil.getModifiedResources(dropCommand);
+			}
+			if(modifiedResources == null || modifiedResources.isEmpty()) {
+				modifiedResources = Collections.EMPTY_SET;
+			}
+		}
+		return modifiedResources;
+	}
+
+}
diff --git a/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/process/BSActivityItemProvider.java b/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/process/BSActivityItemProvider.java
index 94c4b03..3b204a6 100755
--- a/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/process/BSActivityItemProvider.java
+++ b/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/process/BSActivityItemProvider.java
@@ -27,7 +27,9 @@
 import org.eclipse.emf.common.util.AbstractTreeIterator;
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.resource.Resource;
 import org.eclipse.emf.edit.command.AddCommand;
+import org.eclipse.emf.edit.command.MoveCommand;
 import org.eclipse.emf.edit.command.CopyCommand.Helper;
 import org.eclipse.emf.edit.domain.EditingDomain;
 import org.eclipse.emf.edit.provider.Disposable;
@@ -1527,4 +1529,45 @@
 	public void setEnableVariabilityInfo(boolean enableVariabilityInfo) {
 		this.enableVariabilityInfo = enableVariabilityInfo;
 	}
+	
+	private class MoveCommandEx extends MoveCommand implements IResourceAwareCommand {
+
+		private Set<Resource> modifiedResources;
+
+		public MoveCommandEx(EditingDomain domain, EObject owner, EStructuralFeature feature, Object value, int index) {
+			super(domain, owner, feature, value, index);
+		}				
+		
+		@Override
+		public void doExecute() {
+			// translate view index to index in breakdown elements list
+			//
+			List children = (List) getChildren(getTarget());
+			Object child = children.get(index);
+			index = ownerList.indexOf(child);
+			if(index != -1) {
+				super.doExecute();
+			}
+			
+			//TODO: move in between green elements
+		}
+
+		public Collection getModifiedResources() {
+			if(modifiedResources == null) {
+				Resource resource = owner.eResource();
+				if(resource != null) {
+					modifiedResources = Collections.singleton(resource);
+				}
+				else {
+					modifiedResources = Collections.EMPTY_SET;
+				}
+			}
+			return modifiedResources;
+		}
+	}
+	
+	@Override
+	protected Command createMoveCommand(EditingDomain domain, EObject owner, EStructuralFeature feature, Object value, int index) {
+		return new MoveCommandEx(domain, owner, feature, value, index);
+	}
 }
\ No newline at end of file
diff --git a/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/process/DescriptorItemProvider.java b/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/process/DescriptorItemProvider.java
index 9e9aa1c..e44bea2 100755
--- a/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/process/DescriptorItemProvider.java
+++ b/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/process/DescriptorItemProvider.java
@@ -11,12 +11,16 @@
 package org.eclipse.epf.library.edit.process;
 
 import java.text.MessageFormat;
+import java.util.Collection;
 import java.util.Iterator;
 
+import org.eclipse.emf.common.command.Command;
 import org.eclipse.emf.common.notify.AdapterFactory;
+import org.eclipse.emf.edit.domain.EditingDomain;
 import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
 import org.eclipse.emf.edit.provider.ItemProviderAdapter;
 import org.eclipse.epf.library.edit.LibraryEditResources;
+import org.eclipse.epf.library.edit.command.ResourceAwareDragAndDropCommand;
 import org.eclipse.epf.library.edit.util.ProcessUtil;
 import org.eclipse.epf.library.edit.util.TngUtil;
 import org.eclipse.epf.uma.Activity;
@@ -109,4 +113,9 @@
 		return super.getAttribute(object, property);
 	}
 
+	@Override
+	protected Command createDragAndDropCommand(EditingDomain domain, Object owner, float location, int operations, int operation, Collection collection) {
+		return new ResourceAwareDragAndDropCommand(domain, owner, location, operations,
+				operation, collection);
+	}
 }
\ No newline at end of file
diff --git a/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/process/WBSActivityItemProvider.java b/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/process/WBSActivityItemProvider.java
index 14dca89..d7c5b92 100755
--- a/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/process/WBSActivityItemProvider.java
+++ b/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/process/WBSActivityItemProvider.java
@@ -108,12 +108,12 @@
 		Command cmd = new WBSDragAndDropCommand(domain, owner, location,
 				operations, operation, collection);
 
-		// System.out.println(" can execute: " + cmd.canExecute());
-		// System.out.println(" owner: " + owner);
-		// System.out.println(" collection: " + collection);
-		// System.out.println(" location: " + location);
-		// System.out.println(" operations: " + operations);
-		// System.out.println(" operation: " + operation);
+		 System.out.println(" can execute: " + cmd.canExecute());
+		 System.out.println(" owner: " + owner);
+		 System.out.println(" collection: " + collection);
+		 System.out.println(" location: " + location);
+		 System.out.println(" operations: " + operations);
+		 System.out.println(" operation: " + operation);
 		//        
 		// System.out
 		// .println("EXIT:
diff --git a/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/process/command/BSDragAndDropCommand.java b/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/process/command/BSDragAndDropCommand.java
index 99e8c0e..951ad93 100755
--- a/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/process/command/BSDragAndDropCommand.java
+++ b/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/process/command/BSDragAndDropCommand.java
@@ -23,18 +23,15 @@
 import org.eclipse.emf.common.notify.AdapterFactory;
 import org.eclipse.emf.common.ui.viewer.IViewerProvider;
 import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.edit.command.DragAndDropCommand;
 import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
 import org.eclipse.emf.edit.domain.EditingDomain;
-import org.eclipse.epf.library.edit.command.IResourceAwareCommand;
 import org.eclipse.epf.library.edit.command.ResourceAwareCompoundCommand;
+import org.eclipse.epf.library.edit.command.ResourceAwareDragAndDropCommand;
 import org.eclipse.epf.library.edit.util.ExposedAdapterFactory;
 import org.eclipse.epf.library.edit.util.TngUtil;
 import org.eclipse.epf.library.edit.validation.DependencyChecker;
 import org.eclipse.epf.uma.Activity;
 import org.eclipse.epf.uma.BreakdownElement;
-import org.eclipse.epf.uma.CapabilityPattern;
-import org.eclipse.epf.uma.DeliveryProcess;
 import org.eclipse.epf.uma.Process;
 import org.eclipse.epf.uma.ProcessComponent;
 import org.eclipse.jface.viewers.IContentProvider;
@@ -48,8 +45,7 @@
  * @author Shilpa Toraskar
  * @since 1.0
  */
-public abstract class BSDragAndDropCommand extends DragAndDropCommand implements
-		IResourceAwareCommand {
+public abstract class BSDragAndDropCommand extends ResourceAwareDragAndDropCommand {
 
 	/**
 	 * @param domain
@@ -154,17 +150,6 @@
 		return null;
 	}
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see com.ibm.library.edit.command.IResourceAwareCommand#getModifiedResources()
-	 */
-	public Collection getModifiedResources() {
-		if (dropCommand instanceof IResourceAwareCommand) {
-			return ((IResourceAwareCommand) dropCommand).getModifiedResources();
-		}
-		return Collections.EMPTY_LIST;
-	}
 	
 	/* (non-Javadoc)
 	 * @see org.eclipse.emf.edit.command.DragAndDropCommand#getAffectedObjects()
diff --git a/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/util/TngUtil.java b/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/util/TngUtil.java
index 051d730..3ced84a 100755
--- a/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/util/TngUtil.java
+++ b/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/util/TngUtil.java
@@ -21,6 +21,7 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -33,6 +34,7 @@
 import org.eclipse.core.runtime.Status;
 import org.eclipse.emf.common.command.Command;
 import org.eclipse.emf.common.command.CommandWrapper;
+import org.eclipse.emf.common.command.CompoundCommand;
 import org.eclipse.emf.common.notify.Adapter;
 import org.eclipse.emf.common.notify.AdapterFactory;
 import org.eclipse.emf.common.notify.Notification;
@@ -75,6 +77,7 @@
 import org.eclipse.epf.library.edit.PresentationContext;
 import org.eclipse.epf.library.edit.TngAdapterFactory;
 import org.eclipse.epf.library.edit.command.IActionManager;
+import org.eclipse.epf.library.edit.command.IResourceAwareCommand;
 import org.eclipse.epf.library.edit.element.ContentPackageItemProvider;
 import org.eclipse.epf.library.edit.process.BreakdownElementWrapperItemProvider;
 import org.eclipse.epf.library.edit.process.IBSItemProvider;
@@ -2397,6 +2400,34 @@
 		}
 		return owner;
 	}
+	
+	public static Set<Resource> getModifiedResources(Command cmd) {
+		Set<Resource> modifiedResources = new HashSet<Resource>();
+		collectModifiedResources(cmd, modifiedResources);
+		return modifiedResources;
+	}
+	
+	public static void collectModifiedResources(Command command, Set<Resource> modifiedResources) {
+		if (command instanceof IResourceAwareCommand) {
+			modifiedResources.addAll(((IResourceAwareCommand) command)
+					.getModifiedResources());
+		} 
+		else if(command instanceof CompoundCommand){
+			List commandList = ((CompoundCommand)command).getCommandList();
+			for (Iterator iter = commandList.iterator(); iter.hasNext();) {
+				collectModifiedResources((Command) iter.next(), modifiedResources);				
+			}
+		}
+		else {
+			EObject modified = TngUtil.getOwner(command);
+			if(modified != null) {
+				Resource resource = modified.eResource();
+				if(resource != null) {
+					modifiedResources.add(resource);
+				}
+			}
+		}
+	}
 
 	public static List convertGuidanceAttachmentsToList(String attachmentString) {
 		ArrayList attachments = new ArrayList();