/// <summary>
    ///     Has the last undone operation redone.
    /// </summary>
    /// <param name="undoRedoLevel">A level of undo, with contents.</param>
    /// <param name="toInvokeOutsideLock">An action to invoke outside of the lock.</param>
    /// <param name="state">The state object to pass to the invocation.</param>
    /// <returns><see langword="true" /> if the redo was successful, <see langword="false" /> otherwise.</returns>
    protected override bool RedoInternally(
        StateChangeBase undoRedoLevel,
        out Action <object?>?toInvokeOutsideLock,
        out object?state)
    {
        if (base.RedoInternally(
                undoRedoLevel,
                out toInvokeOutsideLock,
                out state))
        {
            return(true);
        }

        switch (undoRedoLevel)
        {
        case AddStateChange <KeyValuePair <TKey, TValue> >(var(key, value), _):
        {
            IDictionaryCollectionAdapter <TKey, TValue> container = InternalContainer;

            _ = container.Add(
                key,
                value);

            toInvokeOutsideLock = innerState =>
            {
                if (innerState == null)
                {
                    return;
                }

                ((ObservableDictionary <TKey, TValue>)innerState).BroadcastChange();
            };
            state = this;

            break;
        }

        case RemoveStateChange <KeyValuePair <TKey, TValue> >(_, var keyValuePair):
        {
            IDictionaryCollectionAdapter <TKey, TValue> container = InternalContainer;

            _ = container.Remove(keyValuePair.Key);

            toInvokeOutsideLock = innerState =>
            {
                if (innerState == null)
                {
                    return;
                }

                ((ObservableDictionary <TKey, TValue>)innerState).BroadcastChange();
            };
            state = this;

            break;
        }

        case ClearStateChange <KeyValuePair <TKey, TValue> > :
        {
            InternalContainer.Clear();

            toInvokeOutsideLock = innerState =>
            {
                if (innerState == null)
                {
                    return;
                }

                ((ObservableDictionary <TKey, TValue>)innerState).BroadcastChange();
            };
            state = this;

            break;
        }

        case DictionaryAddStateChange <TKey, TValue>(var key, var value):
        {
            IDictionaryCollectionAdapter <TKey, TValue> container = InternalContainer;

            _ = container.Add(
                key,
                value);

            toInvokeOutsideLock = innerState =>
            {
                if (innerState == null)
                {
                    return;
                }

                ((ObservableDictionary <TKey, TValue>)innerState).BroadcastChange();
            };
            state = this;

            break;
        }

        case DictionaryRemoveStateChange <TKey, TValue>(var key, _):
        {
            IDictionaryCollectionAdapter <TKey, TValue> container = InternalContainer;

            _ = container.Remove(key);

            toInvokeOutsideLock = innerState =>
            {
                if (innerState == null)
                {
                    return;
                }

                ((ObservableDictionary <TKey, TValue>)innerState).BroadcastChange();
            };
            state = this;

            break;
        }

        case DictionaryChangeStateChange <TKey, TValue>(var key, var newValue, _):
        {
            IDictionaryCollectionAdapter <TKey, TValue> container = InternalContainer;

            container[key] = newValue;

            toInvokeOutsideLock = innerState =>
            {
                if (innerState == null)
                {
                    return;
                }

                ((ObservableDictionary <TKey, TValue>)innerState).BroadcastChange();
            };
            state = this;

            break;
        }

        default:
        {
            toInvokeOutsideLock = null;
            state = null;

            return(false);
        }
        }

        return(true);
    }
 /// <summary>
 ///     Initializes a new instance of the <see cref="EditCommittedEventArgs" /> class.
 /// </summary>
 /// <param name="stateChanges">The state changes that have been committed.</param>
 public EditCommittedEventArgs(StateChangeBase stateChanges) => StateChanges = stateChanges;
