'******************************************************************************************************************
' Undo/Redo framework (c) Copyright 2009 Etienne Nijboer
'******************************************************************************************************************
Public MustInherit Class BaseUndoRedoMonitor
Public Sub New(ByVal AUndoRedoManager As UndoRedoManager)
_UndoRedoManager = AUndoRedoManager
End Sub
Private _UndoRedoManager As UndoRedoManager
Public Property UndoRedoManager() As UndoRedoManager
Get
Return _UndoRedoManager
End Get
Set(ByVal value As UndoRedoManager)
_UndoRedoManager = value
End Set
End Property
Public ReadOnly Property isUndoing() As Boolean
Get
Return UndoRedoManager.isUndoing
End Get
End Property
Public ReadOnly Property isRedoing() As Boolean
Get
Return UndoRedoManager.isRedoing
End Get
End Property
Public ReadOnly Property isPerformingUndoRedo() As Boolean
Get
Return UndoRedoManager.isPerformingUndoRedo
End Get
End Property
Public Sub AddCommand(ByVal UndoRedoCommandType As UndoRedoCommandType, ByVal UndoRedoCommand As BaseUndoRedoCommand)
UndoRedoManager.AddCommand(UndoRedoCommandType, UndoRedoCommand)
End Sub
Public MustOverride Function Monitor(ByVal AControl As Control) As Boolean
End Class
'****************************************************************************************************************
' SimpleControl
' Controls: TextBox, ComboBox, DateTimePicker, NumericUpDown, MaskedTextBox
'****************************************************************************************************************
Public Class SimpleControlMonitor : Inherits BaseUndoRedoMonitor
Private Data As String
Public Sub New(ByVal AUndoRedoManager As UndoRedoManager)
MyBase.New(AUndoRedoManager)
End Sub
Public Overrides Function Monitor(ByVal AControl As System.Windows.Forms.Control) As Boolean
If TypeOf AControl Is TextBox Or _
TypeOf AControl Is ComboBox Or _
TypeOf AControl Is DateTimePicker Or _
TypeOf AControl Is NumericUpDown Or _
TypeOf AControl Is MaskedTextBox Then
AddHandler AControl.Enter, AddressOf Control_Enter
AddHandler AControl.Leave, AddressOf Control_Leave
Return True
End If
Return False
End Function
Private Sub Control_Enter(ByVal sender As System.Object, ByVal e As System.EventArgs)
Data = CType(sender, Control).Text
End Sub
Private Sub Control_Leave(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim CurrentData As String = CType(sender, Control).Text
If Not String.Equals(CurrentData, Data) Then
AddCommand(UndoRedoCommandType.ctUndo, New SimpleControlUndoRedoCommand(Me, sender, Data))
End If
End Sub
End Class
'****************************************************************************************************************
' ListBox
'****************************************************************************************************************
Public Class ListBoxMonitor : Inherits BaseUndoRedoMonitor
Private Data As Object
Public Sub New(ByVal AUndoRedoManager As UndoRedoManager)
MyBase.New(AUndoRedoManager)
End Sub
Public Overrides Function Monitor(ByVal AControl As System.Windows.Forms.Control) As Boolean
If TypeOf AControl Is ListBox Then
AddHandler AControl.Enter, AddressOf Control_Enter
AddHandler CType(AControl, ListBox).SelectedIndexChanged, AddressOf Control_Changed
Return True
End If
Return False
End Function
Public Function GetSelected(ByVal AListBox As Object) As String
Dim Indices As List(Of String) = New List(Of String)
For Each itemIndex As Integer In CType(AListBox, ListBox).SelectedIndices
Indices.Add(CStr(itemIndex + 1))
Next
Return String.Join(",", Indices.ToArray)
End Function
Public Sub RestoreSelected(ByVal AListBox As Object, ByVal ASelection As String)
If Not String.IsNullOrEmpty(ASelection) Then
Dim Indices As List(Of Integer) = New List(Of Integer)(Array.ConvertAll(ASelection.Split(","), New Converter(Of String, Integer)(AddressOf Integer.Parse)))
Dim Control As ListBox = CType(AListBox, ListBox)
Select Case Control.SelectionMode
Case SelectionMode.None
Case SelectionMode.One
Control.SetSelected(Indices(0) - 1, True)
Case SelectionMode.MultiSimple, SelectionMode.MultiExtended
For index As Integer = 0 To Control.Items.Count - 1
Control.SetSelected(index, Indices.IndexOf(index + 1) >= 0)
Next
End Select
Else
CType(AListBox, ListBox).ClearSelected()
End If
End Sub
Private Sub Control_Changed(ByVal sender As System.Object, ByVal e As System.EventArgs)
' Events that are also fired when the undo/redo value is changed by code, like change events,
' it is important to make sure that no undo/redo command is added when performing a undo/redo action.
If Not isPerformingUndoRedo Then
Dim CurrentData As String = GetSelected(sender)
If Not String.Equals(Data, CurrentData) Then
AddCommand(UndoRedoCommandType.ctUndo, New ListBoxUndoRedoCommand(Me, sender, Data))
Data = CurrentData
End If
End If
End Sub
Private Sub Control_Enter(ByVal sender As System.Object, ByVal e As System.EventArgs)
Data = GetSelected(sender)
End Sub
End Class
'****************************************************************************************************************
' CheckBox
'****************************************************************************************************************
Public Class CheckBoxMonitor : Inherits BaseUndoRedoMonitor
Private Data As CheckState
Public Sub New(ByVal AUndoRedoManager As UndoRedoManager)
MyBase.New(AUndoRedoManager)
End Sub
Public Overrides Function Monitor(ByVal AControl As System.Windows.Forms.Control) As Boolean
If TypeOf AControl Is CheckBox Then
AddHandler AControl.Enter, AddressOf Control_Enter
AddHandler AControl.Leave, AddressOf Control_Leave
Return True
End If
Return False
End Function
Private Sub Control_Enter(ByVal sender As System.Object, ByVal e As System.EventArgs)
Data = CType(sender, CheckBox).CheckState
End Sub
Private Sub Control_Leave(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim CurrentData As CheckState = CType(sender, CheckBox).CheckState
If Data <> CurrentData Then
AddCommand(UndoRedoCommandType.ctUndo, New CheckBoxUndoRedoCommand(Me, sender, Data))
End If
End Sub
End Class
'****************************************************************************************************************
' RadioButton
'****************************************************************************************************************
Public Class RadioButtonMonitor : Inherits BaseUndoRedoMonitor
Private Data As RadioButton
Public Sub New(ByVal AUndoRedoManager As UndoRedoManager)
MyBase.New(AUndoRedoManager)
End Sub
Public Overrides Function Monitor(ByVal AControl As System.Windows.Forms.Control) As Boolean
If TypeOf AControl Is RadioButton Then
AddHandler CType(AControl, RadioButton).CheckedChanged, AddressOf Control_CheckedChanged
Return True
End If
Return False
End Function
Private Sub Control_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
' Events that are also fired when the undo/redo value is changed by code, like change events,
' it is important to make sure that no undo/redo command is added when performing a undo/redo action.
If Not isPerformingUndoRedo Then
If CType(sender, RadioButton).Checked Then
AddCommand(UndoRedoCommandType.ctUndo, New RadioButtonUndoRedoCommand(Me, sender, Data))
Else
Data = sender
End If
End If
End Sub
End Class
'****************************************************************************************************************
' MonthCalendar
'****************************************************************************************************************
Public Class MonthCalendarMonitor : Inherits BaseUndoRedoMonitor
Private Data As SelectionRange
Public Sub New(ByVal AUndoRedoManager As UndoRedoManager)
MyBase.New(AUndoRedoManager)
End Sub
Public Overrides Function Monitor(ByVal AControl As System.Windows.Forms.Control) As Boolean
If TypeOf AControl Is MonthCalendar Then
AddHandler AControl.Enter, AddressOf Control_Enter
AddHandler CType(AControl, MonthCalendar).DateSelected, AddressOf Control_DateSelected
Return True
End If
Return False
End Function
Private Sub Control_Enter(ByVal sender As System.Object, ByVal e As System.EventArgs)
Data = CType(sender, MonthCalendar).SelectionRange
End Sub
Private Sub Control_DateSelected(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DateRangeEventArgs)
' Events that are also fired when the undo/redo value is changed by code, like selected events,
' it is important to make sure that no undo/redo command is added when performing a undo/redo action.
If Not isPerformingUndoRedo Then
Dim CurrentData As SelectionRange = CType(sender, MonthCalendar).SelectionRange
If Not SelectionRange.Equals(Data, CurrentData) Then
AddCommand(UndoRedoCommandType.ctUndo, New MonthCalendarUndoRedoCommand(Me, sender, Data))
Data = CurrentData
End If
End If
End Sub
End Class