open System
open System.Collections.Generic
[<AbstractClass>]
type UndoableCommand(description:string) =
member this.Description = description
abstract Execute : unit->unit
abstract Undo : unit->unit
//Property changes by the class via a ref
type PropertyChangedUndoableCommand<'a>(description, fieldRef, newValue:'a) =
inherit UndoableCommand(description)
let oldValue = !fieldRef
override this.Execute() = fieldRef:=newValue
override this.Undo() = fieldRef:=oldValue
type DelegateUndoableCommand(description, doAction, undoAction) =
inherit UndoableCommand(description)
override this.Execute() = doAction()
override this.Undo() = undoAction()
//Document contains an example undo/redo stack
type Document() =
let undoStack = Stack()
let redoStack = Stack()
let execute (command : UndoableCommand) =
redoStack.Clear()
undoStack.Push(command)
command.Execute()
//Undo Implementation
let undo() =
if undoStack.Count > 0 then
let command = undoStack.Pop()
redoStack.Push(command)
command.Undo()
//Redo Implementation
let redo() =
if redoStack.Count> 0 then
let command = redoStack.Pop()
undoStack.Push(command)
command.Execute()
member this.ExecuteCommand command = execute command
member this.Undo() = undo()
member this.Redo() = redo()
member this.CanUndo = undoStack.Count > 0
member this.CanRedo = redoStack.Count > 0
type SomeObject(document:Document) =
let undovalue = ref 50//initial value is 50
member this.UndoableProperty with get() = !undovalue
and set(value) =
let command = PropertyChangedUndoableCommand("Changed", undovalue, value)
document.ExecuteCommand(command)
//Document object hold "do" and "Undone" values
let doc = Document()
let so = SomeObject(doc)
printf "Initial Value %d\n\n" so.UndoableProperty
so.UndoableProperty <- 100
printf "Updated Value %d\n\n" so.UndoableProperty
so.UndoableProperty <- 1000
printf "Updated Value %d\n\n" so.UndoableProperty
doc.Undo()
printf "Undo Value %d\n\n" so.UndoableProperty
doc.Undo()
printf "Undo Value %d\n\n" so.UndoableProperty
doc.Undo()
printf "Undo Value %d\n\n" so.UndoableProperty
doc.Undo()
printf "Undo Value %d\n\n" so.UndoableProperty
doc.Redo()
printf "Redo Value %d\n\n" so.UndoableProperty
doc.Redo()
printf "Redo Value %d\n\n" so.UndoableProperty
doc.Redo()
printf "Redo Value %d\n\n" so.UndoableProperty
System.Console.ReadLine()|>ignore