Example #3
0
    protected override bool UndoInternally(
        StateChangeBase undoRedoLevel,
        out Action <object?>?toInvokeOutsideLock,
        out object?state)
    {
        if (base.UndoInternally(
                undoRedoLevel,
                out toInvokeOutsideLock,
                out state))
        {
            return(true);
        }

        switch (undoRedoLevel)
        {
        case AddStateChange <T>(var item, var index):
        {
            InternalListContainer.RemoveAt(index);

            if (ItemsAreUndoable &&
                AutomaticallyCaptureSubItems &&
                item is IUndoableItem {
                    IsCapturedIntoUndoContext : true
                } ul&&
                ul.ParentUndoContext == this)
            {
                ul.ReleaseFromUndoContext();
            }

            toInvokeOutsideLock = innerState =>
            {
                if (innerState == null)
                {
                    return;
                }

                (var observableListBase, T removedItem, var indexRemoved) =
                    (Tuple <ObservableListBase <T>, T, int>)innerState;

                observableListBase.RaiseCollectionChangedRemove(
                    removedItem,
                    indexRemoved);
                observableListBase.RaisePropertyChanged(nameof(observableListBase.Count));
                observableListBase.ContentsMayHaveChanged();
            };

            state = new Tuple <ObservableListBase <T>, T, int>(
                this,
                item,
                index);

            break;
        }

        case AddMultipleStateChange <T>(var addedItems, var index):
        {
            for (var i = 0; i < addedItems.Length; i++)
            {
                InternalListContainer.RemoveAt(index);
            }

            IEnumerable <T> items = addedItems;

            if (ItemsAreUndoable && AutomaticallyCaptureSubItems)
            {
                foreach (IUndoableItem ul in items.Cast <IUndoableItem>()
                         .Where(
                             (
                                 p,
                                 thisL1) => p.IsCapturedIntoUndoContext && p.ParentUndoContext == thisL1,
                             this))
                {
                    ul.ReleaseFromUndoContext();
                }
            }

            toInvokeOutsideLock = innerState =>
            {
                if (innerState == null)
                {
                    return;
                }

                var(observableListBase, enumerable, addedIndex) =
                    (Tuple <ObservableListBase <T>, IEnumerable <T>, int>)innerState;

                observableListBase.RaiseCollectionChangedRemoveMultiple(
                    enumerable,
                    addedIndex);
                observableListBase.RaisePropertyChanged(nameof(observableListBase.Count));
                observableListBase.ContentsMayHaveChanged();
            };

            state = new Tuple <ObservableListBase <T>, IEnumerable <T>, int>(
                this,
                items,
                index);

            break;
        }

        case RemoveStateChange <T>(var index, var item):
        {
            InternalListContainer.Insert(
                index,
                item);

            if (ItemsAreUndoable &&
                AutomaticallyCaptureSubItems &&
                item is IUndoableItem {
                    IsCapturedIntoUndoContext : false
                } ul)
            {
                ul.CaptureIntoUndoContext(this);
            }

            toInvokeOutsideLock = innerState =>
            {
                if (innerState == null)
                {
                    return;
                }

                (var observableListBase, T removedItem, var removedIndex) =
                    (Tuple <ObservableListBase <T>, T, int>)innerState;

                observableListBase.RaiseCollectionChangedAdd(
                    removedItem,
                    removedIndex);
                observableListBase.RaisePropertyChanged(nameof(observableListBase.Count));
                observableListBase.ContentsMayHaveChanged();
            };

            state = new Tuple <ObservableListBase <T>, T, int>(
                this,
                item,
                index);

            break;
        }

        case RemoveMultipleStateChange <T>(var indexes, var items):
        {
            for (var i = items.Length - 1; i >= 0; i--)
            {
                InternalListContainer.Insert(
                    indexes[i],
                    items[i]);
            }

            if (ItemsAreUndoable && AutomaticallyCaptureSubItems)
            {
                foreach (IUndoableItem ul in items.Cast <IUndoableItem>()
                         .Where(p => !p.IsCapturedIntoUndoContext))
                {
                    ul.CaptureIntoUndoContext(this);
                }
            }

            toInvokeOutsideLock = innerState =>
            {
                if (innerState == null)
                {
                    return;
                }

                var(observableListBase, enumerable, indexesInternal) =
                    (Tuple <ObservableListBase <T>, IEnumerable <T>, IEnumerable <int> >)innerState;

                observableListBase.RaiseCollectionChangedAddMultiple(
                    enumerable,
                    indexesInternal);
                observableListBase.RaisePropertyChanged(nameof(observableListBase.Count));
                observableListBase.ContentsMayHaveChanged();
            };

            state = new Tuple <ObservableListBase <T>, IEnumerable <T>, IEnumerable <int> >(
                this,
                items,
                indexes);

            break;
        }

        case ClearStateChange <T>(var originalItems):
        {
            foreach (T t in originalItems)
            {
                _ = InternalListContainer.Add(t);
            }

            if (ItemsAreUndoable && AutomaticallyCaptureSubItems)
            {
                foreach (IUndoableItem ul in originalItems.Cast <IUndoableItem>()
                         .Where(p => !p.IsCapturedIntoUndoContext))
                {
                    ul.CaptureIntoUndoContext(this);
                }
            }

            toInvokeOutsideLock = innerState =>
            {
                if (innerState == null)
                {
                    return;
                }

                var convertedState = (ObservableListBase <T>)innerState;

                convertedState.RaiseCollectionReset();
                convertedState.RaisePropertyChanged(nameof(convertedState.Count));
                convertedState.ContentsMayHaveChanged();
            };

            state = this;

            break;
        }

        case ChangeAtStateChange <T>(var index, var oldItem, var newItem):
        {
            InternalListContainer[index] = newItem;

            if (ItemsAreUndoable && AutomaticallyCaptureSubItems)
            {
                if (newItem is IUndoableItem {
                        IsCapturedIntoUndoContext : false
                    } ul)
                {
                    ul.CaptureIntoUndoContext(this);
                }

                if (oldItem is IUndoableItem {
                        IsCapturedIntoUndoContext : true
                    } ol&&
                    ol.ParentUndoContext == this)
                {
                    ol.ReleaseFromUndoContext();
                }
            }

            toInvokeOutsideLock = innerState =>
            {
                if (innerState == null)
                {
                    return;
                }

                (var observableListBase, T oldItemInternal, T newItemInternal, var indexInternal) =
                    (Tuple <ObservableListBase <T>, T, T, int>)innerState;

                observableListBase.RaiseCollectionChangedChanged(
                    oldItemInternal,
                    newItemInternal,
                    indexInternal);
                observableListBase.RaisePropertyChanged(nameof(observableListBase.Count));
                observableListBase.ContentsMayHaveChanged();
            };

            state = new Tuple <ObservableListBase <T>, T, T, int>(
                this,
                oldItem,
                newItem,
                index);

            break;
        }

        default:
        {
            toInvokeOutsideLock = null;
            state = null;

            return(false);
        }
        }

        return(true);
    }