Пример #1
0
        private void PinToNode(object parameters)
        {
            var nodeToPin = DynamoSelection.Instance.Selection
                            .OfType <NodeModel>()
                            .FirstOrDefault();

            if (nodeToPin == null)
            {
                return;
            }

            var nodeGroup = WorkspaceViewModel.Annotations
                            .FirstOrDefault(x => x.AnnotationModel.ContainsModel(nodeToPin));

            if (nodeGroup != null)
            {
                nodeGroup.AnnotationModel.AddToSelectedModels(this.Model);
            }

            Model.PinnedNode = nodeToPin;

            MoveNoteAbovePinnedNode();
            SubscribeToPinnedNode();

            WorkspaceModel.RecordModelsForModification(new List <ModelBase> {
                this.Model
            }, WorkspaceViewModel.Model.UndoRecorder);
            WorkspaceViewModel.HasUnsavedChanges = true;
        }
Пример #2
0
        /// <summary>
        /// Implements the MouseDown event handler for the manipulator
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="mouseButtonEventArgs"></param>
        protected virtual void MouseDown(object sender, MouseButtonEventArgs mouseButtonEventArgs)
        {
            UpdatePosition();
            GizmoInAction = null; //Reset Drag.

            var gizmos = GetGizmos(false);

            if (!Active || !IsEnabled() || null == gizmos || !gizmos.Any())
            {
                return;
            }

            var ray = BackgroundPreviewViewModel.GetClickRay(mouseButtonEventArgs);

            if (ray == null)
            {
                return;
            }

            foreach (var item in gizmos)
            {
                object hitObject;
                if (item.HitTest(ray.GetOriginPoint(), ray.GetDirectionVector(), out hitObject))
                {
                    GizmoInAction = item;
                    var nodes = OnGizmoClick(item, hitObject);
                    if (null != nodes && nodes.Any())
                    {
                        WorkspaceModel.RecordModelsForModification(nodes);
                    }
                    newPosition = GizmoInAction.Origin;
                    return;
                }
            }
        }
Пример #3
0
        public void TestRecordModelsForModificationWithEmptyInput()
        {
            WorkspaceModel workspace = Controller.DynamoViewModel.CurrentSpace;
            Assert.AreEqual(false, workspace.CanUndo);

            // Calling the method with a null argument.
            workspace.RecordModelsForModification(null);
            Assert.AreEqual(false, workspace.CanUndo);

            // Calling the method with an empty list.
            List<ModelBase> models = new List<ModelBase>();
            workspace.RecordModelsForModification(models);
            Assert.AreEqual(false, workspace.CanUndo);

            // Calling the method with a list full of null.
            models.Add(null);
            models.Add(null);
            workspace.RecordModelsForModification(models);
            Assert.AreEqual(false, workspace.CanUndo);
        }
Пример #4
0
        /// <summary>
        /// Implements the MouseDown event handler for the manipulator
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="mouseButtonEventArgs"></param>
        protected virtual void MouseDown(object sender, MouseButtonEventArgs mouseButtonEventArgs)
        {
            if (!IsValidNode)
            {
                return;
            }

            active = UpdatePosition();
            if (Origin != null)
            {
                originBeforeMove = Point.ByCoordinates(Origin.X, Origin.Y, Origin.Z);
                originAfterMove  = Point.ByCoordinates(Origin.X, Origin.Y, Origin.Z);
            }

            GizmoInAction = null; //Reset Drag.

            var gizmos = GetGizmos(false);

            if (!IsEnabled() || null == gizmos || !gizmos.Any())
            {
                return;
            }

            var ray = BackgroundPreviewViewModel.GetClickRay(mouseButtonEventArgs);

            if (ray == null)
            {
                return;
            }

            foreach (var item in gizmos)
            {
                using (var originPt = ray.GetOriginPoint())
                    using (var dirVec = ray.GetDirectionVector())
                    {
                        object hitObject;
                        if (item.HitTest(originPt, dirVec, out hitObject))
                        {
                            GizmoInAction = item;

                            var nodes = OnGizmoClick(item, hitObject).ToList();
                            if (nodes.Any())
                            {
                                WorkspaceModel.RecordModelsForModification(nodes);
                            }
                            return;
                        }
                    }
            }
        }
