|
using System;
using System.Collections;
using System.IO;
using Wxv.Wml;
using Wxv.Wml.IO;
using Wxv.Wml.Serialization;
namespace Wxv.WmlDemo
{
public delegate void DataDocumentModified ();
public class DataObjectDifferences
{
private string modifyCommandName;
public string ModifyCommandName { get { return modifyCommandName; } }
private bool dirtyBefore;
public bool DirtyBefore { get { return dirtyBefore; } }
private WmlDocument redoDifferences;
public WmlDocument RedoDifferences { get { return redoDifferences; } }
private WmlDocument undoDifferences;
public WmlDocument UndoDifferences { get { return undoDifferences; } }
public DataObjectDifferences (string modifyCommandName, bool dirtyBefore, WmlDocument redoDifferences, WmlDocument undoDifferences)
{
this.modifyCommandName = modifyCommandName;
this.dirtyBefore = dirtyBefore;
this.redoDifferences = redoDifferences;
this.undoDifferences = undoDifferences;
}
}
public class DataDocument
{
public const int MaxDifferencesCount = 20;
private WmlDocument previousDataObject;
private DataObject dataObject = new DataObject();
public DataObject DataObject
{
get { return dataObject; }
}
private bool dirty;
public bool Dirty { get { return dirty; } }
private ArrayList differences = new ArrayList();
private int differencesIndex = 0;
private string modifyCommandName;
private int modifyCount;
public event DataDocumentModified OnModified;
public DataDocument()
{
previousDataObject = WmlSerializer.Serialize (dataObject);
}
public void BeginModifyCommand (string modifyCommandName)
{
if (modifyCount == 0)
this.modifyCommandName = modifyCommandName;
modifyCount++;
}
public void EndModifyCommand()
{
if (modifyCount == 0)
throw new Exception ("Mismatched call to EndModify");
modifyCount--;
if (modifyCount != 0)
return;
if (!BuildDifferences())
return; // no modifications made
dirty = true;
RaiseOnModified ();
}
private bool BuildDifferences()
{
WmlDocument redoDifferences = WmlSerializer.Compare (previousDataObject, dataObject, false);
// no differences
if (redoDifferences.Count == 0)
return false;
WmlDocument undoDifferences = WmlSerializer.Compare (dataObject, previousDataObject, false);
// remove the undo/redo steps ahead of the current index
while (differencesIndex < differences.Count)
differences.RemoveAt (differencesIndex);
// add the differences to the list
differences.Add (new DataObjectDifferences (modifyCommandName, dirty, redoDifferences, undoDifferences));
if (differences.Count > MaxDifferencesCount)
differences.RemoveAt (0);
else
differencesIndex++;
// update the previous data object
WmlSerializer.Combine (redoDifferences, previousDataObject, false);
return true;
}
private void RaiseOnModified ()
{
if (OnModified != null)
OnModified ();
}
public bool CanUndo
{
get { return ((differencesIndex - 1) >= 0) && ((differencesIndex - 1) < differences.Count); }
}
public DataObjectDifferences CurrentUndoDifference
{
get
{
if (CanUndo)
return (DataObjectDifferences) differences [differencesIndex - 1];
else
return null;
}
}
public void Undo()
{
if (!CanUndo)
return;
DataObjectDifferences differences = CurrentUndoDifference;
dirty = differences.DirtyBefore;
// roll back the data object
WmlSerializer.Combine (differences.UndoDifferences, dataObject, false);
// roll back the previous data object (which is still the same as the data object)
WmlSerializer.Combine (differences.UndoDifferences, previousDataObject, false);
differencesIndex--;
RaiseOnModified ();
}
public bool CanRedo
{
get { return (differencesIndex >= 0) && (differencesIndex < differences.Count); }
}
public DataObjectDifferences CurrentRedoDifference
{
get
{
if (CanRedo)
return (DataObjectDifferences) differences [differencesIndex];
else
return null;
}
}
public void Redo()
{
if (!CanRedo)
return;
DataObjectDifferences differences = CurrentRedoDifference;
dirty = true; // rolling forward always makes it dirty, because a save resets the undo/redo differences
// roll forward the data object
WmlSerializer.Combine (differences.RedoDifferences, dataObject, false);
// roll forward the previous data object (which is still the same as the data object)
WmlSerializer.Combine (differences.RedoDifferences, previousDataObject, false);
differencesIndex++;
RaiseOnModified ();
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
Im a Software Developer working in Auckland, New Zealand. When i was a lot shorter, i started programming in Atari Basic, though these days its mostly C#, and a bit of java (mostly the caffinated kind).