示例#1
0
        /// <summary>
        /// This is invoked when the collection changes.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Collections.Specialized.NotifyCollectionChangedEventArgs"/> instance containing the event data.</param>
        /// <remarks>
        /// This method must be public because the <see cref="IWeakEventListener"/> is used.
        /// </remarks>
        public void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            Log.Debug("Automatically tracking change '{0}' of collection", e.Action);

            var undoList   = new List <CollectionChangeUndo>();
            var collection = (IList)sender;

            switch (e.Action)
            {
            case NotifyCollectionChangedAction.Add:
                undoList.AddRange(e.NewItems.Cast <object>().Select((item, i) => new CollectionChangeUndo(collection, CollectionChangeType.Add, -1, e.NewStartingIndex + i, null, item, Tag)));
                break;

            case NotifyCollectionChangedAction.Remove:
                undoList.AddRange(e.OldItems.Cast <object>().Select((item, i) => new CollectionChangeUndo(collection, CollectionChangeType.Remove, e.OldStartingIndex + i, -1, item, null, Tag)));
                break;

            case NotifyCollectionChangedAction.Replace:
                undoList.Add(new CollectionChangeUndo(collection, CollectionChangeType.Replace, e.OldStartingIndex, e.NewStartingIndex, e.OldItems[0], e.NewItems[0], Tag));
                break;

#if NET
            case NotifyCollectionChangedAction.Move:
                undoList.Add(new CollectionChangeUndo(collection, CollectionChangeType.Move, e.OldStartingIndex, e.NewStartingIndex, e.NewItems[0], e.NewItems[0], Tag));
                break;
#endif
            }

            foreach (var operation in undoList)
            {
                MementoService.Add(operation);
            }

            Log.Debug("Automatically tracked change '{0}' of collection", e.Action);
        }
示例#2
0
            public void MaximumSupportedOperationsTest()
            {
                var mementoService = new MementoService(5);
                var listUndoOps = new List<MockUndo>();

                for (var i = 0; i < 10; i++)
                {
                    var memento = new MockUndo() {Value = i};
                    mementoService.Add(memento);
                    listUndoOps.Add(memento);
                }

                var count = 0;
                while (mementoService.CanUndo)
                {
                    mementoService.Undo();
                    count++;
                }

                for (var i = 0; i < 5; i++)
                {
                    Assert.IsFalse(listUndoOps[i].UndoCalled);
                }

                for (var i = 5; i < 10; i++)
                {
                    Assert.IsTrue(listUndoOps[i].UndoCalled);
                }

                Assert.AreEqual(count, mementoService.MaximumSupportedBatches);
            }
示例#3
0
        /// <summary>
        /// Called when a property has changed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.ComponentModel.PropertyChangedEventArgs"/> instance containing the event data.</param>
        /// <remarks>
        /// This method must be public because the <see cref="IWeakEventListener"/> is used.
        /// </remarks>
        public void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            var modelBase = sender as ModelBase;

            if (modelBase != null)
            {
                if ((string.CompareOrdinal(e.PropertyName, "INotifyDataErrorInfo.HasErrors") == 0) ||
                    (string.CompareOrdinal(e.PropertyName, "INotifyDataWarningInfo.HasWarnings") == 0) ||
                    (string.CompareOrdinal(e.PropertyName, "IsDirty") == 0))
                {
                    return;
                }
            }

            if (ShouldPropertyBeIgnored(sender, e.PropertyName))
            {
                return;
            }

            var oldValue = _previousPropertyValues[e.PropertyName];
            var newValue = PropertyHelper.GetPropertyValue(sender, e.PropertyName, false);

            // CTL-719: ignore duplicate properties
            if (ObjectHelper.AreEqual(oldValue, newValue))
            {
                return;
            }

            _previousPropertyValues[e.PropertyName] = newValue;

            MementoService.Add(new PropertyChangeUndo(sender, e.PropertyName, oldValue, newValue, Tag));
        }
示例#4
0
        /// <summary>
        /// Called when a property has changed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.ComponentModel.PropertyChangedEventArgs"/> instance containing the event data.</param>
        /// <remarks>
        /// This method must be public because the <see cref="IWeakEventListener"/> is used.
        /// </remarks>
        public void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            var modelBase = sender as ModelBase;

            if (modelBase != null)
            {
                if ((string.CompareOrdinal(e.PropertyName, "INotifyDataErrorInfo.HasErrors") == 0) ||
                    (string.CompareOrdinal(e.PropertyName, "INotifyDataWarningInfo.HasWarnings") == 0) ||
                    (string.CompareOrdinal(e.PropertyName, "IsDirty") == 0))
                {
                    return;
                }
            }

            if (ShouldPropertyBeIgnored(sender, e.PropertyName))
            {
                return;
            }

            object oldValue = _previousPropertyValues[e.PropertyName];

            _previousPropertyValues[e.PropertyName] = PropertyHelper.GetPropertyValue(sender, e.PropertyName);
            object newValue = _previousPropertyValues[e.PropertyName];

            MementoService.Add(new PropertyChangeUndo(sender, e.PropertyName, oldValue, newValue, Tag));
        }
            public void SetsValuesCorrectly()
            {
                var obj = new Mocks.MockModel();
                var tag = "MyTag";

                var service = new MementoService();
                var observer = new ObjectObserver(obj, tag, service);

                Assert.AreEqual(tag, observer.Tag);
            }