Пример #5
0
        private void RecordSelectionForUndo()
        {
            // This is where we attempt to store all the models in undo recorder
            // before they are modified (i.e. being dragged around the canvas).
            // Note that we only do this once when the first mouse-move occurs
            // after a mouse-down, because mouse-down can potentially be used
            // just to select a node (as opposed to moving the selected nodes), in
            // which case we don't want any of the nodes to be recorded for undo.
            //
            List <ModelBase> models = DynamoSelection.Instance.Selection.
                                      Where((x) => (x is ModelBase)).Cast <ModelBase>().ToList <ModelBase>();

            WorkspaceModel.RecordModelsForModification(models, Model.UndoRecorder);

            DynamoViewModel.RaiseCanExecuteUndoRedo();
        }
Пример #6
0
        private void DoGraphAutoLayout(object o)
        {
            if (Model.Nodes.Count == 0)
            {
                return;
            }

            var graph  = new GraphLayout.Graph();
            var models = new Dictionary <ModelBase, UndoRedoRecorder.UserAction>();

            foreach (NodeModel x in Model.Nodes)
            {
                graph.AddNode(x.GUID, x.Width, x.Height, x.Y);
                models.Add(x, UndoRedoRecorder.UserAction.Modification);
            }

            foreach (ConnectorModel x in Model.Connectors)
            {
                graph.AddEdge(x.Start.Owner.GUID, x.End.Owner.GUID, x.Start.Center.Y, x.End.Center.Y);
                models.Add(x, UndoRedoRecorder.UserAction.Modification);
            }

            WorkspaceModel.RecordModelsForModification(new List <ModelBase>(Model.Nodes), Model.UndoRecorder);

            // Sugiyama algorithm steps
            graph.RemoveCycles();
            graph.AssignLayers();
            graph.OrderNodes();

            // Assign coordinates to node models
            graph.NormalizeGraphPosition();
            foreach (var x in Model.Nodes)
            {
                var id = x.GUID;
                x.X = graph.FindNode(id).X;
                x.Y = graph.FindNode(id).Y;
                x.ReportPosition();
            }

            // Fit view to the new graph layout
            DynamoSelection.Instance.ClearSelection();
            ResetFitViewToggle(null);
            FitViewInternal();
        }
