public void GetSucceedingDireWhenDeletingPaneTest()
        {
            var nA = new DockPaneLayoutEngine(new DockPaneBase());
            var nB = new DockPaneLayoutEngine(new DockPaneBase());
            var nC = new DockPaneLayoutEngine(new DockPaneBase());
            var parent = new DockBayLayoutEngine(new DockBayBase());

            var nB_acc = DockPaneLayoutEngine_Accessor.AttachShadow(nB);
            var parent_acc = DockBayLayoutEngine_Accessor.AttachShadow(parent);

            //parent
            //-nA
            //-nB
            // -nC
            parent.Add(nA, DockDirection.Top);
            parent.Add(nB, DockDirection.Left);
            nB.Add(nC, DockDirection.Top);

            Assert.IsTrue(nA.GetSucceedingDireWhenDeletingPane() == DockDirection.Left,
                "DockBayNeigh下での挙動に異常があります。");
            Assert.IsTrue(nB.GetSucceedingDireWhenDeletingPane() == DockDirection.Top,
                "DockPaneNeigh下での挙動に異常があります。");
            Assert.IsTrue(nC.GetSucceedingDireWhenDeletingPane() == DockDirection.Bottom,
                "DockPaneNeigh下での挙動に異常があります。");
        }
        public override void Remove(DockPaneLayoutEngine pane)
        {
            if (!Children.Contains(pane))
                throw new ArgumentException("引数paneはこの要素の子要素ではありません。");

            var paneRmvAlign = pane.GetSucceedingDireWhenDeletingPane();

            #region Debug時用状態チェックコード
#if DEBUG
            if (pane.Align == DockDirection.None)
            {
                System.Diagnostics.Debug.Fail(
                    "StatusError", "自身の挿入方向が分かりません。");
                if (System.Diagnostics.Debugger.IsAttached)
                    System.Diagnostics.Debugger.Break();
            }
            if (paneRmvAlign == DockDirection.None)
            {
                System.Diagnostics.Debug.Fail(
                    "StatusError", "自身を消去した後の領域を受け継ぐノードが存在しません。");
                if (System.Diagnostics.Debugger.IsAttached)
                    System.Diagnostics.Debugger.Break();
            }
#endif
            #endregion

            if (pane.Children.Count > 0)
            {
                var newParent = pane.Children.Last();
                //newParent.Align = pane.Align;
                switch (pane.Align)
                {
                    case DockDirection.Top:
                        foreach (var p in pane.GetChildrenOf(~pane.Align))
                            p.Bottom = newParent;
                        foreach (var p in GetChildrenOf(pane.Align, Children.IndexOf(pane) + 1))
                            p.Top = newParent;
                        break;
                    case DockDirection.Bottom:
                        foreach (var p in pane.GetChildrenOf(~pane.Align))
                            p.Top = newParent;
                        foreach (var p in GetChildrenOf(pane.Align, Children.IndexOf(pane) + 1))
                            p.Bottom = newParent;
                        break;
                    case DockDirection.Left:
                        foreach (var p in pane.GetChildrenOf(~pane.Align))
                            p.Right = newParent;
                        foreach (var p in GetChildrenOf(pane.Align, Children.IndexOf(pane) + 1))
                            p.Left = newParent;
                        break;
                    case DockDirection.Right:
                        foreach (var p in pane.GetChildrenOf(~pane.Align))
                            p.Left = newParent;
                        foreach (var p in GetChildrenOf(pane.Align, Children.IndexOf(pane) + 1))
                            p.Right = newParent;
                        break;
                }
                //代替用子要素が持つ、自身と消去要素(paneの事)が接触している部分の
                //SplitPane情報を消去要素が同じ方向に持っているSplitPane情報に差し替え
                switch (paneRmvAlign)
                {
                    case DockDirection.Top:
                        newParent.Bottom = pane.Bottom;
                        break;
                    case DockDirection.Bottom:
                        newParent.Top = pane.Top;
                        break;
                    case DockDirection.Left:
                        newParent.Right = pane.Right;
                        break;
                    case DockDirection.Right:
                        newParent.Left = pane.Left;
                        break;
                }
            }
            else
            {
                //最初要素にも新親要素にもならない独身要素が消える際には削除方向にあるpaneの
                //splitPane情報の自身を参照する方向を自身をまたいだ方向にあるpaneに差し替える
                foreach (var pLayoutEngine in GetChildrenOf(paneRmvAlign, Children.IndexOf(pane) + 1))
                    switch (paneRmvAlign)
                    {
                        case DockDirection.Top:
                            pLayoutEngine.Bottom = pane.Bottom;
                            break;
                        case DockDirection.Bottom:
                            pLayoutEngine.Top = pane.Top;
                            break;
                        case DockDirection.Left:
                            pLayoutEngine.Right = pane.Right;
                            break;
                        case DockDirection.Right:
                            pLayoutEngine.Left = pane.Left;
                            break;
                    }
            }
            base.Remove(pane);
        }
        public override void Remove(DockPaneLayoutEngine pane)
        {
            if (!Children.Contains(pane))
                throw new ArgumentException("引数paneはこの要素の子要素ではありません。");

            var paneRmvAlign = pane.GetSucceedingDireWhenDeletingPane();

            #region Debug時用状態チェックコード
#if DEBUG
            if (pane.Align == DockDirection.None)
            {
                System.Diagnostics.Debug.Fail(
                    "StatusError", "自身の挿入方向が分かりません。");
                if (System.Diagnostics.Debugger.IsAttached)
                    System.Diagnostics.Debugger.Break();
            }
            if (paneRmvAlign == DockDirection.None)
            {
                System.Diagnostics.Debug.Fail(
                    "StatusError", "自身を消去した後の領域を受け継ぐノードが存在しません。");
                if (System.Diagnostics.Debugger.IsAttached)
                    System.Diagnostics.Debugger.Break();
            }
#endif
            #endregion

            if (pane.Children.Count > 0)
            {
                //子要素を自身の代替要素とする場合、各方向のSplitPane情報の更新が必要。
                //よって自身をSplitPaneとして参照する要素のSplitPaneを子要素へ更新する。
                var newParent = pane.Children.Last();
                switch (pane.Align)
                {
                    case DockDirection.Top:
                        foreach (var p in pane.GetChildrenOf(~pane.Align))
                            p.Bottom = newParent;

                        //BayではChildrenの順番がPaneの逆であると同時に要素が1多い。その
                        //ため、Childrenの要素数からindexを引く事でPane時と同じ順番にし、
                        //Pane.Removeでやってるidx+1はしない事で同じ入力をする
                        foreach (var p in GetChildrenOf(pane.Align, Children.Count - Children.IndexOf(pane)))
                            p.Top = newParent;
                        break;
                    case DockDirection.Bottom:
                        foreach (var p in pane.GetChildrenOf(~pane.Align))
                            p.Top = newParent;

                        //※case DockDirection.Topと同様の注意事項
                        foreach (var p in GetChildrenOf(pane.Align, Children.Count - Children.IndexOf(pane)))
                            p.Bottom = newParent;
                        break;
                    case DockDirection.Left:
                        foreach (var p in pane.GetChildrenOf(~pane.Align))
                            p.Right = newParent;

                        //※case DockDirection.Topと同様の注意事項
                        foreach (var p in GetChildrenOf(pane.Align, Children.Count - Children.IndexOf(pane)))
                            p.Left = newParent;
                        break;
                    case DockDirection.Right:
                        foreach (var p in pane.GetChildrenOf(~pane.Align))
                            p.Left = newParent;

                        //※case DockDirection.Topと同様の注意事項
                        foreach (var p in GetChildrenOf(pane.Align, Children.Count - Children.IndexOf(pane)))
                            p.Right = newParent;
                        break;
                }
                //代替用子要素が持つ、自身と消去要素(paneの事)が接触している部分の
                //SplitPane情報を消去要素が同じ方向に持っているSplitPane情報に差し替え
                switch (paneRmvAlign)
                {
                    case DockDirection.Top:
                        newParent.Bottom = pane.Bottom;
                        break;
                    case DockDirection.Bottom:
                        newParent.Top = pane.Top;
                        break;
                    case DockDirection.Left:
                        newParent.Right = pane.Right;
                        break;
                    case DockDirection.Right:
                        newParent.Left = pane.Left;
                        break;
                }
            }
            else if (Children.IndexOf(pane) == 0 && Children.Count > 1)
            {
                //Bayで最初に挿入した子要素は全方向に広がり、Splitterを持たない。そのため、
                //他要素にSplitPaneで参照されることはない。
                //この条件によってBayの最初要素が削除される時に代替要素となる2番目は他要素
                //からのSplitPane参照を消す必要がある。
                var newFillPane = Children[1];
                foreach (var item in newFillPane.GetChildrenOf(~newFillPane.Align))
                    switch (newFillPane.Align)
                    {
                        case DockDirection.Top:
                            item.Bottom = null;
                            break;
                        case DockDirection.Bottom:
                            item.Top = null;
                            break;
                        case DockDirection.Left:
                            item.Right = null;
                            break;
                        case DockDirection.Right:
                            item.Left = null;
                            break;
                    }
            }
            else
            {
                //最初要素にも新親要素にもならない独身要素が消える際には削除方向にあるpaneの
                //splitPane情報の自身を参照する方向を自身をまたいだ方向にあるpaneに差し替える
                foreach (var pLayoutEngine in GetChildrenOf(paneRmvAlign, Children.Count - Children.IndexOf(pane)))
                    switch (paneRmvAlign)
                    {
                        case DockDirection.Top:
                            pLayoutEngine.Bottom = pane.Bottom;
                            break;
                        case DockDirection.Bottom:
                            pLayoutEngine.Top = pane.Top;
                            break;
                        case DockDirection.Left:
                            pLayoutEngine.Right = pane.Right;
                            break;
                        case DockDirection.Right:
                            pLayoutEngine.Left = pane.Left;
                            break;
                    }
            }

            base.Remove(pane);
        }