/// <summary> /// Checks if a node can be complexified. /// </summary> /// <param name="indexTable">List of indexes of more complex nodes upon return.</param> /// <returns>True if a node can be complexified at the focus.</returns> public virtual bool IsItemComplexifiable(out IDictionary <IFocusInner, IList <IFocusInsertionChildNodeIndex> > indexTable) { indexTable = new Dictionary <IFocusInner, IList <IFocusInsertionChildNodeIndex> >(); bool IsComplexifiable = false; IFocusNodeState CurrentState = Focus.CellView.StateView.State; // Search recursively for a complexifiable node. while (CurrentState != null) { if (NodeHelper.GetComplexifiedNode(CurrentState.Node, out IList <Node> ComplexifiedNodeList)) { Debug.Assert(ComplexifiedNodeList != null && ComplexifiedNodeList.Count > 0); Type InterfaceType = CurrentState.ParentInner.InterfaceType; bool IsAssignable = true; foreach (Node ComplexifiedNode in ComplexifiedNodeList) { IsAssignable &= InterfaceType.IsAssignableFrom(Type.FromGetType(ComplexifiedNode)); } if (IsAssignable) { IFocusBrowsingChildIndex ParentIndex = CurrentState.ParentIndex as IFocusBrowsingChildIndex; Debug.Assert(ParentIndex != null); IFocusInner Inner = CurrentState.ParentInner; IList <IFocusInsertionChildNodeIndex> IndexList = new List <IFocusInsertionChildNodeIndex>(); foreach (Node ComplexifiedNode in ComplexifiedNodeList) { IFocusInsertionChildNodeIndex NodeIndex = ((IFocusBrowsingInsertableIndex)ParentIndex).ToInsertionIndex(Inner.Owner.Node, ComplexifiedNode) as IFocusInsertionChildNodeIndex; IndexList.Add(NodeIndex); } indexTable.Add(Inner, IndexList); IsComplexifiable = true; } } CurrentState = CurrentState.ParentState; } return(IsComplexifiable); }
/// <summary> /// Handler called every time a state is inserted in the controller. /// </summary> /// <param name="operation">Details of the operation performed.</param> private protected override void OnStateReplaced(IWriteableReplaceOperation operation) { base.OnStateReplaced(operation); IFocusNodeState NewChildState = ((IFocusReplaceOperation)operation).NewChildState; Debug.Assert(NewChildState != null); Debug.Assert(StateViewTable.ContainsKey(NewChildState)); IFocusBrowsingChildIndex OldBrowsingIndex = ((IFocusReplaceOperation)operation).OldBrowsingIndex; Debug.Assert(OldBrowsingIndex != null); Debug.Assert(NewChildState.ParentIndex != OldBrowsingIndex); IFocusBrowsingChildIndex NewBrowsingIndex = ((IFocusReplaceOperation)operation).NewBrowsingIndex; Debug.Assert(NewBrowsingIndex != null); Debug.Assert(NewChildState.ParentIndex == NewBrowsingIndex); }
/// <summary> /// Checks if a node can be simplified. /// </summary> /// <param name="inner">Inner to use to replace the node upon return.</param> /// <param name="index">Index of the simpler node upon return.</param> /// <returns>True if a node can be simplified at the focus.</returns> public virtual bool IsItemSimplifiable(out IFocusInner inner, out IFocusInsertionChildIndex index) { inner = null; index = null; bool IsSimplifiable = false; IFocusNodeState CurrentState = Focus.CellView.StateView.State; // Search recursively for a simplifiable node. while (CurrentState != null) { if (NodeHelper.GetSimplifiedNode(CurrentState.Node, out Node SimplifiedNode)) { if (SimplifiedNode != null) { Type InterfaceType = CurrentState.ParentInner.InterfaceType; if (InterfaceType.IsAssignableFrom(Type.FromGetType(SimplifiedNode))) { IFocusBrowsingChildIndex ParentIndex = CurrentState.ParentIndex as IFocusBrowsingChildIndex; Debug.Assert(ParentIndex != null); inner = CurrentState.ParentInner; index = ((IFocusBrowsingInsertableIndex)ParentIndex).ToInsertionIndex(inner.Owner.Node, SimplifiedNode) as IFocusInsertionChildIndex; IsSimplifiable = true; } } break; } CurrentState = CurrentState.ParentState; } return(IsSimplifiable); }
/// <summary> /// Replace an existing node with a new one, keeping its cycle. /// </summary> /// <param name="inner">The inner where the node is replaced.</param> /// <param name="cycleIndexList">Cycle of nodes that can replace the current node.</param> /// <param name="cyclePosition">New position in the cycle.</param> /// <param name="nodeIndex">Index of the replacing node upon return.</param> public virtual void Replace(IFocusInner inner, FocusInsertionChildNodeIndexList cycleIndexList, int cyclePosition, out IFocusBrowsingChildIndex nodeIndex) { Contract.RequireNotNull(cycleIndexList, out FocusInsertionChildNodeIndexList CycleIndexList); Debug.Assert(CycleIndexList.Count >= 2); Debug.Assert(cyclePosition >= 0 && cyclePosition < CycleIndexList.Count); IFocusInsertionChildNodeIndex ReplacementIndex = CycleIndexList[cyclePosition]; IndexToPositionAndNode(ReplacementIndex, out int BlockIndex, out int Index, out _, out Node Node); System.Action <IWriteableOperation> HandlerRedo = (IWriteableOperation operation) => ExecuteReplaceWithCycle(operation); System.Action <IWriteableOperation> HandlerUndo = (IWriteableOperation operation) => UndoReplaceWithCycle(operation); IFocusReplaceWithCycleOperation Operation = CreateReplaceWithCycleOperation(inner.Owner.Node, inner.PropertyName, BlockIndex, Index, CycleIndexList, cyclePosition, HandlerRedo, HandlerUndo, isNested: false); ExecuteReplaceWithCycle(Operation); nodeIndex = Operation.NewBrowsingIndex; SetLastOperation(Operation); CheckInvariant(); }