Monorepo/Controls.DocumentViewer/DocumentViewer.vb
2023-04-12 11:00:11 +02:00

716 lines
24 KiB
VB.net

Imports System.IO
Imports DevExpress
Imports DevExpress.Spreadsheet
Imports DevExpress.XtraRichEdit.Commands
Imports DevExpress.Office.Utils
Imports GdPicture14
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.Messaging
Imports DigitalData.Modules.Config
Public Class DocumentViewer
Private Enum ZoomMode
Zoom50
Zoom100
Zoom150
Zoom200
ZoomSelectedArea
ZoomFitToViewer
ZoomFitWidth
ZoomFitHeight
End Enum
Private Enum ViewerMode
GDPicture
RichText
Excel
End Enum
Private Enum FileLoadMode
File
Stream
End Enum
Private _logConfig As LogConfig
Private _logger As Logger
Private _Config As ConfigManager(Of Config)
Private _email As Email2
Private _ViewerMode As ViewerMode
Private _licenseKey As String = String.Empty
Private _licenseManager As New GdPicture14.LicenseManager()
Private _Search As Search
Private _Annotations As Annotations
Private _AnnotationsPending As Boolean = False
Private _hide_file_info_from_user As Boolean = False
Private _FileStream As Stream
Private _FilePath As String
Private _Fileinfo As FileInfo
Private _FileLoadMode As FileLoadMode = FileLoadMode.File
' List of all created temp files when converting msg files
Private _TempFiles As New List(Of String)
Private Sub DocumentViewer_Load(sender As Object, e As EventArgs) Handles Me.Load
UpdateMainUi()
End Sub
Public Property FileLoaded As Boolean = False
Public ReadOnly Property AnnotationsSaved As Boolean
Get
Return Not _AnnotationsPending
End Get
End Property
''' <summary>
''' Initialize the Viewer
''' </summary>
''' <param name="pLogConfig">A LogConfig object</param>
''' <param name="pLicenseKey">The GDPicture.NET License Key</param>
Public Sub Init(pLogConfig As LogConfig, pLicenseKey As String)
_logConfig = pLogConfig
_logger = pLogConfig.GetLogger()
_email = New Email2(pLogConfig)
_licenseKey = pLicenseKey
_licenseManager.RegisterKEY(_licenseKey)
_Annotations = New Annotations(pLogConfig)
_Search = New Search(pLogConfig, GdViewer)
Dim oConfigPath = ConfigPath()
_Config = New ConfigManager(Of Config)(pLogConfig, oConfigPath)
End Sub
''' <summary>
''' Load a file from a path and display it
''' </summary>
Public Sub LoadFile(FilePath As String)
FileLoaded = False
If _licenseKey = String.Empty Then
_logger.Warn("License key was not provided. File {0} not loaded.", FilePath)
Exit Sub
End If
If FilePath Is Nothing OrElse FilePath.Trim().Length = 0 Then
_logger.Warn("FilePath was not provided. File not loaded.")
Exit Sub
End If
_FilePath = FilePath
_FileLoadMode = FileLoadMode.File
_Fileinfo = New FileInfo(FilePath)
_logger.Info("Loading File [{0}] from Filesystem", FilePath)
FileLoaded = DoLoadFile(FilePath)
SetViewerMode(_Fileinfo.Extension)
UpdateMainUi()
End Sub
''' <summary>
''' Load a file from a stream and display it
''' </summary>
Public Sub LoadFile(FileName As String, Stream As Stream)
FileLoaded = False
If _licenseKey = String.Empty Then
_logger.Warn("License key was not provided. File [{0}] not loaded.", FileName)
Exit Sub
End If
Dim oExtension As String = FileName.Substring(FileName.LastIndexOf("."))
_FileStream = Stream
_FileLoadMode = FileLoadMode.Stream
_logger.Info("Loading file [{0}] from Stream", FileName)
FileLoaded = DoLoadFile(Stream, oExtension)
SetViewerMode(oExtension)
UpdateMainUi()
End Sub
Private Sub SearchFile(pSearchQuery As String)
End Sub
''' <summary>
''' Terminate Viewer, freeing up resources and deleting temp files
''' </summary>
Public Sub Done()
Try
_logger.Debug("Done: Deleting Temp Files")
DeleteTempFiles()
_logger.Debug("Done: Closing Documents")
FreeFile()
_logger.Debug("Done: Triggering GC")
GC.Collect()
Catch ex As Exception
_logger.Warn("Error while cleaning up DocumentViewer")
_logger.Error(ex)
End Try
End Sub
Public Function AddAnnotation(pText As String) As Boolean
Dim oFontStyle = FontStyle.Regular
Dim oFontColor = Color.Black
Dim oFontFamily = "Arial"
Dim oFontSize = 8
Dim oBorderColor = Color.Red
Dim oBackColor = Color.LightYellow
Dim oOpacity = 1.0F
Dim oRotation = 0.0F
GdViewer.AddTextAnnotationInteractive(pText, oFontColor, oFontFamily, oFontStyle, oFontSize, Fill:=True, oBorderColor, oBackColor, oOpacity, oRotation)
_AnnotationsPending = True
Return True
End Function
Public Function Save() As Boolean
Dim oSaveResult As GdPictureStatus = GdPictureStatus.OK
If GdViewer.BurnAnnotationsToPage(True, False) = GdPictureStatus.OK Then
If _FileLoadMode = FileLoadMode.Stream Then
oSaveResult = GdViewer.SaveDocumentToPDF(_FileStream)
Else
oSaveResult = GdViewer.SaveDocumentToPDF(_FilePath)
End If
End If
If oSaveResult = GdPictureStatus.OK Then
_AnnotationsPending = False
Return True
Else
Return False
End If
End Function
Public Sub CloseDocument()
Try
GdViewer.CloseDocument()
UpdateMainUi()
Catch ex As Exception
_logger.Error(ex)
End Try
End Sub
''' <summary>
''' Configures the viewer to hide the file path to the end-user.
''' </summary>
''' <param name="ViewOnly">
''' True means that all file info should be hidden from the end-user
''' False means the end user may see the filepath or other info about the file
''' </param>
Public Sub SetViewOnly(ViewOnly As Boolean)
If ViewOnly Then
buttonPrint.Visibility = XtraBars.BarItemVisibility.Never
Else
buttonPrint.Visibility = XtraBars.BarItemVisibility.Always
End If
_hide_file_info_from_user = ViewOnly
End Sub
Public Sub SetAllowAnnotations(AllowAnnotations As Boolean)
End Sub
''' <summary>
''' DEPRECATED: Use SetViewOnly
''' </summary>
Public Sub RightViewOnly(ViewOnly As Boolean)
SetViewOnly(ViewOnly)
End Sub
''' <summary>
''' DEPRECATED: Use SetViewOnly
''' </summary>
Public Sub RightOnlyView(ViewOnly As Boolean)
SetViewOnly(ViewOnly)
End Sub
#Region "Form Events"
Private Sub btnFitWidth_Click(ByVal sender As Object, ByVal e As EventArgs) Handles buttonFitWidth.ItemClick
FitToWidth()
_Config.Config.PageFit = Config.PageFitSetting.FitWidth
_Config.Save()
End Sub
Private Sub btnFitPage_Click(ByVal sender As Object, ByVal e As EventArgs) Handles buttonFitPage.ItemClick
FitToPage()
_Config.Config.PageFit = Config.PageFitSetting.FitPage
_Config.Save()
End Sub
Private Sub RichEditControl1_SizeChanged(sender As Object, e As EventArgs) Handles RichEditControl1.SizeChanged
Dim oControlWidth = RichEditControl1.Width - 100
Dim oPageWidth = Units.DocumentsToPixelsF(RichEditControl1.Document.Sections(0).Page.Width, RichEditControl1.DpiX)
RichEditControl1.Views.PrintLayoutView.ZoomFactor = oControlWidth / oPageWidth
End Sub
Private Sub btnOpen_Click(sender As Object, e As EventArgs)
GdViewer.ZoomMode = ViewerZoomMode.ZoomModeWidthViewer
GdViewer.DocumentAlignment = ViewerDocumentAlignment.DocumentAlignmentTopCenter
If OpenFileDialog.ShowDialog() = DialogResult.OK Then
GdViewer.DisplayFromFile(OpenFileDialog.FileName)
End If
GdViewer.Focus()
UpdateMainUi()
End Sub
Private Sub btnFirstPage_Click(ByVal sender As System.Object, ByVal e As EventArgs) Handles buttonFirstPage.ItemClick
GdViewer.DisplayFirstPage()
End Sub
Private Sub btnPreviousPage_Click(ByVal sender As System.Object, ByVal e As EventArgs) Handles buttonPrevPage.ItemClick
If _ViewerMode = ViewerMode.GDPicture Then
GdViewer.DisplayPreviousPage()
ElseIf _ViewerMode = ViewerMode.RichText Then
Dim oCmd As New PreviousPageCommand(RichEditControl1)
oCmd.Execute()
End If
End Sub
Private Sub btnNextPage_Click(ByVal sender As System.Object, ByVal e As EventArgs) Handles buttonNextPage.ItemClick
If _ViewerMode = ViewerMode.GDPicture Then
GdViewer.DisplayNextPage()
ElseIf _ViewerMode = ViewerMode.RichText Then
Dim oCmd As New NextPageCommand(RichEditControl1)
oCmd.Execute()
End If
End Sub
Private Sub btnLastPage_Click(ByVal sender As System.Object, ByVal e As EventArgs) Handles buttonLastPage.ItemClick
GdViewer.DisplayLastPage()
End Sub
Private Sub tbCurrentPage_Leave(ByVal sender As System.Object, ByVal e As EventArgs) Handles txtCurrentPage.EditValueChanged
Dim page As Integer = 0
If Integer.TryParse(txtCurrentPage.EditValue, page) Then
If page > 0 And page <= GdViewer.PageCount Then
GdViewer.DisplayPage(page)
UpdateaNavigationToolbar()
End If
End If
End Sub
Private Sub GdViewer1_PageChanged() Handles GdViewer.PageChanged
UpdateaNavigationToolbar()
End Sub
Private Sub GdViewer1_AfterZoomChange() Handles GdViewer.AfterZoomChange
UpdateaNavigationToolbar()
If GdViewer.MouseMode = ViewerMouseMode.MouseModeAreaZooming Then
GdViewer.MouseMode = ViewerMouseMode.MouseModePan
End If
End Sub
Private Sub btnZoomOut_Click(sender As Object, e As EventArgs) Handles buttonZoomOut.ItemClick
If _ViewerMode = ViewerMode.GDPicture Then
GdViewer.ZoomOUT()
ElseIf _ViewerMode = ViewerMode.RichText Then
Dim oCmd As New ZoomOutCommand(RichEditControl1)
oCmd.Execute()
End If
End Sub
Private Sub btnZoomIn_Click(sender As Object, e As EventArgs) Handles buttonZoomIn.ItemClick
If _ViewerMode = ViewerMode.GDPicture Then
GdViewer.ZoomIN()
ElseIf _ViewerMode = ViewerMode.RichText Then
Dim oCmd As New ZoomInCommand(RichEditControl1)
oCmd.Execute()
End If
End Sub
Private Sub btnPrint_Click(sender As Object, e As EventArgs) Handles buttonPrint.ItemClick
If GdViewer.PageCount = 0 Then
Return
End If
GdViewer.PrintDialog()
End Sub
Private Sub btnRotateLeft_Click(sender As Object, e As EventArgs) Handles buttonRotateLeft.ItemClick
GdViewer.Rotate(RotateFlipType.Rotate270FlipNone)
End Sub
Private Sub btnRotateRight_Click(sender As Object, e As EventArgs) Handles buttonRotateRight.ItemClick
GdViewer.Rotate(RotateFlipType.Rotate90FlipNone)
End Sub
Private Sub btnFlipX_Click(sender As Object, e As EventArgs) Handles buttonFlipX.ItemClick
GdViewer.Rotate(RotateFlipType.RotateNoneFlipX)
End Sub
Private Sub btnFlipY_Click(sender As Object, e As EventArgs) Handles buttonFlipY.ItemClick
GdViewer.Rotate(RotateFlipType.RotateNoneFlipY)
End Sub
Private Sub GdViewer1_TransferEnded(ByVal status As GdPictureStatus, ByVal download As System.Boolean) Handles GdViewer.TransferEnded
GdViewer.Focus()
UpdateMainUi()
End Sub
Private Sub AddSearchRegion(ByVal occurence As Integer, ByVal leftCoordinate As Single, ByVal topCoordinate As Single, ByVal regionWidth As Single, ByVal regionheight As Single, ByVal ensureVisibility As Boolean)
Dim searchRegion As Integer = GdViewer.AddRegionInches("SearchResult" & occurence, leftCoordinate, topCoordinate, regionWidth, regionheight, ForegroundMixMode.ForegroundMixModeMASKPEN, Color.Yellow)
GdViewer.SetRegionEditable(searchRegion, False)
If ensureVisibility Then
GdViewer.EnsureRegionVisibility(searchRegion)
End If
End Sub
Private Sub btnSettings_Click(ByVal sender As Object, ByVal e As EventArgs) Handles buttonSettings.ItemClick
Using frmSettings As New frmViewerSettings(GdViewer)
frmSettings.ShowDialog(Me)
End Using
UpdateaNavigationToolbar()
End Sub
#End Region
#Region "Private Functions"
Private Function ConfigPath() As String
Return Path.Combine(Application.UserAppDataPath, "DocumentViewer")
End Function
Private Sub UpdateaNavigationToolbar()
Try
Dim oCurrentZoom As Double = GdViewer.Zoom
Dim oCurrentPage As Integer = GdViewer.CurrentPage
Dim oPageCount As Integer = GdViewer.PageCount
txtCurrentPage.EditValue = oCurrentPage
labelPageCount.Caption = $"/ {oPageCount}"
If oCurrentPage = oPageCount Then
buttonLastPage.Enabled = False
buttonNextPage.Enabled = False
buttonPrevPage.Enabled = True
buttonFirstPage.Enabled = True
ElseIf oCurrentPage = 1 Then
buttonPrevPage.Enabled = False
buttonFirstPage.Enabled = False
buttonLastPage.Enabled = True
buttonNextPage.Enabled = True
Else
buttonPrevPage.Enabled = True
buttonFirstPage.Enabled = True
buttonLastPage.Enabled = True
buttonNextPage.Enabled = True
End If
Catch ex As Exception
_logger.Error(ex)
End Try
End Sub
Public Sub DeleteTempFiles()
For Each oFile In _TempFiles
Try
_logger.Debug("Deleting temp file [{0}]", oFile)
File.Delete(oFile)
Catch ex As Exception
_logger.Warn("Could not delete temp file [{0}]", oFile)
End Try
Next
End Sub
Private Sub SetViewerMode(Extension As String)
Select Case Extension.ToUpper
Case ".MSG"
_ViewerMode = ViewerMode.RichText
Case ".EML", ".DOC", ".DOCX", ".ODT", ".RTF", ".TXT"
_ViewerMode = ViewerMode.RichText
Case ".XLSX", ".XLS", "CSV"
_ViewerMode = ViewerMode.Excel
Case Else
_ViewerMode = ViewerMode.GDPicture
End Select
End Sub
Private Sub FreeFile()
Try
If Len(_FilePath) = 0 OrElse _Fileinfo Is Nothing Then
Exit Sub
End If
Dim oExtension As String = _Fileinfo.Extension.ToUpper
Select Case _ViewerMode
Case ViewerMode.RichText
_logger.Debug("Closing RichText Editor")
RichEditControl1.CreateNewDocument()
Case ViewerMode.Excel
_logger.Debug("Closing Excel Editor")
SpreadsheetControl1.CreateNewDocument()
Case Else
_logger.Debug("Closing GDPicture Viewer")
GdViewer.CloseDocument()
End Select
Catch ex As Exception
_logger.Warn($"Unexpected error in FreeFile: {ex.Message}")
End Try
End Sub
Private Function DoLoadFile(FilePath As String) As Boolean
Try
Dim oFileInfo = New FileInfo(FilePath)
Dim oExtension As String = oFileInfo.Extension.ToUpper
RichEditControl1.Visible = False
RichEditControl1.Dock = DockStyle.None
SpreadsheetControl1.Visible = False
SpreadsheetControl1.Dock = DockStyle.None
Select Case oExtension.ToUpper
Case ".MSG"
Dim oEmlPath As String = _email.Convert_ToEml(FilePath)
_TempFiles.Add(oEmlPath)
DoLoadFile(oEmlPath)
Case ".EML", ".DOC", ".DOCX", ".ODT", ".RTF", ".TXT"
RichEditControl1.LoadDocument(FilePath, GetDocumentFormat(oExtension))
RichEditControl1.Visible = True
RichEditControl1.Dock = DockStyle.Fill
Case ".XLSX", ".XLS", ".CSV"
Dim oFormat = GetSpreadsheetFormat(oExtension)
SpreadsheetControl1.LoadDocument(FilePath, oFormat)
Dim oRange = SpreadsheetControl1.ActiveWorksheet.GetUsedRange()
oRange.AutoFitColumns()
SpreadsheetControl1.Visible = True
SpreadsheetControl1.Dock = DockStyle.Fill
Case Else
GdViewer.ZoomMode = ViewerZoomMode.ZoomModeWidthViewer
GdViewer.DocumentAlignment = ViewerDocumentAlignment.DocumentAlignmentTopCenter
GdViewer.ForceTemporaryMode = True
GdViewer.AnnotationDropShadow = True
GdViewer.DisplayFromFile(FilePath)
End Select
UpdateMainUi()
Return True
Catch ex As Exception
_logger.Error(ex)
Return False
End Try
End Function
Private Sub FitToPage()
If _ViewerMode = ViewerMode.GDPicture Then
GdViewer.ZoomMode = ViewerZoomMode.ZoomModeFitToViewer
ElseIf _ViewerMode = ViewerMode.RichText Then
Dim oCmd As New FitToPageCommand(RichEditControl1)
oCmd.Execute()
End If
End Sub
Private Sub FitToWidth()
If _ViewerMode = ViewerMode.GDPicture Then
GdViewer.ZoomMode = ViewerZoomMode.ZoomModeWidthViewer
ElseIf _ViewerMode = ViewerMode.RichText Then
Dim oCmd As New FitWidthCommand(RichEditControl1)
oCmd.Execute()
End If
End Sub
Private Function DoLoadFile(Stream As Stream, Extension As String) As Boolean
Try
RichEditControl1.Visible = False
RichEditControl1.Dock = DockStyle.None
SpreadsheetControl1.Visible = False
SpreadsheetControl1.Dock = DockStyle.None
Select Case Extension.ToUpper
Case ".MSG"
Dim oTempFileName = Path.Combine(IO.Path.GetTempPath(), Guid.NewGuid.ToString & ".msg")
Using oFileStream As New FileStream(oTempFileName, FileMode.Create)
Stream.Seek(0, SeekOrigin.Begin)
Stream.CopyTo(oFileStream)
Stream.Flush()
End Using
Dim oEmlPath As String = _email.Convert_ToEml(oTempFileName)
DoLoadFile(oEmlPath)
Case ".EML", ".DOC", ".DOCX", ".ODT", ".RTF", ".TXT"
RichEditControl1.LoadDocument(Stream, GetDocumentFormat(Extension))
RichEditControl1.ActiveViewType = XtraRichEdit.RichEditViewType.PrintLayout
RichEditControl1.Visible = True
RichEditControl1.Dock = DockStyle.Fill
Case ".XLSX", ".XLS", ".CSV"
SpreadsheetControl1.LoadDocument(Stream, GetSpreadsheetFormat(Extension))
Dim oRange = SpreadsheetControl1.ActiveWorksheet.GetUsedRange()
oRange.AutoFitColumns()
SpreadsheetControl1.Visible = True
SpreadsheetControl1.Dock = DockStyle.Fill
Case Else
GdViewer.ZoomMode = ViewerZoomMode.ZoomModeWidthViewer
GdViewer.DocumentAlignment = ViewerDocumentAlignment.DocumentAlignmentTopCenter
GdViewer.ForceTemporaryMode = True
GdViewer.AnnotationDropShadow = True
GdViewer.DisplayFromStream(Stream)
End Select
UpdateMainUi()
Return True
Catch ex As Exception
_logger.Error(ex)
Return False
End Try
End Function
Private Function GetSpreadsheetFormat(Extension) As Spreadsheet.DocumentFormat
Dim oFormat As Spreadsheet.DocumentFormat = Spreadsheet.DocumentFormat.Undefined
Select Case Extension.ToUpper
Case ".XLSX" : oFormat = Spreadsheet.DocumentFormat.Xlsx
Case ".XLS" : oFormat = Spreadsheet.DocumentFormat.Xls
Case ".CSV" : oFormat = Spreadsheet.DocumentFormat.Csv
End Select
Return oFormat
End Function
Private Function GetDocumentFormat(Extension) As XtraRichEdit.DocumentFormat
Dim oFormat As XtraRichEdit.DocumentFormat = XtraRichEdit.DocumentFormat.Undefined
Select Case Extension.ToUpper
Case ".EML" : oFormat = XtraRichEdit.DocumentFormat.Mht
Case ".DOC" : oFormat = XtraRichEdit.DocumentFormat.Doc
Case ".DOCX" : oFormat = XtraRichEdit.DocumentFormat.OpenXml
Case ".ODT" : oFormat = XtraRichEdit.DocumentFormat.OpenDocument
Case ".RTF" : oFormat = XtraRichEdit.DocumentFormat.Rtf
Case ".TXT" : oFormat = XtraRichEdit.DocumentFormat.PlainText
End Select
Return oFormat
End Function
Private Sub UpdateMainUi()
Select Case _Config?.Config?.PageFit
Case Config.PageFitSetting.FitPage
FitToPage()
Case Config.PageFitSetting.FitWidth
FitToWidth()
End Select
Select Case _ViewerMode
Case ViewerMode.GDPicture
buttonPrint.Enabled = True
buttonFitWidth.Enabled = True
buttonFitPage.Enabled = True
buttonZoomIn.Enabled = True
buttonZoomOut.Enabled = True
buttonRotateLeft.Enabled = True
buttonRotateRight.Enabled = True
buttonFlipX.Enabled = True
buttonFlipY.Enabled = True
buttonFirstPage.Enabled = True
buttonPrevPage.Enabled = True
buttonNextPage.Enabled = True
buttonLastPage.Enabled = True
buttonSettings.Enabled = True
txtCurrentPage.Enabled = True
Case ViewerMode.RichText
buttonFitPage.Enabled = True
buttonZoomIn.Enabled = True
buttonZoomOut.Enabled = True
buttonFitWidth.Enabled = True
buttonNextPage.Enabled = True
buttonPrevPage.Enabled = True
buttonPrint.Enabled = False
buttonRotateLeft.Enabled = False
buttonRotateRight.Enabled = False
buttonFlipX.Enabled = False
buttonFlipY.Enabled = False
buttonFirstPage.Enabled = False
buttonLastPage.Enabled = False
buttonSettings.Enabled = False
txtCurrentPage.Enabled = False
Case ViewerMode.Excel
buttonPrint.Enabled = False
buttonFitWidth.Enabled = False
buttonFitPage.Enabled = False
buttonZoomIn.Enabled = False
buttonZoomOut.Enabled = False
buttonRotateLeft.Enabled = False
buttonRotateRight.Enabled = False
buttonFlipX.Enabled = False
buttonFlipY.Enabled = False
buttonFirstPage.Enabled = False
buttonPrevPage.Enabled = False
buttonNextPage.Enabled = False
buttonLastPage.Enabled = False
buttonSettings.Enabled = False
txtCurrentPage.Enabled = False
End Select
End Sub
Private Sub btnSearch2_ItemClick(sender As Object, e As XtraBars.ItemClickEventArgs) Handles btnSearch2.ItemClick
_Search.SearchAll(txtSearch.EditValue.ToString)
End Sub
Private Sub btnPrevHighlight_ItemClick(sender As Object, e As XtraBars.ItemClickEventArgs) Handles btnPrevHighlight.ItemClick
_Search.PrevHighlight()
End Sub
Private Sub btnNextHighlight_ItemClick(sender As Object, e As XtraBars.ItemClickEventArgs) Handles btnNextHighlight.ItemClick
_Search.NextHighlight()
End Sub
Private Sub txtSearch_EditValueChanged(sender As Object, e As EventArgs) Handles txtSearch.EditValueChanged
If String.IsNullOrEmpty(txtSearch.EditValue) Then
btnPrevHighlight.Enabled = False
btnNextHighlight.Enabled = False
Else
btnPrevHighlight.Enabled = True
btnNextHighlight.Enabled = True
End If
End Sub
#End Region
End Class