Example #1
0
        void DoTest(string tree1, string tree2, string expected)
        {
            var edits  = TreeEdit.GetTreeEdits(new TestNode(tree1), new TestNode(tree2));
            var actual = string.Join("; ", edits);

            Assert.AreEqual(expected, actual);
        }
Example #2
0
            void UpdateStructure(ITreeNode newRoot)
            {
                void Rebind(NSNodeItem item, ITreeNode newNode)
                {
                    nodeToItem.Remove(item.Node);
                    item.Node           = newNode;
                    nodeToItem[newNode] = item;
                }

                void DeleteDescendantsFromMap(NSNodeItem item)
                {
                    item.Children.ForEach(c =>
                    {
                        Debug.Assert(nodeToItem.Remove(c.Node));
                        DeleteDescendantsFromMap(c);
                    });
                }

                var edits = TreeEdit.GetTreeEdits(rootItem.Node, newRoot);

                Rebind(rootItem, newRoot);

                foreach (var e in edits)
                {
                    var node = nodeToItem[e.Node];
                    switch (e.Type)
                    {
                    case TreeEdit.EditType.Insert:
                        var insertedNode = CreateItem(e.NewChild);
                        node.Children.Insert(e.ChildIndex, insertedNode);
                        treeView.InsertItems(new NSIndexSet(e.ChildIndex), ToObject(node), NSTableViewAnimation.None);
                        break;

                    case TreeEdit.EditType.Delete:
                        var deletedNode = node.Children[e.ChildIndex];
                        node.Children.RemoveAt(e.ChildIndex);
                        Debug.Assert(deletedNode == nodeToItem[e.OldChild]);
                        nodeToItem.Remove(e.OldChild);
                        treeView.RemoveItems(new NSIndexSet(e.ChildIndex), ToObject(node), NSTableViewAnimation.None);
                        DeleteDescendantsFromMap(deletedNode);
                        break;

                    case TreeEdit.EditType.Reuse:
                        treeView.ReloadItem(ToObject(node));
                        Rebind(nodeToItem[e.OldChild], e.NewChild);
                        break;

                    case TreeEdit.EditType.Expand:
                        treeView.ExpandItem(ToObject(node), expandChildren: false);
                        break;

                    case TreeEdit.EditType.Collapse:
                        treeView.CollapseItem(ToObject(node), collapseChildren: false);
                        break;
                    }
                }
            }
Example #3
0
            void UpdateStructure(ITreeNode newRoot)
            {
                void Rebind(NSNodeItem item, ITreeNode newNode)
                {
                    nodeToItem.Remove(item.Node);
                    item.Node           = newNode;
                    nodeToItem[newNode] = item;
                }

                void DeleteDescendantsFromMap(NSNodeItem item)
                {
                    item.Children.ForEach(c =>
                    {
                        Debug.Assert(nodeToItem.Remove(c.Node));
                        DeleteDescendantsFromMap(c);
                    });
                }

                var edits = TreeEdit.GetTreeEdits(rootItem.Node, newRoot, new TreeEdit.Options
                {
                    TemporariltyExpandParentToInitChildren = true
                });

                Rebind(rootItem, newRoot);

                foreach (var e in edits)
                {
                    var node = nodeToItem[e.Node];
                    switch (e.Type)
                    {
                    case TreeEdit.EditType.Insert:
                        var insertedNode = CreateItem(e.NewChild);
                        node.Children.Insert(e.ChildIndex, insertedNode);
                        using (var set = new NSIndexSet(e.ChildIndex))
                            treeView.InsertItems(set, ToObject(node), NSTableViewAnimation.None);
                        break;

                    case TreeEdit.EditType.Delete:
                        var deletedNode = node.Children[e.ChildIndex];
                        node.Children.RemoveAt(e.ChildIndex);
                        Debug.Assert(deletedNode == nodeToItem[e.OldChild]);
                        nodeToItem.Remove(e.OldChild);
                        using (var set = new NSIndexSet(e.ChildIndex))
                            treeView.RemoveItems(set, ToObject(node), NSTableViewAnimation.None);
                        DeleteDescendantsFromMap(deletedNode);
                        break;

                    case TreeEdit.EditType.Reuse:
                        var viewItem = nodeToItem [e.OldChild];
                        Rebind(viewItem, e.NewChild);
                        treeView.ReloadItem(ToObject(viewItem), reloadChildren: false);
                        if (owner.OnUpdateRowView != null)
                        {
                            var rowIdx  = treeView.RowForItem(ToObject(viewItem));
                            var rowView = rowIdx >= 0 ? treeView.GetRowView(rowIdx, makeIfNecessary: false) : null;
                            if (rowView != null)
                            {
                                owner.OnUpdateRowView(rowView, (Node)e.NewChild);
                            }
                        }
                        break;

                    case TreeEdit.EditType.Expand:
                        treeView.ExpandItem(ToObject(node), expandChildren: false);
                        break;

                    case TreeEdit.EditType.Collapse:
                        treeView.CollapseItem(ToObject(node), collapseChildren: false);
                        break;
                    }
                }
            }
