private PlacementOperation(DesignItem[] items, PlacementType type) { List <DesignItem> moveableItems; this.currentContainerBehavior = GetPlacementBehavior(items, out moveableItems, type); PlacementInformation[] information = new PlacementInformation[moveableItems.Count]; for (int i = 0; i < information.Length; i++) { information[i] = new PlacementInformation(moveableItems[i], this); } this.placedItems = new ReadOnlyCollection <PlacementInformation>(information); this.type = type; this.currentContainer = moveableItems[0].Parent; this.changeGroup = moveableItems[0].Context.OpenGroup(type.ToString(), moveableItems); }
/// <summary> /// Starts a new placement operation that changes the placement of <paramref name="placedItems"/>. /// </summary> /// <param name="placedItems">The items to be placed.</param> /// <param name="type">The type of the placement.</param> /// <returns>A PlacementOperation object.</returns> /// <remarks> /// You MUST call either <see cref="Abort"/> or <see cref="Commit"/> on the returned PlacementOperation /// once you are done with it, otherwise a ChangeGroup will be left open and Undo/Redo will fail to work! /// </remarks> public static PlacementOperation Start(ICollection <DesignItem> placedItems, PlacementType type) { if (placedItems == null) { throw new ArgumentNullException("placedItems"); } if (type == null) { throw new ArgumentNullException("type"); } DesignItem[] items = placedItems.ToArray(); if (items.Length == 0) { throw new ArgumentException("placedItems.Length must be > 0"); } PlacementOperation op = new PlacementOperation(items, type); try { if (op.currentContainerBehavior == null) { throw new PlacementOperationException("Starting the operation is not supported"); } op.currentContainerBehavior.BeginPlacement(op); foreach (PlacementInformation info in op.placedItems) { info.OriginalBounds = op.currentContainerBehavior.GetPosition(op, info.Item); info.Bounds = info.OriginalBounds; } } catch (Exception ex) { Debug.WriteLine(ex.ToString()); op.changeGroup.Abort(); throw; } return(op); }
/// <summary> /// Try to insert new components into the container. /// </summary> /// <param name="container">The container that should become the parent of the components.</param> /// <param name="placedItems">The components to add to the container.</param> /// <param name="positions">The rectangle specifying the position the element should get.</param> /// <param name="type">The type </param> /// <returns>The operation that inserts the new components, or null if inserting is not possible.</returns> public static PlacementOperation TryStartInsertNewComponents(DesignItem container, IList <DesignItem> placedItems, IList <Rect> positions, PlacementType type) { if (container == null) { throw new ArgumentNullException("container"); } if (placedItems == null) { throw new ArgumentNullException("placedItems"); } if (positions == null) { throw new ArgumentNullException("positions"); } if (type == null) { throw new ArgumentNullException("type"); } if (placedItems.Count == 0) { throw new ArgumentException("placedItems.Count must be > 0"); } if (placedItems.Count != positions.Count) { throw new ArgumentException("positions.Count must be = placedItems.Count"); } DesignItem[] items = placedItems.ToArray(); PlacementOperation op = new PlacementOperation(items, type); try { for (int i = 0; i < items.Length; i++) { op.placedItems[i].OriginalBounds = op.placedItems[i].Bounds = positions[i]; } op.currentContainer = container; op.currentContainerBehavior = container.GetBehavior <IPlacementBehavior>(); if (op.currentContainerBehavior == null || !op.currentContainerBehavior.CanEnterContainer(op, true)) { op.changeGroup.Abort(); return(null); } op.currentContainerBehavior.EnterContainer(op); } catch (Exception ex) { Debug.WriteLine(ex.ToString()); op.changeGroup.Abort(); throw; } return(op); }
/// <summary> /// Gets the placement behavior associated with the specified items. /// </summary> public static IPlacementBehavior GetPlacementBehavior(ICollection <DesignItem> items, out List <DesignItem> moveableItems, PlacementType placementType) { moveableItems = new List <DesignItem>(); if (items == null) { throw new ArgumentNullException("items"); } if (items.Count == 0) { return(null); } var possibleItems = items; if (!items.Any(x => x.Parent == null)) { var itemsPartentGroup = items.GroupBy(x => x.Parent); var parents = itemsPartentGroup.Select(x => x.Key).OrderBy(x => x.DepthLevel).First(); possibleItems = itemsPartentGroup.Where(x => x.Key.DepthLevel == parents.DepthLevel) .SelectMany(x => x) .ToList(); } var first = possibleItems.First(); DesignItem parent = first.Parent; moveableItems.Add(first); foreach (DesignItem item in possibleItems.Skip(1)) { if (item.Parent != parent) { if (placementType != PlacementType.MoveAndIgnoreOtherContainers) { return(null); } } else { moveableItems.Add(item); } } if (parent != null) { return(parent.GetBehavior <IPlacementBehavior>()); } else if (possibleItems.Count == 1) { return(first.GetBehavior <IRootPlacementBehavior>()); } else { return(null); } }