Imports EnvDTE
Imports System

Public Module UndoContexts

    Private output As OutputWindowPane = GetOutputWindowPane("UndoContext Macros")


    Sub StackLinkage(Optional ByVal strictLinkage As String = "False")
        ' Description: Makes changes to three documents within either a
        '              strict or nonstrict undo context

        Dim strict As Boolean
        Dim caption As String

        Try
            strict = Convert.ToBoolean(strictLinkage)
        Catch ex As Exception
            strict = False
        End Try

        ' Determine the window captions
        If strict Then
            caption = "Strict"
        Else
            caption = "Nonstrict"
        End If

        Dim txtDoc(3) As TextDocument
        Dim editPnt(3) As EditPoint
        Dim i As Integer

        ' Open three documents for editing
        For i = 1 To 3
            txtDoc(i) = GetTextDocument(caption & i.ToString())
            editPnt(i) = txtDoc(i).StartPoint.CreateEditPoint
        Next

        Try
            DTE.UndoContext.Open(caption & "Linkage", strict)

            For i = 1 To 3
                editPnt(i).Insert("Changes to " & caption & i.ToString())
            Next

            DTE.UndoContext.Close()
        Catch
        End Try
    End Sub


    '''
    ''' UndoContext Polling example
    '''
    <System.ContextStaticAttribute()> Public WithEvents UndoTimer As System.Timers.Timer

    Sub UndoContextTimer()
        ' Description: If undo context is busy, creates a timer that  
        '              polls the UndoContext.IsOpen property until the
        '              undo context becomes free

        ' Start timer if undo context is busy
        If Not AddText() Then
            UndoTimer = New System.Timers.Timer
            UndoTimer.Interval = 100
            UndoTimer.Enabled = True
        End If
    End Sub

    Private Function AddText() As Boolean
        ' Description: Adds text to the "Text File" document within 
        '              the "Timer" undo context

        Dim success As Boolean = True

        Try
            ' Open the undo context
            DTE.UndoContext.Open("Timer")

            ' Open the "Text File" document for editing
            Dim txtDoc As TextDocument = GetTextDocument("Text File")
            Dim editPnt As EditPoint = txtDoc.StartPoint.CreateEditPoint

            ' Add some text
            editPnt.Insert("Here's text in the 'Timer' undo context." & System.Environment.NewLine)

            ' Close the undo context
            DTE.UndoContext.Close()
        Catch
            success = False
        End Try

        Return success
    End Function

    Public Sub UndoTimer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles UndoTimer.Elapsed
        ' Check whether the undo context is free
        If Not DTE.UndoContext.IsOpen Then
            UndoTimer.Enabled = False

            ' Kill timer if AddText is successful, otherwise re-enable it
            If AddText() Then
                UndoTimer.Dispose()
                UndoTimer = Nothing
            Else
                UndoTimer.Enabled = True
            End If
        End If
    End Sub


    '''
    ''' Miscellaneous macros
    '''
    Sub DisplayIsOpen()
        ' Description: Displays whether the undo context is open

        output.OutputString("UndoContext.IsOpen = " & DTE.UndoContext.IsOpen.ToString() & vbCrLf)
    End Sub

    Sub CloseUndoContext()
        ' Description: Closes the undo context

        Try
            DTE.UndoContext.Close()
        Catch
        End Try
    End Sub

    Sub TestAbortAndClose()
        ' Description: Demonstrates that SetAbort closes the undo context automatically

        Try
            DTE.UndoContext.Open("AbortAndClose")
            DTE.UndoContext.SetAborted()

            Try
                ' SetAborted closed the undo context, so
                ' this statement throws an exception
                DTE.UndoContext.Close()
            Catch e As Exception
                output.OutputString("Error: " & e.Message & vbCrLf)
            End Try
        Catch
        End Try
    End Sub

End Module
