public void HasRedoDataTest()
        {
            DocumentDataModel target = new DocumentDataModel();

            DocumentDataModelInvariant(target);
            target.New(new Size(700, 1200), new Thickness(32, 32, 32, 32));
            //Test if the property is false at initialisation.
            Assert.IsFalse(target.HasRedoData);

            //Test if the property is true after an undo
            target.AddShape(new XElement("TestTag"));
            target.Undo();
            Assert.IsTrue(target.HasRedoData);
            DocumentDataModelInvariant(target);
            Assert.AreEqual(DataModel.ModelState.Ready, target.State);

            //Test if the property is false after a redo.
            target.Redo();
            Assert.IsFalse(target.HasRedoData);
            DocumentDataModelInvariant(target);
            Assert.AreEqual(DataModel.ModelState.Ready, target.State);

            //Test if redo is cleared if a new element is added after undo
            target.Undo();
            target.AddShape(new XElement("TestTag"));
            Assert.IsFalse(target.HasRedoData);
            DocumentDataModelInvariant(target);
            Assert.AreEqual(DataModel.ModelState.Ready, target.State);
        }
        public void UndoTest()
        {
            DocumentDataModel target = new DocumentDataModel();

            target.New(new Size(700, 1200), new Thickness(32, 32, 32, 32));
            DocumentDataModelInvariant(target);
            Assert.AreEqual(DataModel.ModelState.Ready, target.State);

            XElement expected = new XElement(target.DocumentRoot);

            target.AddShape(new XElement("TestTag"));
            target.Undo();
            Assert.IsFalse(target.HasUndoData);
            AssertAreEqualStrings(expected, target.DocumentRoot);
            DocumentDataModelInvariant(target);
            Assert.AreEqual(DataModel.ModelState.Ready, target.State);
        }
        public void HasUnsavedDataTest()
        {
            DocumentDataModel target = new DocumentDataModel();

            target.New(new Size(700, 1200), new Thickness(32, 32, 32, 32));
            DocumentDataModelInvariant(target);
            Assert.AreEqual(DataModel.ModelState.Ready, target.State);
            Assert.IsFalse(target.HasUnsavedData);

            target.AddShape(new XElement("TestTag"));
            Assert.IsTrue(target.HasUnsavedData);
            DocumentDataModelInvariant(target);
            Assert.AreEqual(DataModel.ModelState.Ready, target.State);

            target.Undo(); //Undo should return the datamodel to a state with no unsaved data.
            Assert.IsFalse(target.HasUnsavedData);
            DocumentDataModelInvariant(target);
            Assert.AreEqual(DataModel.ModelState.Ready, target.State);
        }
        public void EndOperationTest()
        {
            DocumentDataModel target = new DocumentDataModel();

            target.New(new Size(700, 1200), new Thickness(32, 32, 32, 32));
            DocumentDataModelInvariant(target);
            Assert.AreEqual(DataModel.ModelState.Ready, target.State);
            Assert.IsFalse(target.HasUndoData);

            //Test that undo state is created at end of operation.
            XElement expected = new XElement(target.DocumentRoot);

            target.BeginOperation("testoperation");
            target.AddShape(new XElement("testelement"));
            target.EndOperation("testoperation");
            Assert.IsTrue(target.HasUndoData);
            DocumentDataModelInvariant(target);
            Assert.AreEqual(DataModel.ModelState.Ready, target.State);
            target.Undo(); //Undo should bring us back before the operation.
            AssertAreEqualStrings(expected, target.DocumentRoot);
        }
        public void PropertyChangedTest()
        {
            DocumentDataModel model = new DocumentDataModel();

            string[] watchedProperties = new string[] { "HasUnsavedData", "HasUndoData", "HasRedoData", "DocumentRoot", "ObservableDocumentRoot" };
            Dictionary <string, object> propertyValues    = new Dictionary <string, object>();
            HashSet <string>            changedProperties = new HashSet <string>();

            PropertyChangedEventHandler propChangedHandler = delegate(object sender, PropertyChangedEventArgs e)
            {
                Assert.AreSame(model, sender);
                changedProperties.Add(e.PropertyName);
            };

            ZeroArgDelegate prepare = delegate()
            {
                // Note old property values for later comparison.
                foreach (string prop in watchedProperties)
                {
                    propertyValues[prop] = model.GetType().GetProperty(prop).GetValue(model, null);
                }
                changedProperties.Clear();
            };

            ZeroArgDelegate verify = delegate()
            {
                // Verify that properties are unchanged, or that we were notified that they changed.
                foreach (string prop in watchedProperties)
                {
                    if (changedProperties.Contains(prop))
                    {
                        continue;                                   // We were notified of a change.
                    }
                    object oldValue = propertyValues[prop];
                    object newValue = model.GetType().GetProperty(prop).GetValue(model, null);
                    Assert.AreEqual(oldValue, newValue,
                                    "Property {0} changed without notification, from '{1}' to '{2}'",
                                    prop, oldValue, newValue);
                }
                DocumentDataModelInvariant(model);
            };

            model.PropertyChanged += propChangedHandler;


            prepare();
            model.New(new Size(100, 100), new Thickness(20));
            verify();
            // New should trigger updates on both DocumentRoot properties.
            Assert.IsTrue(changedProperties.Contains("DocumentRoot"));
            Assert.IsTrue(changedProperties.Contains("ObservableDocumentRoot"));

            prepare();
            model.AddShape(new XElement("Test"));
            verify();
            // A "deep" change of the document XML must not trigger updates on DocumentRoot, but only on ObservableDocumentRoot
            Assert.IsFalse(changedProperties.Contains("DocumentRoot"));
            Assert.IsTrue(changedProperties.Contains("ObservableDocumentRoot"));

            prepare();
            model.Undo();
            verify();
            // Undo should trigger updates on both DocumentRoot properties.
            Assert.IsTrue(changedProperties.Contains("DocumentRoot"));
            Assert.IsTrue(changedProperties.Contains("ObservableDocumentRoot"));

            prepare();
            model.Redo();
            verify();
            // Redo should trigger updates on both DocumentRoot properties.
            Assert.IsTrue(changedProperties.Contains("DocumentRoot"));
            Assert.IsTrue(changedProperties.Contains("ObservableDocumentRoot"));

            prepare();
            ((XElement)model.DocumentRoot.FirstNode).Name = "Test2";
            verify();
            // A "deep" change of the document XML must not trigger updates on DocumentRoot, but only on ObservableDocumentRoot
            Assert.IsFalse(changedProperties.Contains("DocumentRoot"));
            Assert.IsTrue(changedProperties.Contains("ObservableDocumentRoot"));

            // If we remove the handler, we should not get any notifications. :-)
            model.PropertyChanged -= propChangedHandler;
            prepare();
            model.Undo();

            Assert.AreEqual(0, changedProperties.Count); // No changes that we know of.
        }