//This enables us to get children ICompositeViews from WorkflowViewElements. //Eg. get the WorkflowItemsPresenter from SequenceDesigner. //This is useful for Cut-Copy-Paste, Delete handling, etc. internal static void RegisterWithParentViewElement(ICompositeView container) { WorkflowViewElement parent = GetParentViewElement(container); if (parent != null) { CutCopyPasteHelper.AddChildContainer(parent, container); } }
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 DoCut(EditingContext context) { if (context == null) { throw FxTrace.Exception.AsError(new ArgumentNullException("context")); } Selection currentSelection = context.Items.GetValue <Selection>(); List <ModelItem> modelItemsToCut = new List <ModelItem>(currentSelection.SelectedObjects); CutCopyPasteHelper.DoCut(modelItemsToCut, context); }
public void OnItemsPasted(List <object> itemsToPaste, List <object> metaData, Point pastePoint, WorkflowViewElement pastePointReference) { // first see if a spacer is selected. int index = this.selectedSpacerIndex; // else see if we can paste after a selected child if (index < 0) { Selection currentSelection = this.Context.Items.GetValue <Selection>(); index = this.Items.IndexOf(currentSelection.PrimarySelection); //paste after the selected child if (index >= 0) { index++; } } if (index < 0) { index = addAtEndMarker; } IList <object> mergedItemsToPaste = CutCopyPasteHelper.SortFromMetaData(itemsToPaste, metaData); List <ModelItem> modelItemsToSelect = new List <ModelItem>(); foreach (object itemToPaste in mergedItemsToPaste) { if (IsDropAllowed(itemToPaste)) { if (index == addAtEndMarker) { modelItemsToSelect.Add(this.Items.Add(itemToPaste)); } else { modelItemsToSelect.Add(this.Items.Insert(index, itemToPaste)); } if (index >= 0) { index++; } } } this.Dispatcher.BeginInvoke( new Action(() => { this.Context.Items.SetValue(new Selection(modelItemsToSelect)); }), Windows.Threading.DispatcherPriority.ApplicationIdle, null); }
void ICompositeView.OnItemsPasted(List <object> itemsToPaste, List <object> metaData, Point pastePoint, WorkflowViewElement pastePointReference) { if (itemsToPaste.Count == 1) { // Single Paste UpdateItem(itemsToPaste[0]); } else { // Mutiple Paste. IList <object> sortedList = CutCopyPasteHelper.SortFromMetaData(itemsToPaste, metaData); Fx.Assert(this.Item == null, "multi-paste on item != null is not supported now"); this.DoAutoWrapDrop(InsertionPosition.None, sortedList); } }
// Get rid of descendant model items when both ancestor and descendant and ancestor model items are selected internal static IEnumerable <ModelItem> GetModelItemsToDrag(IEnumerable <ModelItem> modelItems) { HashSet <ModelItem> modelItemsToDrag = new HashSet <ModelItem>(); foreach (ModelItem modelItem in modelItems) { HashSet <ModelItem> parentModelItems = CutCopyPasteHelper.GetSelectableParentModelItems(modelItem); parentModelItems.IntersectWith(modelItems); if (parentModelItems.Count == 0) { modelItemsToDrag.Add(modelItem); } } return(modelItemsToDrag); }
//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); }
void OnItemsChanged(ModelItemCollection oldItemsCollection, ModelItemCollection newItemsCollection) { if (oldItemsCollection != null) { oldItemsCollection.CollectionChanged -= this.OnCollectionChanged; } if (newItemsCollection != null) { newItemsCollection.CollectionChanged += this.OnCollectionChanged; } if (!isRegisteredWithParent) { CutCopyPasteHelper.RegisterWithParentViewElement(this); isRegisteredWithParent = true; } populateOnLoad = false; PopulateContent(); }
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); } } }
protected override void OnRender(DrawingContext drawingContext) { CutCopyPasteHelper.RegisterWithParentViewElement(this); base.OnRender(drawingContext); }