public virtual void Add(DockPaneLayoutEngine pane, DockDirection align, int i)
 {
     _children.Insert(i, pane);
     pane.Removed += pane_Removed;
     AddEngine(pane);
     OnPaneAdded(new LayoutEngineAddedEventArgs(this, pane, align, i));
 }
        public virtual void Remove(DockPaneLayoutEngine pane)
        {
            if (pane.Children.Count > 0)
            {
                var newParent = pane.Children.Last();
                pane._children.Remove(newParent);
                ChildReplace(pane, newParent);
                newParent._children.InsertRange(0, pane.Children);
                newParent.Initialize(this, pane.Owner, pane.Align);
            }
            else
                _children.Remove(pane);

            RemoveEngine(pane);
            pane._ownNodes.Clear();
            pane._ownNodes.Add(pane);
            pane.Top = null;
            pane.Bottom = null;
            pane.Left = null;
            pane.Right = null;
            pane._children.Clear();
            //Initializeは実行前にChildrenをClearしないと子要素が巻き添え食らう
            pane.Initialize(null, null, DockDirection.None);
            pane.OnRemoved(new EventArgs());
            OnPaneRemoved(new LayoutEngineEventArgs(pane));
        }
 public void DockPaneLayoutEngineConstructorTest()
 {
     var target = new DockPaneLayoutEngine(new DockPaneBase());
     Assert.AreEqual(DockDirection.None, target.Align);
     Assert.IsNull(target.Parent);
     Assert.IsNull(target.Owner);
     Assert.IsNotNull(target.Children);
     Assert.AreEqual(0, target.Children.Count);
 }
 internal override void RemoveEngine(DockPaneLayoutEngine layout)
 {
     base.RemoveEngine(layout);
     if (Parent != null)
         Parent.RemoveEngine(layout);
 }
        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);
        }
 internal virtual void RemoveEngine(DockPaneLayoutEngine layout)
 {
     _ownNodes.Remove(layout);
 }
 internal virtual void AddEngine(DockPaneLayoutEngine layout)
 {
     foreach (var item in layout.OwnNodes)
         _ownNodes.Add(item);
 }
        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 void RemoveTest()
        {
            //テスト事項
            //Bay: 子要素の最初の時
            //Pane: 子要素がある場合の処理, 独身の場合

            var bay = new DockBayLayoutEngine(new DockBayBase());
            var lv1A = new DockPaneLayoutEngine(new DockPaneBase());
            var lv1B = new DockPaneLayoutEngine(new DockPaneBase());
            var lv2A = new DockPaneLayoutEngine(new DockPaneBase());
            var flg_removed = false;
            bay.PaneRemoved += (sender, e) => flg_removed = true;

            //lv0A
            //-lv1A(Top)
            //-lv1B(Left)
            // -lv2A(Bottom)
            bay.Add(lv1A, DockDirection.Top);
            bay.Add(lv1B, DockDirection.Left);
            lv1B.Add(lv2A, DockDirection.Bottom);

            var lv1ASeq = new[]
                {
                    new { Top = (DockPaneLayoutEngine)null, Bottom = (DockPaneLayoutEngine)null, Left = lv2A, Right = (DockPaneLayoutEngine)null, Align = DockDirection.Top, Parent = (DockNodeLayoutEngine)bay },
                    new { Top = (DockPaneLayoutEngine)null, Bottom = (DockPaneLayoutEngine)null, Left = lv2A, Right = (DockPaneLayoutEngine)null, Align = DockDirection.Top, Parent = (DockNodeLayoutEngine)bay },
                    new { Top = (DockPaneLayoutEngine)null, Bottom = (DockPaneLayoutEngine)null, Left = lv2A, Right = (DockPaneLayoutEngine)null, Align = DockDirection.Top, Parent = (DockNodeLayoutEngine)bay },
                    new { Top = (DockPaneLayoutEngine)null, Bottom = (DockPaneLayoutEngine)null, Left = (DockPaneLayoutEngine)null, Right = (DockPaneLayoutEngine)null, Align = DockDirection.None, Parent = (DockNodeLayoutEngine)null },
                };
            var lv1BSeq = new[]
                {
                    new { Top = (DockPaneLayoutEngine)null, Bottom = (DockPaneLayoutEngine)null, Left = (DockPaneLayoutEngine)null, Right = (DockPaneLayoutEngine)null, Align = DockDirection.None, Parent = (DockNodeLayoutEngine)null },
                    new { Top = lv1B, Bottom = (DockPaneLayoutEngine)null, Left = (DockPaneLayoutEngine)null, Right = lv2A, Align = DockDirection.Bottom, Parent = (DockNodeLayoutEngine)lv2A },
                    new { Top = (DockPaneLayoutEngine)null, Bottom = (DockPaneLayoutEngine)null, Left = (DockPaneLayoutEngine)null, Right = (DockPaneLayoutEngine)null, Align = DockDirection.None, Parent = (DockNodeLayoutEngine)null },
                    new { Top = (DockPaneLayoutEngine)null, Bottom = (DockPaneLayoutEngine)null, Left = (DockPaneLayoutEngine)null, Right = (DockPaneLayoutEngine)null, Align = DockDirection.None, Parent = (DockNodeLayoutEngine)null },
                };
            var lv2ASeq = new[]
                {
                    new { Top = (DockPaneLayoutEngine)null, Bottom = (DockPaneLayoutEngine)null, Left = (DockPaneLayoutEngine)null, Right = lv2A, Align = DockDirection.Left, Parent = (DockNodeLayoutEngine)bay },
                    new { Top = (DockPaneLayoutEngine)null, Bottom = lv1B, Left = (DockPaneLayoutEngine)null, Right = lv2A, Align = DockDirection.Left, Parent = (DockNodeLayoutEngine)bay },
                    new { Top = (DockPaneLayoutEngine)null, Bottom = (DockPaneLayoutEngine)null, Left = (DockPaneLayoutEngine)null, Right = lv2A, Align = DockDirection.Left, Parent = (DockNodeLayoutEngine)bay },
                    new { Top = (DockPaneLayoutEngine)null, Bottom = (DockPaneLayoutEngine)null, Left = (DockPaneLayoutEngine)null, Right = (DockPaneLayoutEngine)null, Align = DockDirection.Left, Parent = (DockNodeLayoutEngine)bay },
                };
            var testFunc = (Action<int>)(idx =>
                {
                    Assert.AreEqual(lv1ASeq[idx].Align, lv1A.Align);
                    Assert.AreEqual(lv1ASeq[idx].Parent, lv1A.Parent);
                    Assert.AreEqual(lv1ASeq[idx].Top, lv1A.Top);
                    Assert.AreEqual(lv1ASeq[idx].Bottom, lv1A.Bottom);
                    Assert.AreEqual(lv1ASeq[idx].Left, lv1A.Left);
                    Assert.AreEqual(lv1ASeq[idx].Right, lv1A.Right);

                    Assert.AreEqual(lv1BSeq[idx].Align, lv1B.Align);
                    Assert.AreEqual(lv1BSeq[idx].Parent, lv1B.Parent);
                    Assert.AreEqual(lv1BSeq[idx].Top, lv1B.Top);
                    Assert.AreEqual(lv1BSeq[idx].Bottom, lv1B.Bottom);
                    Assert.AreEqual(lv1BSeq[idx].Left, lv1B.Left);
                    Assert.AreEqual(lv1BSeq[idx].Right, lv1B.Right);

                    Assert.AreEqual(lv2ASeq[idx].Align, lv2A.Align);
                    Assert.AreEqual(lv2ASeq[idx].Parent, lv2A.Parent);
                    Assert.AreEqual(lv2ASeq[idx].Top, lv2A.Top);
                    Assert.AreEqual(lv2ASeq[idx].Bottom, lv2A.Bottom);
                    Assert.AreEqual(lv2ASeq[idx].Left, lv2A.Left);
                    Assert.AreEqual(lv2ASeq[idx].Right, lv2A.Right);
                });

            //lv0A
            //-lv1A(Top)
            //-lv2A(Bottom->Left)
            bay.Remove(lv1B);
            testFunc(0);

            //lv0A
            //-lv1A(Top)
            //-lv2A(Bottom->Left)
            // -lv1B(Left->Bottom)
            lv2A.Add(lv1B, DockDirection.Bottom);
            testFunc(1);

            //lv0A
            //-lv1A(Top)
            //-lv2A(Bottom->Left)
            lv2A.Remove(lv1B);
            testFunc(2);

            //lv0A
            //-lv2A(Bottom->Left)
            bay.Remove(lv1A);
            testFunc(3);

            Assert.IsTrue(flg_removed, "Removed eventが発生してません。");
        }
 public DockPaneBase()
 {
     _layout = new DockPaneLayoutEngine(this);
     _layout.PropertyChanged += new PropertyChangedEventHandler(_layout_PropertyChanged);
     SplitterVisible = _layout.SplitterVisible;
 }
 public void Add(DockPaneLayoutEngine pane, DockDirection align)
 { Add(pane, align, Children.Count); }
 public LayoutEngineReplaceEventArgs(DockPaneLayoutEngine oldPane, DockPaneLayoutEngine newPane)
 {
     NewPane = newPane;
     OldPane = oldPane;
 }
 public LayoutEngineAddedEventArgs(DockNodeLayoutEngine target, DockPaneLayoutEngine pane, DockDirection align, int insertIndex)
     : base(pane)
 {
     Target = target;
     Align = align;
     InsertIndex = insertIndex;
 }
 public LayoutEngineEventArgs(DockPaneLayoutEngine pane)
 {
     DockPane = pane;
 }
        public void AddTest()
        {
            var target = new DockPaneLayoutEngine(new DockPaneBase());

            //AddTest
            //DockPaneNeighs
            var tmp = new[]
                {
                    new { LayoutEngine = new DockPaneLayoutEngine(new DockPaneBase()), Align = DockDirection.Left, Index = 0, Count = 1 },
                    new { LayoutEngine = new DockPaneLayoutEngine(new DockPaneBase()), Align = DockDirection.Top, Index = 1, Count = 2 },
                    new { LayoutEngine = new DockPaneLayoutEngine(new DockPaneBase()), Align = DockDirection.Right, Index = 2, Count = 3 },
                    new { LayoutEngine = new DockPaneLayoutEngine(new DockPaneBase()), Align = DockDirection.Bottom, Index = 3, Count = 4 },
                    new { LayoutEngine = new DockPaneLayoutEngine(new DockPaneBase()), Align = DockDirection.Right, Index = 3, Count = 5 },
                }
                .ToArray();
            //TestDatas
            var testDtIdx = 0;
            var testDt = new[]
                {
                    new { Top = (DockPaneLayoutEngine)null, Bottom = (DockPaneLayoutEngine)null, Left = (DockPaneLayoutEngine)null, Right = tmp[0].LayoutEngine },
                    new { Top = (DockPaneLayoutEngine)null, Bottom = tmp[1].LayoutEngine, Left = tmp[0].LayoutEngine, Right = (DockPaneLayoutEngine)null },
                    new { Top = tmp[1].LayoutEngine, Bottom = (DockPaneLayoutEngine)null, Left = tmp[2].LayoutEngine, Right = (DockPaneLayoutEngine)null },
                    new { Top = tmp[3].LayoutEngine, Bottom = (DockPaneLayoutEngine)null, Left = tmp[0].LayoutEngine, Right = tmp[2].LayoutEngine },
                    new { Top = tmp[1].LayoutEngine, Bottom = (DockPaneLayoutEngine)null, Left = tmp[4].LayoutEngine, Right = tmp[2].LayoutEngine },
                };
            //MargeCollection
            var children = tmp
                .Select(n => new
                {
                    Align = n.Align,
                    LayoutEngine = n.LayoutEngine,
                    TestData = testDt[testDtIdx++],
                    Index = n.Index,
                    Count = n.Count,
                })
                .ToArray();
            foreach (var item in children)
            {
                target.Add(item.LayoutEngine, item.Align, item.Index);

                Assert.AreEqual(target, item.LayoutEngine.Parent);
                Assert.AreEqual(item.Align, item.LayoutEngine.Align);
                Assert.AreEqual(target, item.LayoutEngine.Parent);
                Assert.IsNull(item.LayoutEngine.Owner);
                Assert.AreEqual(item.Index, target.Children.IndexOf(item.LayoutEngine));
                Assert.AreEqual(item.Count, target.Children.Count);

                Assert.AreEqual(item.TestData.Top, item.LayoutEngine.Top);
                Assert.AreEqual(item.TestData.Bottom, item.LayoutEngine.Bottom);
                Assert.AreEqual(item.TestData.Left, item.LayoutEngine.Left);
                Assert.AreEqual(item.TestData.Right, item.LayoutEngine.Right);
                switch (item.Align)
                {
                    case DockDirection.Top:
                        Assert.AreEqual(0,
                            target.GetChildrenOf(item.Align, target.Children.IndexOf(item.LayoutEngine) + 1)
                            .Select(n => n.Top)
                            .Where(n => n != item.LayoutEngine)
                            .Count());
                        break;
                    case DockDirection.Bottom:
                        Assert.AreEqual(0,
                            target.GetChildrenOf(item.Align, target.Children.IndexOf(item.LayoutEngine) + 1)
                            .Select(n => n.Bottom)
                            .Where(n => n != item.LayoutEngine)
                            .Count());
                        break;
                    case DockDirection.Left:
                        Assert.AreEqual(0,
                            target.GetChildrenOf(item.Align, target.Children.IndexOf(item.LayoutEngine) + 1)
                            .Select(n => n.Left)
                            .Where(n => n != item.LayoutEngine)
                            .Count());
                        break;
                    case DockDirection.Right:
                        Assert.AreEqual(0,
                            target.GetChildrenOf(item.Align, target.Children.IndexOf(item.LayoutEngine) + 1)
                            .Select(n => n.Right)
                            .Where(n => n != item.LayoutEngine)
                            .Count());
                        break;
                }
            }

            //InsertTest
            var lyout = new DockPaneLayoutEngine(new DockPaneBase());
            target.Add(lyout, DockDirection.Left, 3);
            Assert.AreEqual(tmp[1].LayoutEngine, lyout.Top);
            Assert.AreEqual(tmp[0].LayoutEngine, lyout.Left);
            Assert.AreEqual(lyout, lyout.Right);
            Assert.AreEqual(null, lyout.Bottom);
            Assert.AreEqual(target.Left, lyout);
            Assert.AreEqual(tmp[3].LayoutEngine.Left, lyout);
            Assert.AreEqual(target, lyout.Parent);

            var bay = new DockBayLayoutEngine(new DockBayBase());
            bay.Add(target, DockDirection.Top);
            foreach (var item in children)
                Assert.AreEqual(bay, item.LayoutEngine.Owner);

            //不正引数用
            var exCnter = 0;
            try { target.Add((DockPaneLayoutEngine)null, DockDirection.Top, 0); }
            catch (ArgumentNullException) { exCnter++; }
            catch { }

            try { target.Add(children[0].LayoutEngine, DockDirection.Bottom, 0); }
            catch (ArgumentException) { exCnter++; }
            catch { }

            try { target.Add(new DockPaneLayoutEngine(new DockPaneBase()), DockDirection.None, 0); }
            catch (ArgumentException) { exCnter++; }
            catch { }

            try { target.Add(new DockPaneLayoutEngine(new DockPaneBase()), DockDirection.Left, -1); }
            catch (ArgumentException) { exCnter++; }
            catch { }
            Assert.AreEqual(4, exCnter, "無効な引数に対して適切な対処が取れていません。");
        }
        public void RemoveEngineTest()
        {
            var parent = new DockPaneLayoutEngine(new DockPaneBase());
            var target = new DockPaneLayoutEngine(new DockPaneBase());
            var layout = new DockPaneLayoutEngine(new DockPaneBase());
            parent.AddEngine(target);
            target.Parent = parent;
            target.AddEngine(layout);
            layout.Parent = target;
            target.RemoveEngine(layout);

            var parent_acc = DockPaneLayoutEngine_Accessor.AttachShadow(parent);
            Assert.IsTrue(parent_acc.OwnNodes.Contains(parent));
            Assert.IsTrue(parent_acc.OwnNodes.Contains(target));
            Assert.IsFalse(parent_acc.OwnNodes.Contains(layout));
            Assert.AreEqual(2, parent_acc.OwnNodes.Count);

            var target_acc = DockPaneLayoutEngine_Accessor.AttachShadow(target);
            Assert.IsTrue(target_acc.OwnNodes.Contains(target));
            Assert.IsFalse(target_acc.OwnNodes.Contains(layout));
            Assert.AreEqual(1, target_acc.OwnNodes.Count);
        }
        /// <summary>子ノード郡の間に新しいPaneを挿入します</summary>
        /// <param name="idx">後輩ノードになるPaneのインデックス</param>
        public override void Add(DockPaneLayoutEngine pane, DockDirection align, int idx)
        {
            if (pane == null)
                throw new ArgumentNullException("第1引数のneighをnullにする事はできません。");
            if (pane.Owner != null)
                throw new ArgumentException("第1引数のneighは使用中です。");
            if (align == DockDirection.None)
                throw new ArgumentException("第2引数のalignをDockDirection.Noneにすることはできません。");
            if (idx < 0 || idx > Children.Count)
                throw new ArgumentOutOfRangeException("第3引数のinsertIndexが有効範囲外です。");

            if (align != DockDirection.Top)
            {
                var btm = GetChildrenOf(DockDirection.Bottom, idx).FirstOrDefault();
                if (btm != null)
                    foreach (var e in pane.GetChildrenOf(DockDirection.Bottom))
                        e.Bottom = btm.Bottom;
            }
            if (align != DockDirection.Bottom)
            {
                var top = GetChildrenOf(DockDirection.Top, idx).FirstOrDefault();
                if (top != null)
                    foreach (var e in pane.GetChildrenOf(DockDirection.Top))
                        e.Top = top.Top;
            }
            if (align != DockDirection.Left)
            {
                var rgh = GetChildrenOf(DockDirection.Right, idx).FirstOrDefault();
                if (rgh != null)
                    foreach (var e in pane.GetChildrenOf(DockDirection.Right))
                        e.Right = rgh.Right;
            }
            if (align != DockDirection.Right)
            {
                var lft = GetChildrenOf(DockDirection.Left, idx).FirstOrDefault();
                if (lft != null)
                    foreach (var e in pane.GetChildrenOf(DockDirection.Left))
                        e.Left = lft.Left;
            }
            switch (align)
            {
                case DockDirection.Top:
                    foreach (var paneInner in pane.GetChildrenOf(~align))
                        paneInner.Bottom = pane;
                    foreach (var thisInner in GetChildrenOf(align, idx))
                        thisInner.Top = pane;
                    break;
                case DockDirection.Bottom:
                    foreach (var paneInner in pane.GetChildrenOf(~align))
                        paneInner.Top = pane;
                    foreach (var thisInner in GetChildrenOf(align, idx))
                        thisInner.Bottom = pane;
                    break;
                case DockDirection.Left:
                    foreach (var paneInner in pane.GetChildrenOf(~align))
                        paneInner.Right = pane;
                    foreach (var thisInner in GetChildrenOf(align, idx))
                        thisInner.Left = pane;
                    break;
                case DockDirection.Right:
                    foreach (var paneInner in pane.GetChildrenOf(~align))
                        paneInner.Left = pane;
                    foreach (var thisInner in GetChildrenOf(align, idx))
                        thisInner.Right = pane;
                    break;
            }
            pane.Initialize(this, Owner, align);

            //base.Addを初めに呼びだしてしまうと、Childrenが更新されるために
            //GetChildrenOfの挙動に以上が生じる。そのため、base.Addは最後に呼ぶ
            base.Add(pane, align, idx);
        }
        public void OnDockPaneAddedTest()
        {
            var target = new DockBayLayoutEngine(new DockBayBase());
            var neighA = new DockPaneLayoutEngine(new DockPaneBase());
            var neighB = new DockPaneLayoutEngine(new DockPaneBase());
            var idx_logger = 0;
            var logger = new DockDirection[2];
            target.PaneAddedInBay += (sender, e) =>
            {
                logger[idx_logger++] = e.Align;
                if (idx_logger > 2)
                    Assert.Fail("DockPaneAddedの呼び出し回数が多すぎです");
            };
            target.Add(neighA, DockDirection.Top);
            neighA.Add(neighB, DockDirection.Left);

            Assert.AreEqual<int>(idx_logger, 2, "DockPaneAddedの呼び出し回数が少なすぎです。");
        }
        protected void MoveSplitter(DockDirection align, double distance, DockPaneLayoutEngine splitPane)
        {
            var pane = (DockPaneLayoutEngine)LayoutEngine;
            //isFamilyがtrueの時はouterに自Nodeがある
            //Bayへはまだ未対応Parent.Childrenを弄る必要がある
            var isFamily = splitPane.OwnNodes.Contains(pane) ? 1 : -1;
            //splitPaneの子要素Sizeの再計算を行うために親要素での自身が展開可能な最大サイズを出す。
            var splitPaneParent = (DockNode)splitPane.Parent.Target;
            var baseSz = (align == DockDirection.Top || align == DockDirection.Bottom
                ? splitPaneParent.ItemsPanelSize.Height : splitPaneParent.ItemsPanelSize.Width)
                - splitPane.Parent.PaneVisualTree
                .TakeWhile(l => l != splitPane)
                .Where(l => l.Align == align || l.Align == ~align)
                .Select(l => l.Align == DockDirection.Top || l.Align == DockDirection.Bottom
                    ? l.Target.ActualHeight : l.Target.ActualWidth)
                .Sum();
            var outer = (DockPaneBase)splitPane.Target;
            var index = Array.IndexOf(splitPane.Parent.PaneVisualTree.ToArray(), splitPane);
            var inners = splitPane.Parent.PaneVisualTree
                .Skip(index + 1)
                .Take(splitPane.Parent.PaneVisualTree
                    .Skip(index + 1)
                    .TakeWhile(l => l.Align != ~align)
                    .Count() + 1);

            //CheckResizableSize
            distance = ResizableDistance(align, isFamily * distance);
            //Resize
            outer.ResizeNodes(align, distance * isFamily, baseSz);
            baseSz -= (align == DockDirection.Top || align == DockDirection.Bottom
                ? outer.ActualHeight : outer.ActualWidth) + distance;
            foreach (var item in inners)
            {
                //alignはResizePaneのResize方向が入ってる。よって、alignは仕組み上、innersに
                //とってはResizePaneの存在する反対方向を指し示す値が入る。そのため、innersの
                //ResizePaneと接しておらず、Resize不要の反対alignPaneは"item.Align == align"
                //がtrueになる。これを利用してResize量を出す
                var childDistance = item.Align == align ? 0 : distance;
                ((DockPaneBase)item.Target).ResizeNodes(~align, childDistance * -isFamily, baseSz);
                //itemのResize分だけ子要素の展開可能Sizeを更新
                if (item.Align == align || item.Align == ~align)
                    baseSz -= (align == DockDirection.Top || align == DockDirection.Bottom
                        ? item.Target.ActualHeight : item.Target.ActualWidth) + childDistance;
            }
        }
        public void RemoveTest()
        {
            //テスト事項
            //Bay: 子要素の最初の時
            //Pane: 子要素がある場合の処理, 独身の場合
            var eBay = new DockBayLayoutEngine(new DockBayBase());
            var eLv1A = new DockPaneLayoutEngine(new DockPaneBase());
            var eLv1B = new DockPaneLayoutEngine(new DockPaneBase());
            var eLv1C = new DockPaneLayoutEngine(new DockPaneBase());

            //lv0A
            //-lv1A(Top)
            //-lv1B(Left)
            //-lv1C(Right)
            eBay.Add(eLv1A, DockDirection.Top);
            eBay.Add(eLv1B, DockDirection.Left);
            eBay.Add(eLv1C, DockDirection.Right);

            //bay
            //-lv1A(Top)
            //-lv1C(Right)
            eBay.Remove(eLv1B);
            //LeftPane
            Assert.IsNull(eLv1A.Top);
            Assert.IsNull(eLv1A.Bottom);
            Assert.IsNull(eLv1A.Left);
            Assert.AreNotEqual(eLv1B, eLv1A.Right);
            Assert.AreEqual(eLv1C, eLv1A.Right);
            //RightPane
            Assert.IsNull(eLv1C.Top);
            Assert.IsNull(eLv1C.Bottom);
            Assert.AreNotEqual(eLv1B, eLv1C.Left);
            Assert.AreEqual(eLv1C, eLv1C.Left);
            Assert.IsNull(eLv1C.Right);

            //lv0A
            //-lv2A(Bottom->Left)
            eBay.Remove(eLv1A);
            Assert.IsNull(eLv1C.Left);
        }
        public void GetChildrenOfTest()
        {
            var target = new DockBayLayoutEngine(new DockBayBase());
            var lv1A = new DockPaneLayoutEngine(new DockPaneBase());
            var lv1B = new DockPaneLayoutEngine(new DockPaneBase());
            var lv1C = new DockPaneLayoutEngine(new DockPaneBase());
            var lv1D = new DockPaneLayoutEngine(new DockPaneBase());
            var lv2A = new DockPaneLayoutEngine(new DockPaneBase());

            target.Add(lv1A, DockDirection.Top);

            target.Add(lv1D, DockDirection.Top);
            lv1D.Add(lv2A, DockDirection.Right);
            target.Add(lv1C, DockDirection.Left);
            target.Add(lv1B, DockDirection.Top);

            //自ノードを含まない
            var testA = target.GetChildrenOf(DockDirection.Left, deep: false).ToArray();
            Assert.IsTrue(testA.Contains(lv1B));
            Assert.IsTrue(testA.Contains(lv1C));
            Assert.AreEqual(2, testA.Length);

            //自ノードを含む
            var testB = target.GetChildrenOf(DockDirection.Right, deep: false).ToArray();
            Assert.IsTrue(testB.Contains(lv1B));
            Assert.IsTrue(testB.Contains(lv1D));
            Assert.IsTrue(testB.Contains(lv1A));
            Assert.AreEqual(3, testB.Length);

            //自ノードを含み、かつ実質接触要素
            var testC = target.GetChildrenOf(DockDirection.Right, deep: true).ToArray();
            Assert.IsTrue(testC.Contains(lv1A));
            Assert.IsTrue(testC.Contains(lv1B));
            Assert.IsTrue(testC.Contains(lv2A));
            Assert.AreEqual(3, testC.Length);

            //自ノードを含み、スキップ2使用(lv1Cから探索)
            var testD = target.GetChildrenOf(DockDirection.Right, 2).ToArray();
            Assert.IsTrue(testD.Contains(lv1A));
            Assert.IsTrue(testD.Contains(lv2A));
            Assert.AreEqual(2, testD.Length);
        }
        public void InitializeTest()
        {
            var target = new DockPaneLayoutEngine(new DockPaneBase());
            var parent = new DockPaneLayoutEngine(new DockPaneBase());
            var owner = new DockBayLayoutEngine(new DockBayBase());
            var align = DockDirection.Top;

            target.Initialize(parent, owner, align);
            Assert.AreEqual(target.Parent, parent);
            Assert.AreEqual(target.Owner, owner);
        }
        public void OnDockPaneRemovedTest()
        {
            var target = new DockBayLayoutEngine(new DockBayBase());
            var neighA = new DockPaneLayoutEngine(new DockPaneBase());
            var neighB = new DockPaneLayoutEngine(new DockPaneBase());
            var logger = new bool[2];
            var counter = 0;
            target.PaneRemovedInBay += (sender, e) =>
            {
                //[0]はneighAのeventが呼ばれたかを記録
                //[1]はneighBのeventが呼ばれたかを記録
                logger[0] |= neighA == e.DockPane;
                logger[1] |= neighB == e.DockPane;
                counter++;
                if (counter > 2)
                    Assert.Fail("DockPaneAddedの呼び出し回数が多すぎです");
            };
            target.Add(neighA, DockDirection.Top);
            neighA.Add(neighB, DockDirection.Left);
            neighA.Remove(neighB);
            target.Remove(neighA);

            Assert.AreEqual<int>(counter, 2, "DockPaneAddedの呼び出し回数が少なすぎです。");
        }
 internal virtual void ChildReplace(DockPaneLayoutEngine oldNeigh, DockPaneLayoutEngine newNeigh)
 {
     _children[_children.IndexOf(oldNeigh)] = newNeigh;
     OnPaneReplaced(new LayoutEngineReplaceEventArgs(oldNeigh, newNeigh));
 }
        public void AddTest()
        {
            var eTarget = new DockBayLayoutEngine(new DockBayBase());

            //AddTest
            //DockPaneNeighs
            var tmp = new[]
                {
                    new {LayoutEngine = new DockPaneLayoutEngine(new DockPaneBase()), Align = DockDirection.Top},
                    new {LayoutEngine = new DockPaneLayoutEngine(new DockPaneBase()), Align = DockDirection.Left},
                    new {LayoutEngine = new DockPaneLayoutEngine(new DockPaneBase()), Align = DockDirection.Top},
                    new {LayoutEngine = new DockPaneLayoutEngine(new DockPaneBase()), Align = DockDirection.Right}
                }
                .ToArray();
            //TestDatas
            var testDtIdx = 0;
            var testDt = new[]
                {
                    new { Top = (DockPaneLayoutEngine)null, Bottom = (DockPaneLayoutEngine)null, Left = (DockPaneLayoutEngine)null, Right = (DockPaneLayoutEngine)null },
                    new { Top = (DockPaneLayoutEngine)null, Bottom = (DockPaneLayoutEngine)null, Left = (DockPaneLayoutEngine)null, Right = tmp[1].LayoutEngine },
                    new { Top = (DockPaneLayoutEngine)null, Bottom = tmp[2].LayoutEngine, Left = (DockPaneLayoutEngine)null, Right = (DockPaneLayoutEngine)null },
                    new { Top = (DockPaneLayoutEngine)null, Bottom = (DockPaneLayoutEngine)null, Left = tmp[3].LayoutEngine, Right = (DockPaneLayoutEngine)null },
                };
            //MargeCollection
            var children = tmp
                .Select(n => new
                {
                    Align = n.Align,
                    LayoutEngine = n.LayoutEngine,
                    TestData = testDt[testDtIdx++],
                });
            foreach (var item in children)
            {
                eTarget.Add(item.LayoutEngine, item.Align);

                Assert.AreEqual(eTarget, item.LayoutEngine.Parent);
                Assert.AreEqual(item.TestData.Top, item.LayoutEngine.Top);
                Assert.AreEqual(item.TestData.Bottom, item.LayoutEngine.Bottom);
                Assert.AreEqual(item.TestData.Left, item.LayoutEngine.Left);
                Assert.AreEqual(item.TestData.Right, item.LayoutEngine.Right);
            }

            //InsertTest
            var lyout = new DockPaneLayoutEngine(new DockPaneBase());
            eTarget.Add(lyout, DockDirection.Left, 1);
            Assert.AreEqual(tmp[2].LayoutEngine, lyout.Top);
            Assert.AreEqual(tmp[1].LayoutEngine, lyout.Left);
            Assert.AreEqual(lyout, lyout.Right);
            Assert.AreEqual(null, lyout.Bottom);
            Assert.AreEqual(tmp[0].LayoutEngine.Left, lyout);
            Assert.AreEqual(eTarget, lyout.Parent);
        }
        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);
        }