Пример #7
0
        public void AlignSelected(object parameter)
        {
            string alignType = parameter.ToString();

            if (DynamoSelection.Instance.Selection.Count <= 1)
            {
                return;
            }

            // All the models in the selection will be modified,
            // record their current states before anything gets changed.
            SmartCollection <ISelectable> selection = DynamoSelection.Instance.Selection;
            IEnumerable <ModelBase>       models    = selection.OfType <ModelBase>();

            WorkspaceModel.RecordModelsForModification(models.ToList(), Model.UndoRecorder);

            var toAlign = DynamoSelection.Instance.Selection.OfType <ILocatable>().ToList();

            switch (alignType)
            {
            case "HorizontalCenter":
            {
                var xAll = GetSelectionAverageX();
                toAlign.ForEach((x) => { x.CenterX = xAll; });
            }
            break;

            case "HorizontalLeft":
            {
                var xAll = GetSelectionMinX();
                toAlign.ForEach((x) => { x.X = xAll; });
            }
            break;

            case "HorizontalRight":
            {
                var xAll = GetSelectionMaxX();
                toAlign.ForEach((x) => { x.X = xAll - x.Width; });
            }
            break;

            case "VerticalCenter":
            {
                var yAll = GetSelectionAverageY();
                toAlign.ForEach((x) => { x.CenterY = yAll; });
            }
            break;

            case "VerticalTop":
            {
                var yAll = GetSelectionMinY();
                toAlign.ForEach((x) => { x.Y = yAll; });
            }
            break;

            case "VerticalBottom":
            {
                var yAll = GetSelectionMaxY();
                toAlign.ForEach((x) => { x.Y = yAll - x.Height; });
            }
            break;

            case "VerticalDistribute":
            {
                if (DynamoSelection.Instance.Selection.Count <= 2)
                {
                    return;
                }

                var yMin = GetSelectionMinY();
                var yMax = GetSelectionMaxY();

                var spacing = 0.0;
                var span    = yMax - yMin;

                var nodeHeightSum =
                    DynamoSelection.Instance.Selection.Where(y => y is ILocatable)
                    .Cast <ILocatable>()
                    .Sum((y) => y.Height);

                if (span > nodeHeightSum)
                {
                    spacing = (span - nodeHeightSum)
                              / (DynamoSelection.Instance.Selection.Count - 1);
                }

                var cursor = yMin;
                foreach (var node in toAlign.OrderBy(y => y.Y))
                {
                    node.Y  = cursor;
                    cursor += node.Height + spacing;
                }
            }
            break;

            case "HorizontalDistribute":
            {
                if (DynamoSelection.Instance.Selection.Count <= 2)
                {
                    return;
                }

                var xMin = GetSelectionMinX();
                var xMax = GetSelectionMaxX();

                var spacing      = 0.0;
                var span         = xMax - xMin;
                var nodeWidthSum =
                    DynamoSelection.Instance.Selection.Where((x) => x is ILocatable)
                    .Cast <ILocatable>()
                    .Sum((x) => x.Width);

                // If there is more span than total node width,
                // distribute the nodes with a gap. If not, leave
                // the spacing at 0 and the nodes will distribute
                // up against each other.
                if (span > nodeWidthSum)
                {
                    spacing = (span - nodeWidthSum)
                              / (DynamoSelection.Instance.Selection.Count - 1);
                }

                var cursor = xMin;
                foreach (var node in toAlign.OrderBy(x => x.X))
                {
                    node.X  = cursor;
                    cursor += node.Width + spacing;
                }
            }
            break;
            }

            toAlign.ForEach(x => x.ReportPosition());
        }
Пример #8
0
        private void DoGraphAutoLayout(object o)
        {
            if (Model.Nodes.Count() == 0)
            {
                return;
            }

            var graph  = new GraphLayout.Graph();
            var models = new Dictionary <ModelBase, UndoRedoRecorder.UserAction>();

            foreach (AnnotationModel x in Model.Annotations)
            {
                // Treat a group as a graph layout node/vertex
                graph.AddNode(x.GUID, x.Width, x.Height, x.Y);
                models.Add(x, UndoRedoRecorder.UserAction.Modification);
            }

            foreach (NodeModel x in Model.Nodes)
            {
                AnnotationModel group = Model.Annotations.Where(
                    s => s.SelectedModels.Contains(x)).ToList().FirstOrDefault();

                // Do not process nodes within groups
                if (group == null)
                {
                    graph.AddNode(x.GUID, x.Width, x.Height, x.Y);
                    models.Add(x, UndoRedoRecorder.UserAction.Modification);
                }
            }

            foreach (ConnectorModel x in Model.Connectors)
            {
                AnnotationModel startGroup = null, endGroup = null;
                startGroup = Model.Annotations.Where(
                    s => s.SelectedModels.Contains(x.Start.Owner)).ToList().FirstOrDefault();
                endGroup = Model.Annotations.Where(
                    s => s.SelectedModels.Contains(x.End.Owner)).ToList().FirstOrDefault();

                // Connector does not belong to any group
                if ((startGroup == null) && (endGroup == null))
                {
                    graph.AddEdge(x.Start.Owner.GUID, x.End.Owner.GUID, x.Start.Center.Y, x.End.Center.Y);
                }

                // Connector starts from a node within a group
                else if ((startGroup != null) && (endGroup == null))
                {
                    graph.AddEdge(startGroup.GUID, x.End.Owner.GUID, x.Start.Center.Y, x.End.Center.Y);
                }

                // Connector ends at a node within a group
                else if ((startGroup == null) && (endGroup != null))
                {
                    graph.AddEdge(x.Start.Owner.GUID, endGroup.GUID, x.Start.Center.Y, x.End.Center.Y);
                }

                models.Add(x, UndoRedoRecorder.UserAction.Modification);
            }

            // Support undo for graph layout command
            WorkspaceModel.RecordModelsForModification(new List <ModelBase>(Model.Nodes), Model.UndoRecorder);

            // Sugiyama algorithm steps
            graph.RemoveCycles();
            graph.AssignLayers();
            graph.OrderNodes();

            graph.NormalizeGraphPosition();

            // Assign coordinates to nodes inside groups
            foreach (var x in Model.Annotations)
            {
                var    id     = x.GUID;
                double deltaX = graph.FindNode(id).X - x.X;
                double deltaY = graph.FindNode(id).Y - x.Y;
                foreach (var n in x.SelectedModels)
                {
                    n.X += deltaX;
                    n.Y += deltaY;
                    n.ReportPosition();
                }
            }

            // Assign coordinates to nodes outside groups
            foreach (var x in Model.Nodes)
            {
                var n = graph.FindNode(x.GUID);
                if (n != null)
                {
                    x.X = n.X;
                    x.Y = n.Y;
                    x.ReportPosition();
                }
            }

            // Fit view to the new graph layout
            DynamoSelection.Instance.ClearSelection();
            ResetFitViewToggle(null);
            FitViewInternal();
        }
