/// <summary>
            /// Returns a list that contains a port candidate for each of the node's
            /// ports. Each candidate has the same location as the port. If a port
            /// already has a connected edge, its port candidate is marked as invalid.
            /// </summary>
            /// <remarks>
            /// Note that the various variants of getPortCandidates of
            /// <see cref="PortCandidateProviderBase"/> delegate to this method.
            /// This can be used to provide the same candidates for all use-cases.
            /// </remarks>
            protected override IEnumerable <IPortCandidate> GetPortCandidates(IInputModeContext context)
            {
                List <IPortCandidate> candidates = new List <IPortCandidate>();
                var graph = context.GetGraph();

                // Create the candidate for each port
                if (graph != null)
                {
                    foreach (IPort port in node.Ports)
                    {
                        DefaultPortCandidate portCandidate = new DefaultPortCandidate(port);
                        portCandidate.Validity = graph.Degree(port) == 0 ? PortCandidateValidity.Valid : PortCandidateValidity.Invalid;
                        candidates.Add(portCandidate);
                    }
                }

                // If no candidates have been created so far, create a single invalid candidate as fallback
                if (candidates.Count == 0)
                {
                    DefaultPortCandidate item = new DefaultPortCandidate(node, FreeNodePortLocationModel.NodeCenterAnchored);
                    item.Validity = PortCandidateValidity.Invalid;
                    candidates.Add(item);
                }

                return(candidates);
            }
            /// <summary>
            /// Returns a list that contains a port candidate for each of the node's
            /// ports. Each candidate has the same location as the port. If a port
            /// already has a connected edge, its port candidate is marked as invalid.
            /// </summary>
            /// <remarks>
            /// Note that the variants of getPortCandidates for target ports are all
            /// implemented by this class. Therefore, this method is only used for
            /// source ports.
            /// </remarks>
            protected override IEnumerable <IPortCandidate> GetPortCandidates(IInputModeContext context)
            {
                List <IPortCandidate> candidates = new List <IPortCandidate>();
                bool hasValid = false;
                var  graph    = context.GetGraph();

                if (graph != null)
                {
                    // Create a port candidate for each port on the node
                    foreach (IPort port in node.Ports)
                    {
                        DefaultPortCandidate portCandidate = new DefaultPortCandidate(port);
                        bool valid = graph.OutDegree(port) == 0;
                        hasValid |= valid;
                        portCandidate.Validity = valid ? PortCandidateValidity.Valid : PortCandidateValidity.Invalid;
                        candidates.Add(portCandidate);
                    }
                }

                // If no valid candidates have been created so far, use the ShapeGeometryPortCandidateProvider as fallback.
                // This provides a candidate in the middle of each of the four sides of the node.
                if (!hasValid)
                {
                    candidates.AddRange(PortCandidateProviders.FromShapeGeometry(node).GetSourcePortCandidates(context));
                }
                return(candidates);
            }
            /// <summary>
            /// Returns all port candidates that apply for the provided opposite port candidate.
            /// </summary>
            /// <remarks>
            /// In this implementation only source ports with the same color and source ports of nodes
            /// with the same color as the target port are accepted.
            /// </remarks>
            public override IEnumerable <IPortCandidate> GetTargetPortCandidates(IInputModeContext context, IPortCandidate source)
            {
                List <IPortCandidate> candidates = new List <IPortCandidate>();
                var graph = context.GetGraph();

                if (graph != null)
                {
                    foreach (IPort port in node.Ports)
                    {
                        DefaultPortCandidate portCandidate = new DefaultPortCandidate(port);
                        var  sourcePort = source.CreatePort(context);
                        bool valid      = port.Tag.Equals(source.Owner.Tag) || sourcePort != null && port.Tag.Equals(sourcePort.Tag);
                        portCandidate.Validity = valid ? PortCandidateValidity.Valid : PortCandidateValidity.Invalid;
                        candidates.Add(portCandidate);
                    }
                }

                return(candidates);
            }
        /// <summary>
        /// Returns the suitable candidates based on the specified <see cref="EdgeDirection"/>.
        /// </summary>
        private IEnumerable <IPortCandidate> GetCandidatesForDirection(EdgeDirection direction, IInputModeContext context)
        {
            // If EdgeDirectionPolicy.DetermineFromPortCandidates is used, CreateEdgeInputMode queries GetSourcePortCandidates
            // as well as GetTargetPortCandidates to collect possible port candidates to start the edge creation.
            // In this case this method is called twice (with EdgeDirection.In and EdgeDirection.Out) so for each call we
            // should only return the *valid* port candidates of a port as otherwise for each port a valid as well as an invalid
            // candidate is returned.
            var provideAllCandidates = true;
            var ceim = context.ParentInputMode as CreateEdgeInputMode;

            if (ceim != null)
            {
                // check the edge direction policy as well as whether candidates are collected for starting or ending the edge creation
                provideAllCandidates = ceim.EdgeDirectionPolicy != EdgeDirectionPolicy.DetermineFromPortCandidates ||
                                       ceim.IsCreationInProgress;
            }

            var candidates = new List <IPortCandidate>();

            // iterate over all available ports
            foreach (var port in context.GetGraph().Ports)
            {
                // create a port candidate, invalidate it (so it is visible but not usable)
                var candidate = new DefaultPortCandidate(port)
                {
                    Validity = PortCandidateValidity.Invalid
                };
                // get the port descriptor
                var portDescriptor = port.Tag as PortDescriptor;
                // make the candidate valid if the direction is the same as the one supplied
                if (portDescriptor != null && portDescriptor.EdgeDirection == direction)
                {
                    candidate.Validity = PortCandidateValidity.Valid;
                }
                // add the candidate to the list
                if (provideAllCandidates || candidate.Validity == PortCandidateValidity.Valid)
                {
                    candidates.Add(candidate);
                }
            }
            // and return the list
            return(candidates);
        }
            /// <summary>
            /// Creates an enumeration of possible port candidates, in this
            /// case one port candidate for each of the node's
            /// ports in the same location as the port.
            /// </summary>
            /// <remarks>
            /// This method is used to provide the same candidates for all
            /// use-cases. It is used as a fallback if methods <c>GetSourcePortCandidates()</c>
            /// and <c>GetTargetPortCandidates()</c> aren't implemented.
            /// </remarks>
            protected override IEnumerable <IPortCandidate> GetPortCandidates(IInputModeContext context)
            {
                List <IPortCandidate> candidates = new List <IPortCandidate>();
                var graph = context.GetGraph();

                if (graph != null)
                {
                    foreach (IPort port in node.Ports)
                    {
                        DefaultPortCandidate portCandidate = new DefaultPortCandidate(port);
                        candidates.Add(portCandidate);
                    }
                }
                if (candidates.Count == 0)
                {
                    DefaultPortCandidate item = new DefaultPortCandidate(node, FreeNodePortLocationModel.NodeCenterAnchored);
                    item.Validity = PortCandidateValidity.Invalid;
                    candidates.Add(item);
                }

                return(candidates);
            }