Example #4
0
        public void Update(Node newRoot)
        {
            var finalizeActions = new List <Action>();

            bool   updateBegun = false;
            Action beginUpdate = () =>
            {
                if (!updateBegun)
                {
                    // Call ListView's BeginUpdate/EndUpdate only when needed
                    // tree structure changed to avoid flickering when only selection changes.
                    treeView.BeginUpdate();
                    updateBegun = true;
                }
            };

            updating = true;
            try
            {
                var edits = TreeEdit.GetTreeEdits(currentRoot, newRoot);
                currentRoot = newRoot;

                foreach (var e in edits)
                {
                    TreeNode           node         = e.Node == newRoot ? null : nodeToViewNodes[e.Node];
                    TreeNodeCollection nodeChildren = e.Node == newRoot ? treeView.Nodes : node.Nodes;
                    switch (e.Type)
                    {
                    case TreeEdit.EditType.Insert:
                        beginUpdate();
                        var insertedNode = CreateViewNode((Node)e.NewChild);
                        nodeChildren.Insert(e.ChildIndex, insertedNode);
                        break;

                    case TreeEdit.EditType.Delete:
                        beginUpdate();
                        var deletedNode = nodeChildren[e.ChildIndex];
                        nodeChildren.RemoveAt(e.ChildIndex);
                        Debug.Assert(deletedNode == nodeToViewNodes[e.OldChild]);
                        nodeToViewNodes.Remove(e.OldChild);
                        DeleteDescendantsFromMap(deletedNode);
                        break;

                    case TreeEdit.EditType.Reuse:
                        var nodeToReuse = nodeToViewNodes[e.OldChild];
                        Rebind(nodeToReuse, (Node)e.NewChild);
                        UpdateViewNode(nodeToReuse, (Node)e.NewChild, (Node)e.OldChild, beginUpdate);
                        break;

                    case TreeEdit.EditType.Expand:
                        finalizeActions.Add(node.Expand);
                        break;

                    case TreeEdit.EditType.Collapse:
                        finalizeActions.Add(() => node.Collapse(ignoreChildren: true));
                        break;

                    case TreeEdit.EditType.Select:
                        treeView.SelectNode(node);
                        break;

                    case TreeEdit.EditType.Deselect:
                        treeView.DeselectNode(node);
                        break;
                    }
                }
            }
            finally
            {
                if (updateBegun)
                {
                    treeView.EndUpdate();
                }
                finalizeActions.ForEach(a => a());
                if (treeView.SelectedNode is ViewNode selected && !selected.Node.IsSelected)
                {
                    // When no nodes are explicitly selected, the OS selects one for us,
                    // and we have to undo that.
                    // Another scenario is that a node that was optimistically allowed to be selected in BeforeSelect
                    // turned out not be selected.
                    treeView.SelectedNode = null;
                }
                updating = false;
            }
        }