Пример #9
0
        public void AlignSelected(object parameter)
        {
            string alignType = parameter.ToString();

            if (DynamoSelection.Instance.Selection.Count <= 1)
            {
                return;
            }

            // All the models in the selection will be modified,
            // record their current states before anything gets changed.
            SmartCollection <ISelectable> selection = DynamoSelection.Instance.Selection;
            IEnumerable <ModelBase>       models    = selection.OfType <ModelBase>();

            _model.RecordModelsForModification(models.ToList());

            var toAlign = DynamoSelection.Instance.Selection.Where((x) => x is ILocatable)
                          .Cast <ILocatable>()
                          .ToList();

            if (alignType == "HorizontalCenter")  // make vertial line of elements
            {
                var xAll = GetSelectionAverageX();
                toAlign.ForEach((x) => { x.CenterX = xAll; });
            }
            else if (alignType == "HorizontalLeft")
            {
                var xAll = GetSelectionMinX();
                toAlign.ForEach((x) => { x.X = xAll; });
            }
            else if (alignType == "HorizontalRight")
            {
                var xAll = GetSelectionMaxX();
                toAlign.ForEach((x) => { x.X = xAll - x.Width; });
            }
            else if (alignType == "VerticalCenter")
            {
                var yAll = GetSelectionAverageY();
                toAlign.ForEach((x) => { x.CenterY = yAll; });
            }
            else if (alignType == "VerticalTop")
            {
                var yAll = GetSelectionMinY();
                toAlign.ForEach((x) => { x.Y = yAll; });
            }
            else if (alignType == "VerticalBottom")
            {
                var yAll = GetSelectionMaxY();
                toAlign.ForEach((x) => { x.Y = yAll - x.Height; });
            }
            else if (alignType == "VerticalDistribute")
            {
                if (DynamoSelection.Instance.Selection.Count <= 2)
                {
                    return;
                }

                var yMin    = GetSelectionMinY();
                var yMax    = GetSelectionMaxTopY();
                var spacing = (yMax - yMin) / (DynamoSelection.Instance.Selection.Count - 1);
                int count   = 0;

                toAlign.OrderBy((x) => x.Y)
                .ToList()
                .ForEach((x) => x.Y = yMin + spacing * count++);
            }
            else if (alignType == "HorizontalDistribute")
            {
                if (DynamoSelection.Instance.Selection.Count <= 2)
                {
                    return;
                }

                var xMin    = GetSelectionMinX();
                var xMax    = GetSelectionMaxLeftX();
                var spacing = (xMax - xMin) / (DynamoSelection.Instance.Selection.Count - 1);
                int count   = 0;

                toAlign.OrderBy((x) => x.X)
                .ToList()
                .ForEach((x) => x.X = xMin + spacing * count++);
            }

            toAlign.ForEach(x => x.ReportPosition());
        }