/// <summary>
        /// リンクを削除する
        /// </summary>
        public void RemoveLink(LinkViewModel link)
        {
            UndoableContext.CurrentContext.CommandStacking(new UndoableDelegate("RemoveLink", false,
                                                                                // Undo
                                                                                (o) => {
                var d = o as ConnectorHistoryData;
                d.linkObject.SourceConnector = d.source;
                d.linkObject.TargetConnector = d.target;
                Links.Add(d.linkObject);
                return(o);
            },
                                                                                // Redo
                                                                                (o) => {
                // 内部でコールバック登録等を行っているのでちゃんといったんクリアする
                var d = o as ConnectorHistoryData;
                d.linkObject.SourceConnector = null;
                d.linkObject.TargetConnector = null;
                Links.Remove(d.linkObject);
                return(o);
            }),
                                                           // History data
                                                           new ConnectorHistoryData()
            {
                linkObject = link,
                source     = link.SourceConnector,
                target     = link.TargetConnector
            }
                                                           );

            // リンク解除
            link.SourceConnector = null;
            link.TargetConnector = null;
            Links.Remove(link);
        }
        /// <summary>
        ///
        /// </summary>
        public void ConnectionDragging(ConnectionDraggingEventArgs arg)
        {
            LinkViewModel m = arg.Connection as LinkViewModel;

            if (m == null)
            {
                return;
            }

            // 位置を更新
            if (m.SourceConnector != null)
            {
                m.End = arg.Position;
            }
            else
            {
                m.Start = arg.Position;
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="connector"></param>
        /// <returns></returns>
        public LinkViewModel ConnectionDragStarted(NodeConnectorViewModel connector)
        {
            LinkViewModel link = new LinkViewModel();

            switch (connector.Type)
            {
            case NodeConnectorViewModel.ConnectorType.Input:
                link.TargetConnector = connector;
                break;

            case NodeConnectorViewModel.ConnectorType.Output:
                link.SourceConnector = connector;
                break;
            }

            // 追加
            Links.Add(link);

            return(link);
        }
        /// <summary>
        ///
        /// </summary>
        public void ConnectionDragCompleted(ConnectionDragCompletedEventArgs arg)
        {
            LinkViewModel m = arg.Connection as LinkViewModel;

            if (m == null)
            {
                return;
            }

            bool isConnect = false;

            if (arg.ConnectorDraggedOver != null)
            {
                NodeConnectorViewModel connector = arg.ConnectorDraggedOver as NodeConnectorViewModel;
                if (connector != null)
                {
                    var linkSource = m.SourceConnector != null ? m.SourceConnector : m.TargetConnector;

                    // リンク元と同じタイプ、同じ親ならdiscard
                    if (linkSource.Type != connector.Type &&
                        linkSource.Parent != connector.Parent
                        )
                    {
                        if (connector.Type == NodeConnectorViewModel.ConnectorType.Input)
                        {
                            m.TargetConnector = connector;
                        }
                        else
                        {
                            m.SourceConnector = connector;
                        }
                        isConnect = true;
                    }
                }
            }

            // 接続されない場合リンクを削除する
            if (!isConnect)
            {
                m.SourceConnector = null;
                m.TargetConnector = null;
                Links.Remove(m);
            }
            else
            {
                // 接続された場合Undo登録する
                UndoableContext.CurrentContext.CommandStacking(new UndoableDelegate("ConnectAttribute", false,
                                                                                    // Undo
                                                                                    (o) => {
                    // 内部でコールバック登録等を行っているのでちゃんといったんクリアする
                    var d = o as ConnectorHistoryData;
                    d.linkObject.SourceConnector = null;
                    d.linkObject.TargetConnector = null;
                    Links.Remove(d.linkObject);
                    return(o);
                },
                                                                                    // Redo
                                                                                    (o) => {
                    var d = o as ConnectorHistoryData;
                    d.linkObject.SourceConnector = d.source;
                    d.linkObject.TargetConnector = d.target;
                    Links.Add(d.linkObject);
                    return(o);
                }),
                                                               // History data
                                                               new ConnectorHistoryData()
                {
                    linkObject = m,
                    source     = m.SourceConnector,
                    target     = m.TargetConnector
                }
                                                               );
            }
        }