示例#6
0
            public void CallActions()
            {
                var value = false;
                var mementoService = new MementoService();
                var action = new ActionUndo(this, () => value = true, () => value = false);

                mementoService.Add(action);
                Assert.IsFalse(value);

                mementoService.Undo();
                Assert.IsTrue(value);

                mementoService.Redo();
                Assert.IsFalse(value);
            }
            public void CorrectlyIgnoresDuplicatePropertyChangesWithEqualValues()
            {
                var obj = new Mocks.MockModel();
                
                var service = new MementoService();
                var observer = new ObjectObserver(obj, mementoService: service);

                Assert.AreEqual(0, service.UndoBatches.Count());

                obj.Value = "A";

                Assert.AreEqual(1, service.UndoBatches.Count());

                obj.Value = "A";

                Assert.AreEqual(1, service.UndoBatches.Count());
            }
示例#8
0
            public void BeginsNewBatchWhenThereAlreadyIsABatch()
            {
                var mementoService = new MementoService();
                var model = new MockModel();

                var firstBatch = mementoService.BeginBatch("FirstBatch");
                mementoService.Add(new PropertyChangeUndo(model, "Value", model.Value));
                Assert.AreEqual(1, firstBatch.ActionCount);

                var secondBatch = mementoService.BeginBatch("SecondBatch");
                mementoService.Add(new PropertyChangeUndo(model, "Value", model.Value));
                Assert.AreEqual(1, secondBatch.ActionCount);

                // Also check if the first batch was closed
                Assert.AreEqual(1, mementoService.UndoBatches.Count());
                Assert.AreEqual(1, firstBatch.ActionCount);
            }
示例#9
0
            public void ClearsCurrentUndoRedoStackForInstance()
            {
                var obj = new MockModel {Value = "value1"};
                var service = new MementoService();

                service.RegisterObject(obj);

                obj.Value = "newvalue1";
                Assert.IsFalse(service.CanRedo);

                service.UnregisterObject(obj);

                Assert.IsFalse(service.CanUndo);
            }
示例#10
0
            public void UndoTest()
            {
                var mementoService = new MementoService();
                var undo1 = new MockUndo();
                var undo2 = new MockUndo();

                mementoService.Add(undo1);
                mementoService.Add(undo2);

                mementoService.Undo();
                Assert.IsTrue(undo2.UndoCalled);
                Assert.IsFalse(undo1.UndoCalled);
                Assert.IsTrue(mementoService.CanUndo);
            }
示例#11
0
            public void SetProperty()
            {
                var instance = new IniEntry();
                var action = new PropertyChangeUndo(instance, "Key", "previousValue", "nextValue");
                var mementoService = new MementoService();

                mementoService.Add(action);
                Assert.AreEqual(IniEntry.KeyProperty.GetDefaultValue(), instance.Key);

                mementoService.Undo();
                Assert.AreEqual("previousValue", instance.Key);

                mementoService.Redo();
                Assert.AreEqual("nextValue", instance.Key);
            }
示例#12
0
            public void PreventsAdditionsWhenDisabled()
            {
                var mementoService = new MementoService();
                mementoService.IsEnabled = false;

                var undo1 = new MockUndo(true);
                mementoService.Add(undo1);

                Assert.IsFalse(mementoService.CanRedo);
            }
示例#13
0
            public void HandlesDoubleUndo()
            {
                var obj = new MockModel {Value = "value1"};
                var service = new MementoService();

                service.RegisterObject(obj);

                obj.Value = "value2";
                obj.Value = "value3";

                service.Undo();
                Assert.AreEqual("value2", obj.Value);

                service.Undo();
                Assert.AreEqual("value1", obj.Value);
            }
示例#14
0
            public void IsTrueByDefault()
            {
                var mementoService = new MementoService();

                Assert.IsTrue(mementoService.IsEnabled);
            }
示例#15
0
            public void CanUndoTest()
            {
                var mementoService = new MementoService();
                Assert.IsFalse(mementoService.CanUndo);

                mementoService.Add(new MockUndo());
                Assert.IsTrue(mementoService.CanUndo);

                mementoService.Undo();
                Assert.IsFalse(mementoService.CanUndo);
            }
示例#16
0
 public void ExpectDefaultMaximumSupportedActionsValue()
 {
     var mementoService = new MementoService();
     Assert.AreEqual(300, mementoService.MaximumSupportedBatches);
 }
示例#17
0
            public void ThrowsArgumentNullExceptionForNullInstance()
            {
                var service = new MementoService();

                ExceptionTester.CallMethodAndExpectException<ArgumentNullException>(() => service.UnregisterObject(null));
            }
示例#18
0
            public void CancelsSubscriptionForInstance()
            {
                var obj = new MockModel {Value = "value1"};
                var service = new MementoService();

                service.RegisterObject(obj);
                service.UnregisterObject(obj);

                obj.Value = "newvalue";

                Assert.IsFalse(service.CanUndo);
            }