private bool AllowDropOnSpacer(DragEventArgs e) { return(this.wfItemPresenter.Item != null && !this.IsOwnerActivityBeingDragged(e) && DragDropHelper.AllowDrop(typeof(Sequence), this.wfItemPresenter.AllowedItemType) && // Is Sequence allowed to be dropped inside the WIP? Beause it will trigger AutoWrap. DragDropHelper.AllowDrop(e.Data, this.wfItemPresenter.Context, typeof(Activity))); // Is the item being dragged allowed to be dropped onto Sequence? }
void UpdateEffects(DragEventArgs args) { if (!DragDropHelper.AllowDrop(args.Data, this.Context, this.AllowedItemType)) { args.Effects = DragDropEffects.None; } }
private void CheckListConsistentAndThrow(List <ModelItem> src, List <ModelItem> copied) { bool valid = DragDropHelper.AreListsIdenticalExceptOrder(src, copied); if (!valid) { throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Error_BadOutputFromSortSelectedItems)); } }
static ICompositeView GetContainerForPaste(ModelItem pasteModelItem, Point clickPoint) { ICompositeView pasteContainer = null; if (null != pasteModelItem && null != pasteModelItem.View && pasteModelItem.View is WorkflowViewElement) { pasteContainer = ((WorkflowViewElement)pasteModelItem.View).ActiveCompositeView; } if (null == pasteContainer) { //Get clicked container. if (clickPoint.X > 0 && clickPoint.Y > 0) { pasteContainer = GetClickedContainer(pasteModelItem, clickPoint); } //If the container itself is a WVE, there's posibility that it's collapsed. //Thus, we need to check this as well. if (pasteContainer != null && pasteContainer is WorkflowViewElement) { WorkflowViewElement view = pasteContainer as WorkflowViewElement; if (!view.ShowExpanded) { pasteContainer = null; } } else if (pasteContainer == null) //If the modelitem.View itself is a container. { WorkflowViewElement view = pasteModelItem.View as WorkflowViewElement; if (view != null && view.ShowExpanded) { pasteContainer = pasteModelItem.View as ICompositeView; } } //Get the container registered with modelItem.View if unambigous //If nothing works take the container with keyboard focus if one exists. if (pasteContainer == null) { HashSet <ICompositeView> childrenContainers = CutCopyPasteHelper.GetChildContainers(pasteModelItem.View as WorkflowViewElement); if ((childrenContainers == null || childrenContainers.Count == 0) && null != pasteModelItem.View) { pasteContainer = (ICompositeView)DragDropHelper.GetCompositeView((WorkflowViewElement)pasteModelItem.View); } else if (null != childrenContainers && childrenContainers.Count == 1) { pasteContainer = new List <ICompositeView>(childrenContainers)[0]; } else { pasteContainer = Keyboard.FocusedElement as ICompositeView; } } } return(pasteContainer); }
public static void Delete(EditingContext context) { if (context == null) { throw FxTrace.Exception.AsError(new ArgumentNullException("context")); } Selection selection = context.Items.GetValue <Selection>(); if (null != selection) { bool selectRoot = false; DesignerView designerView = context.Services.GetService <DesignerView>(); var toDelete = selection.SelectedObjects.Where(p => null != p.View && p.View is WorkflowViewElement && !p.View.Equals(designerView.RootDesigner)); if (toDelete.Count() > 0) { using (EditingScope es = (EditingScope)toDelete.FirstOrDefault().BeginEdit(SR.DeleteOperationEditingScopeDescription)) { Dictionary <ICompositeView, List <ModelItem> > containerToModelItemsDict = new Dictionary <ICompositeView, List <ModelItem> >(); List <ModelItem> modelItemsPerContainer; foreach (var item in toDelete) { ICompositeView container = (ICompositeView)DragDropHelper.GetCompositeView((WorkflowViewElement)item.View); if (null != container) { if (!containerToModelItemsDict.TryGetValue(container, out modelItemsPerContainer)) { modelItemsPerContainer = new List <ModelItem>(); containerToModelItemsDict.Add(container, modelItemsPerContainer); } modelItemsPerContainer.Add(item); } } foreach (ICompositeView container in containerToModelItemsDict.Keys) { container.OnItemsDelete(containerToModelItemsDict[container]); selectRoot = true; } if (selectRoot) { DesignerView view = context.Services.GetService <DesignerView>(); if (null != view) { WorkflowViewElement rootView = view.RootDesigner as WorkflowViewElement; if (rootView != null) { Selection.SelectOnly(context, rootView.ModelItem); } } } es.Complete(); } } } }
public void OnItemsMoved(List <ModelItem> movedItems) { if (movedItems == null) { throw FxTrace.Exception.ArgumentNull("movedItems"); } DragDropHelper.ValidateItemsAreOnView(movedItems, this.Items); this.OnItemsDelete(movedItems); }
void OnDrag(DragEventArgs e) { if (!e.Handled) { if (!DragDropHelper.AllowDrop(e.Data, this.Context, this.AllowedItemType)) { e.Effects = DragDropEffects.None; } e.Handled = true; } }
private Point GetRelativeLocation(IEnumerable <WorkflowViewElement> draggedViews) { HashSet <WorkflowViewElement> viewElements = new HashSet <WorkflowViewElement>(draggedViews); if (!viewElements.Contains(this)) { viewElements.Add(this); } Dictionary <WorkflowViewElement, Point> locations = DragDropHelper.GetViewElementRelativeLocations(viewElements); return(locations[this]); }
// 1) obj with CompositeView2: sort by IMultipleDragEnabledCompositeView SortSelectedItems. // 2) obj with CompoisteView: no sort. // 3) obj without CompositeView: just put them at the end of the list as the order in selectedObjects. internal static List <object> SortSelectedObjects(IEnumerable <object> selectedObjects) { //1) Separate objects Dictionary <ICompositeView, List <ModelItem> > viewItemListDictionary = new Dictionary <ICompositeView, List <ModelItem> >(); List <object> nonCompositeView = new List <object>(); List <object> retList = new List <object>(); foreach (object obj in selectedObjects) { ModelItem modelItem = obj as ModelItem; if (modelItem == null || modelItem.View == null) { nonCompositeView.Add(obj); continue; } ICompositeView container = DragDropHelper .GetCompositeView(modelItem.View as WorkflowViewElement) as ICompositeView; if (container == null) { nonCompositeView.Add(obj); continue; } // add to dictionary. if (!viewItemListDictionary.ContainsKey(container)) { viewItemListDictionary.Add(container, new List <ModelItem>()); } viewItemListDictionary[container].Add(modelItem); } // 2) sort when possible foreach (KeyValuePair <ICompositeView, List <ModelItem> > pair in viewItemListDictionary) { IMultipleDragEnabledCompositeView view2 = pair.Key as IMultipleDragEnabledCompositeView; List <ModelItem> sortedList = view2 == null ? pair.Value : view2.SortSelectedItems(new List <ModelItem>(pair.Value)); if (!AreListsIdenticalExceptOrder(pair.Value, sortedList)) { // check consistens. throw FxTrace.Exception.AsError( new InvalidOperationException(SR.Error_BadOutputFromSortSelectedItems)); } retList.AddRange(sortedList); } retList.AddRange(nonCompositeView); return(retList); }
//This is more efficient than walking up the VisualTree looking for WorkflowViewElements. //Assuming that Cut-Copy will always be against selected elements. //This implies that only elements under the BreadCrumbRoot can be cut/copied. static List <WorkflowViewElement> GetSelectableParentViewElements(WorkflowViewElement childElement) { List <WorkflowViewElement> parentViewElements = new List <WorkflowViewElement>(); if (childElement != null) { UIElement breadcrumbRoot = childElement.Context.Services.GetService <DesignerView>().RootDesigner; ICompositeView container = (ICompositeView)DragDropHelper.GetCompositeView(childElement); while (!childElement.Equals(breadcrumbRoot) && container != null) { childElement = CutCopyPasteHelper.GetParentViewElement(container); Fx.Assert(childElement != null, "container should be present in a WorkflowViewElement"); parentViewElements.Add(childElement); container = (ICompositeView)DragDropHelper.GetCompositeView(childElement); } } return(parentViewElements); }
bool AllowDragging() { Selection selection = this.Context.Items.GetValue <Selection>(); if (!this.DraggingMultipleItemsEnabled) { if (selection.SelectionCount != 1) { return(false); } } return(selection.SelectedObjects.All <ModelItem>((p) => { return p != null && p != p.Root && p.View != null && ((WorkflowViewElement)p.View).IsVisible && (DragDropHelper.GetCompositeView((WorkflowViewElement)p.View) as ICompositeView) != null; })); }
private List <WorkflowViewElement> ObjectList2WorkflowViewElementList(IEnumerable <object> droppedObjects) { List <WorkflowViewElement> movedViewElements = new List <WorkflowViewElement>(); foreach (object droppedObject in droppedObjects) { if (droppedObject is ModelItem && ((ModelItem)droppedObject).View != null) { WorkflowViewElement view = (WorkflowViewElement)((ModelItem)droppedObject).View; WorkflowItemPresenter container = DragDropHelper.GetCompositeView(view) as WorkflowItemPresenter; if (container != this) { movedViewElements.Add(view); } } } return(movedViewElements); }
bool DoSingleDrop(object droppedObject, DragEventArgs args) { if (UpdateItem(droppedObject)) { args.Handled = true; #pragma warning disable 618 DragDropHelper.SetDragDropCompletedEffects(args, DragDropEffects.Move); #pragma warning restore 618 if (droppedObject is ModelItem && ((ModelItem)droppedObject).View != null) { DragDropHelper.SetDragDropMovedViewElements(args, new WorkflowViewElement[] { ((ModelItem)droppedObject).View as WorkflowViewElement }); } return(true); } return(false); }
private bool IsOwnerActivityBeingDragged(DragEventArgs e) { if (this.wfItemPresenter.Item == null) { return(false); } else { // In case of a toolbox drop, DragDropHelper.GetObjectsToBeDropped // will create an instance, which will possibliy pop up a type picker // dialog for generic activities. So check for it first and avoid // pop up dialogs. if (DragDropHelper.IsDraggingFromToolbox(e)) { return(false); } IEnumerable <ModelItem> draggedObjects = DragDropHelper.GetDraggedModelItems(e); return(draggedObjects.Contains(this.wfItemPresenter.Item)); } }
protected override void OnDrop(DragEventArgs e) { ModelTreeManager manager = this.Context.Services.GetService <ModelTreeManager>(); // When dragging from toolbox: // editingScope should not be null // there should only be one item // When dragging from canvas: // editingScope should be null // Call editingScope.Complete() to commit changes, otherwise the editing scope will be aborted using (EditingScope editingScope = ModelItemHelper.TryCreateImmediateEditingScope(manager, SR.PropertyChangeEditingScopeDescription)) { List <object> droppedObjects = this.GetSortedObjectList(e); #pragma warning disable 618 DragDropHelper.SetDragDropCompletedEffects(e, DragDropEffects.None); #pragma warning restore 618 if (droppedObjects == null || droppedObjects.Count == 0) { return; } if (droppedObjects.Count == 1) { if (this.DoSingleDrop(droppedObjects[0], e)) { if (editingScope != null) { editingScope.Complete(); } } return; } else { // multi drop Fx.Assert(editingScope == null, "editingScope should be null for dragging from canvas."); this.DoAutoWrapDrop(InsertionPosition.None, e, droppedObjects); } base.OnDrop(e); } }
public ViewElementDragShadow(UIElement owner, IEnumerable <WorkflowViewElement> viewElements, Point offset, double scaleFactor) : base(owner) { Dictionary <WorkflowViewElement, Point> locations = DragDropHelper.GetViewElementRelativeLocations(viewElements); Grid grid = new Grid(); foreach (WorkflowViewElement viewElement in viewElements) { Rect bounds = VisualTreeHelper.GetDescendantBounds(viewElement); Rectangle rectangle = new Rectangle() { Width = bounds.Width, Height = bounds.Height, Fill = new VisualBrush(viewElement), Margin = new Thickness(locations[viewElement].X, locations[viewElement].Y, 0, 0), VerticalAlignment = VerticalAlignment.Top, HorizontalAlignment = HorizontalAlignment.Left }; grid.Children.Add(rectangle); } grid.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); this.width = grid.DesiredSize.Width; this.height = grid.DesiredSize.Height; this.content = new Rectangle() { Width = this.width, Height = this.height, Fill = new VisualBrush(grid) { Opacity = 0.6 } }; this.InitializeCommon(offset, scaleFactor); }
void StartDragging() { try { using (ModelEditingScope editingScope = this.ModelItem.BeginEdit(SR.MoveEditingScopeDescription, true)) { HashSet <WorkflowViewElement> draggedViews = new HashSet <WorkflowViewElement>(); Dictionary <ModelItem, ICompositeView> sourceContainers = new Dictionary <ModelItem, ICompositeView>(); HashSet <ICompositeView> compViewSet = new HashSet <ICompositeView>(); Selection selection = this.Context.Items.GetValue <Selection>(); IEnumerable <ModelItem> selectedObjects = selection.SelectedObjects; IEnumerable <ModelItem> modelItemsToDrag = DragDropHelper.GetModelItemsToDrag(selectedObjects); // Save the source containers for the dragged items foreach (ModelItem modelItem in modelItemsToDrag) { WorkflowViewElement view = (WorkflowViewElement)modelItem.View; draggedViews.Add(view); ICompositeView container = DragDropHelper.GetCompositeView(view) as ICompositeView; sourceContainers.Add(modelItem, container); // If Add returns true => the container is added the first time, which is always ok // If Add returns false => the container is added more than once // it must be a IMultipleDragEnabledCompositeView, otherwise, return, because // we don't support dragging from ICompositeView. if (!compViewSet.Add(container) && !(container is IMultipleDragEnabledCompositeView)) { return; } } // Calculate the anchor point for the dragged items Point relativeLocation = GetRelativeLocation(draggedViews); Point referencePoint = this.lastMouseDownPoint; referencePoint.Offset(relativeLocation.X, relativeLocation.Y); DataObject dataObject = DragDropHelper.DoDragMoveImpl(draggedViews, referencePoint); IEnumerable <WorkflowViewElement> movedViewElements = DragDropHelper.GetDragDropMovedViewElements(dataObject); // once drag drop is done make sure the CompositeView is notified of the change in data if (movedViewElements != null) { Dictionary <ICompositeView, List <ModelItem> > containerMovedModelItemList = new Dictionary <ICompositeView, List <ModelItem> >(); // Create containerMovedModelItemList foreach (WorkflowViewElement view in movedViewElements) { ICompositeView compView = DragDropHelper.GetCompositeView(view) as ICompositeView; Fx.Assert(compView != null, "not an ICompositeView"); if (!containerMovedModelItemList.ContainsKey(compView)) { containerMovedModelItemList.Add(compView, new List <ModelItem>()); } containerMovedModelItemList[compView].Add(view.ModelItem); } // Call OnItemsMoved to notify the source container. foreach (KeyValuePair <ICompositeView, List <ModelItem> > pair in containerMovedModelItemList) { if (pair.Key is IMultipleDragEnabledCompositeView) { ((IMultipleDragEnabledCompositeView)pair.Key).OnItemsMoved(pair.Value); } else { if (pair.Value.Count >= 2) { throw FxTrace.Exception.AsError( new InvalidOperationException(SR.Error_MovingMoreThanOneItemsFromICompositeView)); } pair.Key.OnItemMoved(pair.Value[0]); } } // animation foreach (WorkflowViewElement view in movedViewElements) { BeginDropAnimation(view); } } // the drop target is using old DragDropHelper API and did not set the moved view elements else { DragDropEffects executedDragDropEffect = DragDropHelper.GetDragDropCompletedEffects(dataObject); if (executedDragDropEffect == DragDropEffects.Move) { if (modelItemsToDrag.Count() == 1) { ModelItem movedItem = modelItemsToDrag.First <ModelItem>(); sourceContainers[movedItem].OnItemMoved(movedItem); BeginDropAnimation((WorkflowViewElement)movedItem.View); } else { throw FxTrace.Exception.AsError(new InvalidOperationException(SR.DraggingMulitpleItemsError)); } } } editingScope.Complete(); bool dropHappened = movedViewElements != null || DragDropHelper.GetDragDropCompletedEffects(dataObject) == DragDropEffects.Move; if (dropHappened) { // add the selected objects back into selection. this.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, (Action)(() => { foreach (ModelItem item in selectedObjects) { // We need only the first one IInputElement viewToFocus = item == null ? null : item.View as IInputElement; if (viewToFocus != null) { Keyboard.Focus(viewToFocus); break; } } this.Context.Items.SetValue(new Selection(selectedObjects)); })); } } } catch (Exception e) { ErrorReporting.ShowErrorMessage(e.Message); } }
static void CutCopyOperation(List <ModelItem> modelItemsToCutCopy, EditingContext context, bool isCutOperation) { List <object> objectsOnClipboard = null; List <object> metaData = null; if (modelItemsToCutCopy.Count > 0) { objectsOnClipboard = new List <object>(modelItemsToCutCopy.Count); metaData = new List <object>(); Dictionary <ICompositeView, List <ModelItem> > notifyDictionary = new Dictionary <ICompositeView, List <ModelItem> >(); UIElement breadCrumbRootView = ((DesignerView)context.Services.GetService <DesignerView>()).RootDesigner; foreach (ModelItem modelItem in modelItemsToCutCopy) { object currentElement = modelItem.GetCurrentValue(); if (typeof(Activity).IsAssignableFrom(currentElement.GetType())) { string fileName; if (AttachablePropertyServices.TryGetProperty(currentElement, XamlDebuggerXmlReader.FileNameName, out fileName)) { AttachablePropertyServices.RemoveProperty(currentElement, XamlDebuggerXmlReader.FileNameName); } } if (modelItem.View != null) { //The case where the breadcrumbroot designer is Cut/Copied. We do not delete the root designer, we only copy it. if (breadCrumbRootView.Equals(modelItem.View)) { notifyDictionary.Clear(); objectsOnClipboard.Add(modelItem.GetCurrentValue()); break; } else { ICompositeView container = (ICompositeView)DragDropHelper.GetCompositeView((WorkflowViewElement)modelItem.View); if (container != null) { //If the parent and some of its children are selected and cut/copied, we ignore the children. //The entire parent will be cut/copied. //HashSet parentModelItems contains all the model items in the parent chain of current modelItem. //We use HashSet.IntersectWith operation to determine if one of the parents is set to be cut. HashSet <ModelItem> parentModelItems = CutCopyPasteHelper.GetSelectableParentModelItems(modelItem); parentModelItems.IntersectWith(modelItemsToCutCopy); if (parentModelItems.Count == 0) { if (!notifyDictionary.ContainsKey(container)) { notifyDictionary[container] = new List <ModelItem>(); } notifyDictionary[container].Add(modelItem); } } } } } foreach (ICompositeView container in notifyDictionary.Keys) { object containerMetaData = false; if (isCutOperation) { containerMetaData = container.OnItemsCut(notifyDictionary[container]); } else { containerMetaData = container.OnItemsCopied(notifyDictionary[container]); } if (containerMetaData != null) { metaData.Add(containerMetaData); } //Put the actual activities and not the modelItems in the clipboard. foreach (ModelItem modelItem in notifyDictionary[container]) { objectsOnClipboard.Add(modelItem.GetCurrentValue()); } } if (metaData.Count == 0) { metaData = null; } } try { FrameworkName targetFramework = context.Services.GetService <DesignerConfigurationService>().TargetFrameworkName; PutOnClipBoard(objectsOnClipboard, metaData, targetFramework); } catch (XamlObjectReaderException exception) { if (modelItemsToCutCopy.Count > 0 && ErrorActivity.GetHasErrorActivities(modelItemsToCutCopy[0].Root.GetCurrentValue())) { ErrorReporting.ShowErrorMessage(SR.CutCopyErrorActivityMessage); } else { ErrorReporting.ShowErrorMessage(exception.Message); } } }
bool DoAutoWrapDrop(InsertionPosition insertionPos, DragEventArgs e, IList <object> droppedObjects = null) { if (droppedObjects == null) { ModelTreeManager manager = this.Context.Services.GetRequiredService <ModelTreeManager>(); EditingScope editingScope = null; try { editingScope = ModelItemHelper.TryCreateImmediateEditingScope(manager, SR.WrapInSequenceDescription); droppedObjects = this.GetSortedObjectList(e); if (!this.DoAutoWrapDrop(insertionPos, droppedObjects)) { return(false); } if (editingScope != null) { editingScope.Complete(); } } finally { if (editingScope != null) { editingScope.Dispose(); editingScope = null; } } } else { if (!this.DoAutoWrapDrop(insertionPos, droppedObjects)) { return(false); } } if (!DragDropHelper.IsDraggingFromToolbox(e)) { List <WorkflowViewElement> movedViewElements = ObjectList2WorkflowViewElementList(droppedObjects); DragDropHelper.SetDragDropMovedViewElements(e, movedViewElements); //Backward compatibility for 4.0 if (droppedObjects.Count == 1 && movedViewElements.Count == 1) { #pragma warning disable 618 DragDropHelper.SetDragDropCompletedEffects(e, DragDropEffects.Move); #pragma warning restore 618 } } else { Fx.Assert(droppedObjects.Count == 1, "Dropping from Toolbox with count != 1"); // Set focus if it is dropping from ToolBox. // In common drag/drop, the selection setting is done at the end of // StartDragging(). if (this.Item == null) { return(true); } Fx.Assert(typeof(Sequence).IsAssignableFrom(this.Item.ItemType), "Auto Wrap didn't add a sequence. Is Item.Properties[\"Activities\"] still correct?"); foreach (ModelItem item in this.Item.Properties["Activities"].Collection) { // Find the ModelItem whose value is an activity from Toolbox. if (item.GetCurrentValue() == droppedObjects[0]) { this.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, (Action)(() => { item.Focus(); })); break; } } } return(true); }
List <object> GetSortedObjectList(DragEventArgs args) { IEnumerable <object> droppedObjects = DragDropHelper.GetDroppedObjects(this, args, this.context); return(DragDropHelper.SortSelectedObjects(droppedObjects)); }
void OnItemsDropped(DragEventArgs e, int index) { ModelItemHelper.TryCreateImmediateEditingScopeAndExecute(this.Items.GetEditingContext(), System.Activities.Presentation.SR.CollectionAddEditingScopeDescription, (es) => { DragDropHelper.SetDragDropCompletedEffects(e, DragDropEffects.None); List <object> droppedObjects = new List <object>(DragDropHelper.GetDroppedObjects(this, e, Context)); List <WorkflowViewElement> movedViewElements = new List <WorkflowViewElement>(); List <object> externalMoveList = new List <object>(); List <ModelItem> internalMoveList = new List <ModelItem>(); // Step 1: Sort the list List <object> sortedDroppingList = DragDropHelper.SortSelectedObjects(droppedObjects); // Step 2: Categorize dropped objects by their source container. foreach (object droppedObject in sortedDroppingList) { ModelItem modelItem = droppedObject as ModelItem; WorkflowViewElement view = (modelItem == null) ? null : (modelItem.View as WorkflowViewElement); if (view == null) { externalMoveList.Add(droppedObject); continue; } UIElement container = DragDropHelper.GetCompositeView(view); if (container == this) { internalMoveList.Add(modelItem); continue; } movedViewElements.Add(view); externalMoveList.Add(droppedObject); } // Step 3: Internal movement if (this.ShouldMoveItems(internalMoveList, index)) { foreach (ModelItem modelItem in internalMoveList) { int oldIndex = this.Items.IndexOf(modelItem); this.Items.Remove(modelItem); //if element is placed ahead of old location, decrement the index not to include moved object if (oldIndex < index) { this.InsertItem(index - 1, modelItem); } else { this.InsertItem(index, modelItem); index++; } } } // Step 4: External move and drop from toolbox foreach (object droppedObject in externalMoveList) { if (!this.IsDropAllowed(droppedObject)) { continue; } this.InsertItem(index++, droppedObject); DragDropHelper.SetDragDropCompletedEffects(e, DragDropEffects.Move); } DragDropHelper.SetDragDropMovedViewElements(e, movedViewElements); e.Handled = true; if (es != null) { es.Complete(); } }); }