Exemplo n.º 1
0
        // FIXME: consider using the cut/paste mechanism for moving entities
        protected virtual void MoveChildren([NotNull] IReadOnlyCollection <object> children, int index)
        {
            if (children.Count == 0)
            {
                return;
            }

            var moved = false;

            // Save the selection to restore it after the operation
            var selection = Editor.SelectedContent.ToList();

            // Clear the selection
            Editor.ClearSelection();

            using (var transaction = Editor.UndoRedoService.CreateTransaction())
            {
                foreach (var child in children)
                {
                    if (child is UIElementViewModel element)
                    {
                        // Some of the elements we're moving might already be children of this object, let's count for their removal in the insertion index.
                        var elementIndex = Children.IndexOf(element);
                        if (elementIndex >= 0 && elementIndex < index)
                        {
                            --index;
                        }

                        // Hierarchy must be cloned before removing the elements!
                        // Note: if the source asset is different than the current asset, we need to generate new ids.
                        var flags     = element.Asset == Asset ? SubHierarchyCloneFlags.None : SubHierarchyCloneFlags.GenerateNewIdsForIdentifiableObjects;
                        var hierarchy = UIAssetPropertyGraph.CloneSubHierarchies(element.Asset.Session.AssetNodeContainer, element.Asset.Asset, element.Id.ObjectId.Yield(), flags, out Dictionary <Guid, Guid> idRemapping);
                        // Remove from previous asset
                        element.Asset.AssetHierarchyPropertyGraph.RemovePartFromAsset(element.UIElementDesign);
                        // Get the id of the new element
                        if (!idRemapping.TryGetValue(element.Id.ObjectId, out Guid partId))
                        {
                            partId = element.Id.ObjectId;
                        }
                        // Insert it in the new parent, or as root if the new parent is null.
                        Asset.AssetHierarchyPropertyGraph.AddPartToAsset(hierarchy.Parts, hierarchy.Parts[partId], (this as UIElementViewModel)?.AssetSideUIElement, index++);
                        moved = true;
                        continue;
                    }
                    if (child is IUIElementFactory factory)
                    {
                        var childHierarchy = factory.Create(UIAsset);
                        Asset.AssetHierarchyPropertyGraph.AddPartToAsset(childHierarchy.Parts, childHierarchy.Parts[childHierarchy.RootParts.Single().Id], (this as UIElementViewModel)?.AssetSideUIElement, index++);
                    }
                }
                Editor.UndoRedoService.SetName(transaction, $"{(moved ? "Move" : "Add")} {children.Count} element{(children.Count > 1 ? "s" : string.Empty)} to {GetDropLocationName()}");
            }

            // Fixup selection since adding/inserting may create new viewmodels
            Editor.FixupAndRestoreSelection(selection, children);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Successively copy the properties from the <paramref name="sourcePanel"/> to the <paramref name="targetPanel"/>, then swap the panels in the parent
        /// and finally move the children from the <paramref name="sourcePanel"/> to the <paramref name="targetPanel"/>.
        /// </summary>
        private void CopySwapExchange([NotNull] PanelViewModel sourcePanel, [NotNull] UIElementDesign targetPanel,
                                      [CanBeNull] Func <IEnumerable <UIElementViewModel>, IEnumerable <UIElementViewModel> > childSorter = null)
        {
            var targetPanelElement = targetPanel.UIElement as Panel;

            if (targetPanelElement == null)
            {
                throw new ArgumentException(@"The target element must be a Panel", nameof(targetPanel));
            }

            // Clone common properties
            CopyCommonProperties(Editor.NodeContainer, sourcePanel.AssetSidePanel, targetPanelElement);

            // Initialize the new hierarchy of elements that starts from the target and contains all the children
            IEnumerable <UIElementViewModel> children = sourcePanel.Children.ToList();
            var hierarchy = UIAssetPropertyGraph.CloneSubHierarchies(Asset.Session.AssetNodeContainer, Asset.Asset, children.Select(c => c.Id.ObjectId), SubHierarchyCloneFlags.None, out _);

            hierarchy.RootParts.Add(targetPanel.UIElement);
            hierarchy.Parts.Add(targetPanel);
            // Remove all children from the source panel.
            foreach (var child in children)
            {
                Asset.AssetHierarchyPropertyGraph.RemovePartFromAsset(child.UIElementDesign);
            }

            // Swap panels in the parent
            var elementParent = Parent as UIElementViewModel;
            var rootParent    = Parent as UIRootViewModel;

            if (rootParent != null)
            {
                // special case of RootElement
                rootParent.ReplaceRootElement(sourcePanel, hierarchy, targetPanelElement.Id);
            }
            else if (elementParent != null)
            {
                // Remove current panel from Parent
                var index = elementParent.Children.IndexOf(sourcePanel);
                Asset.AssetHierarchyPropertyGraph.RemovePartFromAsset(sourcePanel.UIElementDesign);
                Asset.AssetHierarchyPropertyGraph.AddPartToAsset(hierarchy.Parts, targetPanel, elementParent.AssetSideUIElement, index);
            }
            else
            {
                throw new InvalidOperationException();
            }

            // Sort the children list before re-inserting them in the target panel.
            children = childSorter?.Invoke(children) ?? children;

            // Then populate the target panel
            foreach (var child in children)
            {
                Asset.InsertUIElement(hierarchy.Parts, hierarchy.Parts[child.Id.ObjectId], targetPanelElement);
            }
        }
Exemplo n.º 3
0
        private void GroupInto(IUIElementFactory factory)
        {
            var targetPanelType = (factory as UIElementFromSystemLibrary)?.Type;

            if (targetPanelType == null)
            {
                throw new NotSupportedException("Grouping elements into a user library type isn't supported.");
            }
            if (!typeof(Panel).IsAssignableFrom(targetPanelType))
            {
                throw new ArgumentException(@"The target type isn't a panel", nameof(targetPanelType));
            }

            if (SelectedContent.Count == 0)
            {
                return;
            }

            // Ensure that the selected elements are sibling.
            var allParents = SelectedItems.Select(x => x.Parent).OfType <UIHierarchyItemViewModel>().ToList();
            var parent     = allParents[0];

            if (allParents.Any(x => x != parent))
            {
                throw new InvalidOperationException("This operation can only be executed on a selection of sibling elements.");
            }

            using (var transaction = UndoRedoService.CreateTransaction())
            {
                var children = SelectedItems.ToList();
                // Create the new panel into which we'll insert the selection
                var newPanel       = (Panel)Activator.CreateInstance(targetPanelType);
                var newPanelDesign = new UIElementDesign(newPanel);
                // Create a hierarchy containing all children and the panel
                var hierarchy = UIAssetPropertyGraph.CloneSubHierarchies(Asset.Session.AssetNodeContainer, Asset.Asset, children.Select(c => c.Id.ObjectId), SubHierarchyCloneFlags.None, out _);
                hierarchy.RootParts.Add(newPanel);
                hierarchy.Parts.Add(newPanelDesign);
                // Remove all children from their partDesign panel.
                foreach (var child in children)
                {
                    child.Asset.AssetHierarchyPropertyGraph.RemovePartFromAsset(child.UIElementDesign);
                }
                // Add the new panel in place of the selected content.
                parent.Asset.InsertUIElement(hierarchy.Parts, newPanelDesign, (parent as UIElementViewModel)?.AssetSideUIElement);
                // Add the children into the new panel.
                foreach (var child in children)
                {
                    parent.Asset.InsertUIElement(hierarchy.Parts, hierarchy.Parts[child.Id.ObjectId], newPanel);
                }
                UndoRedoService.SetName(transaction, $"Group into {targetPanelType.Name}");
            }
        }
Exemplo n.º 4
0
        public AssetCompositeHierarchyData <UIElementDesign, UIElement> Create(UIAssetBase targetAsset)
        {
            // Create a clone without linking to the library
            var flags           = SubHierarchyCloneFlags.GenerateNewIdsForIdentifiableObjects | SubHierarchyCloneFlags.RemoveOverrides;
            var clonedHierarchy = UIAssetPropertyGraph.CloneSubHierarchies(library.Session.AssetNodeContainer, library.Asset, id.Yield(), flags, out Dictionary <Guid, Guid> _);

            foreach (var part in clonedHierarchy.Parts.Values)
            {
                // Reset name property
                part.UIElement.Name = null;
                part.Base           = null;
            }
            return(clonedHierarchy);
        }
Exemplo n.º 5
0
        private void Ungroup()
        {
            // Move all children of this panel into the parent panel, if available:
            //   - if parent is a root, this action should be ignored
            //   - if parent is ContentControl and this panel has more than one child, this action should be ignored
            if (Parent is UIRootViewModel || (Parent is ContentControlViewModel && Children.Count > 1))
            {
                return;
            }

            var parentElement = (Parent as UIElementViewModel)?.AssetSideUIElement;

            if (parentElement == null)
            {
                return;
            }

            // FIXME: should be similar to "move all children" then "delete previous panel"
            using (var transaction = Editor.UndoRedoService.CreateTransaction())
            {
                var children  = Children.ToList();
                var hierarchy = UIAssetPropertyGraph.CloneSubHierarchies(Asset.Session.AssetNodeContainer, Asset.Asset, children.Select(c => c.Id.ObjectId), SubHierarchyCloneFlags.None, out _);
                // Remove all children from this panel.
                foreach (var child in children)
                {
                    Asset.AssetHierarchyPropertyGraph.RemovePartFromAsset(child.UIElementDesign);
                }
                // Remove the current panel.
                Asset.AssetHierarchyPropertyGraph.RemovePartFromAsset(UIElementDesign);
                // Add the children into the parent panel.
                foreach (var child in children)
                {
                    // TODO: might need smart rules for dependency properties (maybe use the same rules than when changing the layout type)
                    Asset.InsertUIElement(hierarchy.Parts, hierarchy.Parts[child.Id.ObjectId], parentElement);
                }
                Editor.UndoRedoService.SetName(transaction, $"Ungroup {children.Count} elements");
            }
        }