/// <summary> /// Inserts a new node in a list or block list. /// </summary> /// <param name="inner">The inner for the list or block list where the node is inserted.</param> /// <param name="insertedIndex">Index for the insertion operation.</param> /// <param name="nodeIndex">Index of the inserted node upon return.</param> public virtual void Insert(IWriteableCollectionInner inner, IWriteableInsertionCollectionNodeIndex insertedIndex, out IWriteableBrowsingCollectionNodeIndex nodeIndex) { Contract.RequireNotNull(inner, out IWriteableCollectionInner Inner); Contract.RequireNotNull(insertedIndex, out IWriteableInsertionCollectionNodeIndex InsertedIndex); IWriteableNodeState Owner = Inner.Owner; IWriteableIndex ParentIndex = Owner.ParentIndex; Debug.Assert(Contains(ParentIndex)); Debug.Assert(IndexToState(ParentIndex) == Owner); WriteableInnerReadOnlyDictionary <string> InnerTable = Owner.InnerTable; Debug.Assert(InnerTable.ContainsKey(Inner.PropertyName)); Debug.Assert(InnerTable[Inner.PropertyName] == Inner); bool IsHandled = false; nodeIndex = null; if (Inner is IWriteableBlockListInner <IWriteableBrowsingBlockNodeIndex> AsBlockListInner && InsertedIndex is IWriteableInsertionNewBlockNodeIndex AsNewBlockIndex) { InsertNewBlock(AsBlockListInner, AsNewBlockIndex, out nodeIndex); IsHandled = true; } else if (Inner is IWriteableCollectionInner <IWriteableBrowsingCollectionNodeIndex> AsCollectionInner && InsertedIndex is IWriteableInsertionCollectionNodeIndex AsCollectionIndex) { InsertNewNode(AsCollectionInner, AsCollectionIndex, out nodeIndex); IsHandled = true; } Debug.Assert(IsHandled); }
private protected virtual void ExecuteMove(WriteableMoveNodeOperation operation) { Node ParentNode = operation.ParentNode; string PropertyName = operation.PropertyName; IWriteableCollectionInner <IWriteableBrowsingCollectionNodeIndex> Inner = GetInner(ParentNode, PropertyName) as IWriteableCollectionInner <IWriteableBrowsingCollectionNodeIndex>; Inner.Move(operation); NotifyStateMoved(operation); }
private protected virtual void RemoveNode(IWriteableCollectionInner <IWriteableBrowsingCollectionNodeIndex> inner, int blockIndex, int index) { System.Action <IWriteableOperation> HandlerRedo = (IWriteableOperation operation) => RedoRemoveNode(operation); System.Action <IWriteableOperation> HandlerUndo = (IWriteableOperation operation) => UndoRemoveNode(operation); WriteableRemoveNodeOperation Operation = CreateRemoveNodeOperation(inner.Owner.Node, inner.PropertyName, blockIndex, index, HandlerRedo, HandlerUndo, isNested: false); Operation.Redo(); SetLastOperation(Operation); CheckInvariant(); }
/// <summary> /// Checks whether a node can be moved in a list. /// </summary> /// <param name="inner">The inner where the node is.</param> /// <param name="nodeIndex">Index of the node that would be moved.</param> /// <param name="direction">Direction of the move, relative to the current position of the item.</param> public virtual bool IsMoveable(IWriteableCollectionInner inner, IWriteableBrowsingCollectionNodeIndex nodeIndex, int direction) { Contract.RequireNotNull(inner, out IWriteableCollectionInner Inner); Contract.RequireNotNull(nodeIndex, out IWriteableBrowsingCollectionNodeIndex NodeIndex); IWriteableNodeState State = (IWriteableNodeState)StateTable[NodeIndex]; Debug.Assert(State != null); bool Result = Inner.IsMoveable(NodeIndex, direction); return(Result); }
private protected virtual void InsertNewNode(IWriteableCollectionInner <IWriteableBrowsingCollectionNodeIndex> inner, IWriteableInsertionCollectionNodeIndex insertedIndex, out IWriteableBrowsingCollectionNodeIndex nodeIndex) { IndexToPositionAndNode(insertedIndex, out int BlockIndex, out int Index, out _, out Node Node); Action <IWriteableOperation> HandlerRedo = (IWriteableOperation operation) => RedoInsertNewNode(operation); Action <IWriteableOperation> HandlerUndo = (IWriteableOperation operation) => UndoInsertNewNode(operation); WriteableInsertNodeOperation Operation = CreateInsertNodeOperation(inner.Owner.Node, inner.PropertyName, BlockIndex, Index, Node, HandlerRedo, HandlerUndo, isNested: false); Operation.Redo(); SetLastOperation(Operation); CheckInvariant(); nodeIndex = Operation.BrowsingIndex; }
/// <summary> /// Checks whether a range of nodes can be removed from a list or block list. /// </summary> /// <param name="inner">The inner with nodes to remove.</param> /// <param name="blockIndex">Index of the block where to remove nodes, for a block list. -1 for a list.</param> /// <param name="firstNodeIndex">Index of the first node to remove.</param> /// <param name="lastNodeIndex">Index following the last node to remove.</param> public virtual bool IsNodeRangeRemoveable(IWriteableCollectionInner inner, int blockIndex, int firstNodeIndex, int lastNodeIndex) { Contract.RequireNotNull(inner, out IWriteableCollectionInner Inner); bool IsHandled = false; bool Result = false; if (Inner is IWriteableBlockListInner AsBlockListInner) { Result = IsNodeRangeRemoveable(AsBlockListInner, blockIndex, firstNodeIndex, lastNodeIndex); IsHandled = true; } else if (Inner is IWriteableListInner AsListInner) { Debug.Assert(blockIndex == -1); Result = IsNodeRangeRemoveable(AsListInner, firstNodeIndex, lastNodeIndex); IsHandled = true; } Debug.Assert(IsHandled); if (!Result) { Debug.Assert(Inner.Owner != null); Node Node = Inner.Owner.Node; string PropertyName = Inner.PropertyName; Debug.Assert(Node != null); Result = true; //Type InterfaceType = NodeTreeHelper.NodeTypeToInterfaceType(inner.Owner.Node.GetType()); Type InterfaceType = Type.FromGetType(Inner.Owner.Node); IReadOnlyDictionary <Type, string[]> NeverEmptyCollectionTable = NodeHelper.NeverEmptyCollectionTable; if (NeverEmptyCollectionTable.ContainsKey(InterfaceType)) { foreach (string Item in NeverEmptyCollectionTable[InterfaceType]) { if (Item == PropertyName) { Result = false; } } } } return(Result); }
private protected virtual void ExecuteRemoveNode(WriteableRemoveNodeOperation operation) { Node ParentNode = operation.ParentNode; string PropertyName = operation.PropertyName; IWriteableCollectionInner <IWriteableBrowsingCollectionNodeIndex> Inner = GetInner(ParentNode, PropertyName) as IWriteableCollectionInner <IWriteableBrowsingCollectionNodeIndex>; Inner.Remove(operation); IWriteableNodeState RemovedState = operation.RemovedState; PruneState(RemovedState); Stats.PlaceholderNodeCount--; NotifyStateRemoved(operation); }
/// <summary> /// Moves a node around in a list or block list. In a block list, the node stays in same block. /// </summary> /// <param name="inner">The inner for the list or block list in which the node is moved.</param> /// <param name="nodeIndex">Index for the moved node.</param> /// <param name="direction">The change in position, relative to the current position.</param> public virtual void Move(IWriteableCollectionInner inner, IWriteableBrowsingCollectionNodeIndex nodeIndex, int direction) { Contract.RequireNotNull(inner, out IWriteableCollectionInner Inner); Contract.RequireNotNull(nodeIndex, out IWriteableBrowsingCollectionNodeIndex NodeIndex); IWriteableNodeState State = (IWriteableNodeState)StateTable[NodeIndex]; Debug.Assert(State != null); IndexToPositionAndNode(NodeIndex, out int BlockIndex, out int Index, out _, out Node Node); Action <IWriteableOperation> HandlerRedo = (IWriteableOperation operation) => RedoMove(operation); Action <IWriteableOperation> HandlerUndo = (IWriteableOperation operation) => UndoMove(operation); WriteableMoveNodeOperation Operation = CreateMoveNodeOperation(Inner.Owner.Node, Inner.PropertyName, BlockIndex, Index, direction, HandlerRedo, HandlerUndo, isNested: false); Operation.Redo(); SetLastOperation(Operation); CheckInvariant(); }
private protected virtual void ExecuteInsertNewNode(WriteableInsertNodeOperation operation) { Node ParentNode = operation.ParentNode; string PropertyName = operation.PropertyName; IWriteableCollectionInner <IWriteableBrowsingCollectionNodeIndex> Inner = GetInner(ParentNode, PropertyName) as IWriteableCollectionInner <IWriteableBrowsingCollectionNodeIndex>; Inner.Insert(operation); IWriteableBrowsingCollectionNodeIndex BrowsingIndex = operation.BrowsingIndex; IWriteablePlaceholderNodeState ChildState = operation.ChildState; AddState(BrowsingIndex, ChildState); Stats.PlaceholderNodeCount++; BuildStateTable(Inner, null, BrowsingIndex, ChildState); Debug.Assert(Contains(BrowsingIndex)); NotifyStateInserted(operation); }
/// <summary> /// Removes a range of nodes from a list or block list and replace them with other nodes. /// </summary> /// <param name="inner">The inner for the list or block list from which nodes are replaced.</param> /// <param name="blockIndex">Index of the block where to remove nodes, for a block list. -1 for a list.</param> /// <param name="firstNodeIndex">Index of the first node to remove.</param> /// <param name="lastNodeIndex">Index following the last node to remove.</param> /// <param name="indexList">List of nodes to insert.</param> public virtual void ReplaceNodeRange(IWriteableCollectionInner inner, int blockIndex, int firstNodeIndex, int lastNodeIndex, IList <IWriteableInsertionCollectionNodeIndex> indexList) { Contract.RequireNotNull(inner, out IWriteableCollectionInner Inner); bool IsHandled = false; if (Inner is IWriteableBlockListInner AsBlockListInner) { ReplaceNodeRange(AsBlockListInner, blockIndex, firstNodeIndex, lastNodeIndex, indexList); IsHandled = true; } else if (Inner is IWriteableListInner AsListInner) { Debug.Assert(blockIndex == -1); ReplaceNodeRange(AsListInner, firstNodeIndex, lastNodeIndex, indexList); IsHandled = true; } Debug.Assert(IsHandled); }
/// <summary> /// Removes a node from a list or block list. /// </summary> /// <param name="inner">The inner for the list or block list from which the node is removed.</param> /// <param name="nodeIndex">Index for the removed node.</param> public virtual void Remove(IWriteableCollectionInner inner, IWriteableBrowsingCollectionNodeIndex nodeIndex) { Contract.RequireNotNull(inner, out IWriteableCollectionInner Inner); Contract.RequireNotNull(nodeIndex, out IWriteableBrowsingCollectionNodeIndex NodeIndex); IWriteableNodeState Owner = Inner.Owner; IWriteableIndex ParentIndex = Owner.ParentIndex; Debug.Assert(Contains(ParentIndex)); Debug.Assert(IndexToState(ParentIndex) == Owner); WriteableInnerReadOnlyDictionary <string> InnerTable = Owner.InnerTable; Debug.Assert(InnerTable.ContainsKey(Inner.PropertyName)); Debug.Assert(InnerTable[Inner.PropertyName] == Inner); IndexToPositionAndNode(NodeIndex, out int BlockIndex, out int Index, out _, out Node Node); bool IsHandled = false; if (Inner is IWriteableBlockListInner <IWriteableBrowsingBlockNodeIndex> AsBlockListInner && NodeIndex is IWriteableBrowsingExistingBlockNodeIndex ExistingBlockIndex) { if (AsBlockListInner.BlockStateList[ExistingBlockIndex.BlockIndex].StateList.Count == 1) { RemoveBlock(AsBlockListInner, BlockIndex); } else { RemoveNode(AsBlockListInner, BlockIndex, Index); } IsHandled = true; } else if (Inner is IWriteableCollectionInner <IWriteableBrowsingCollectionNodeIndex> AsCollectionInner) { RemoveNode(AsCollectionInner, BlockIndex, Index); IsHandled = true; } Debug.Assert(IsHandled); }
/// <summary> /// Checks whether a node can be removed from a list. /// </summary> /// <param name="inner">The inner where the node is.</param> /// <param name="nodeIndex">Index of the node that would be removed.</param> public bool IsRemoveable(IWriteableCollectionInner inner, IWriteableBrowsingCollectionNodeIndex nodeIndex) { Contract.RequireNotNull(inner, out IWriteableCollectionInner Inner); Contract.RequireNotNull(nodeIndex, out IWriteableBrowsingCollectionNodeIndex NodeIndex); if (Inner.Count > 1) { return(true); } Debug.Assert(Inner.Count == 1); Debug.Assert(Inner.Owner != null); Node Node = Inner.Owner.Node; string PropertyName = Inner.PropertyName; Debug.Assert(Node != null); bool Result = true; //Type InterfaceType = NodeTreeHelper.NodeTypeToInterfaceType(inner.Owner.Node.GetType()); Type InterfaceType = Type.FromGetType(Inner.Owner.Node); IReadOnlyDictionary <Type, string[]> NeverEmptyCollectionTable = NodeHelper.NeverEmptyCollectionTable; if (NeverEmptyCollectionTable.ContainsKey(InterfaceType)) { foreach (string Item in NeverEmptyCollectionTable[InterfaceType]) { if (Item == PropertyName) { Result = false; } } } return(Result); }