From de49c3ba33aadac9b7d442158ff5f08edef10a5b Mon Sep 17 00:00:00 2001 From: Philipp Bauer Date: Thu, 2 Nov 2023 19:01:59 -0500 Subject: [PATCH 1/4] Update azure-pipelines-photino.net-prod.yml for Azure Pipelines --- azure-pipelines-photino.net-prod.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines-photino.net-prod.yml b/azure-pipelines-photino.net-prod.yml index 4587cc2..5b9affc 100644 --- a/azure-pipelines-photino.net-prod.yml +++ b/azure-pipelines-photino.net-prod.yml @@ -6,7 +6,7 @@ trigger: variables: major: 2 - minor: 4 + minor: 5 patch: $[counter(variables['minor'], 0)] #this will reset when we bump minor buildConfiguration: 'Release' From 4ded72521b0712df3be836bcc61d0c7908bf4e72 Mon Sep 17 00:00:00 2001 From: Philipp Bauer Date: Thu, 2 Nov 2023 19:08:32 -0500 Subject: [PATCH 2/4] Update azure-pipelines-photino.net-prod.yml for Azure Pipelines --- azure-pipelines-photino.net-prod.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/azure-pipelines-photino.net-prod.yml b/azure-pipelines-photino.net-prod.yml index 5b9affc..25cb692 100644 --- a/azure-pipelines-photino.net-prod.yml +++ b/azure-pipelines-photino.net-prod.yml @@ -7,7 +7,8 @@ trigger: variables: major: 2 minor: 5 - patch: $[counter(variables['minor'], 0)] #this will reset when we bump minor + patch: 0 + # patch: $[counter(variables['minor'], 0)] #this will reset when we bump minor buildConfiguration: 'Release' jobs: From d62d96c4cdc61c6fe89887263162fd91342da674 Mon Sep 17 00:00:00 2001 From: Philipp Bauer Date: Fri, 3 Nov 2023 09:05:26 -0500 Subject: [PATCH 3/4] Reset build pipeline patch version --- azure-pipelines-photino.net-dev.yml | 130 +++++++++++++-------------- azure-pipelines-photino.net-prod.yml | 67 +++++++------- 2 files changed, 98 insertions(+), 99 deletions(-) diff --git a/azure-pipelines-photino.net-dev.yml b/azure-pipelines-photino.net-dev.yml index 134fe65..2e683dc 100644 --- a/azure-pipelines-photino.net-dev.yml +++ b/azure-pipelines-photino.net-dev.yml @@ -2,82 +2,82 @@ # https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core trigger: -- debug + - debug variables: - versionprefix: 0.9.0 + versionprefix: 0.9.0 jobs: - - job: 'BuildPackageAndPublish' + - job: "BuildPackageAndPublish" - pool: - vmImage: windows-latest + pool: + vmImage: windows-latest - variables: - buildConfiguration: 'Debug' + variables: + buildConfiguration: "Debug" - steps: - - task: UseDotNet@2 - displayName: 'Use .NET 7 sdk' - inputs: - packageType: sdk - version: 7.0.x - installationPath: $(Agent.ToolsDirectory)/dotnet + steps: + - task: UseDotNet@2 + displayName: "Use .NET 7 sdk" + inputs: + packageType: sdk + version: 7.0.x + installationPath: $(Agent.ToolsDirectory)/dotnet - - task: CmdLine@2 - displayName: 'Add NuGet source' - inputs: - script: 'dotnet nuget add source https://pkgs.dev.azure.com/tryphotino/Photino.Native/_packaging/PhotinoPackages/nuget/v3/index.json -n DevOpsArtifacts' + - task: CmdLine@2 + displayName: "Add NuGet source" + inputs: + script: "dotnet nuget add source https://pkgs.dev.azure.com/tryphotino/Photino.Native/_packaging/PhotinoPackages/nuget/v3/index.json -n DevOpsArtifacts" - - task: NuGetAuthenticate@0 - displayName: 'NuGet Authenticate' + - task: NuGetAuthenticate@0 + displayName: "NuGet Authenticate" - #- task: CmdLine@2 - # displayName: 'Build Photino.NET' - # inputs: - # script: 'dotnet build Photino.NET/Photino.NET.csproj -c $(buildConfiguration)' + #- task: CmdLine@2 + # displayName: 'Build Photino.NET' + # inputs: + # script: 'dotnet build Photino.NET/Photino.NET.csproj -c $(buildConfiguration)' - #Build and Create NuGet package - - task: CmdLine@2 - displayName: 'Build and Create NuGet package' - inputs: - script: 'dotnet pack Photino.NET/Photino.NET.csproj -c $(buildConfiguration) --include-symbols /p:Version=$(versionprefix)-dev-$(Build.BuildNumber) /p:PackageVersion=$(versionprefix)-dev-$(Build.BuildNumber)' + #Build and Create NuGet package + - task: CmdLine@2 + displayName: "Build and Create NuGet package" + inputs: + script: "dotnet pack Photino.NET/Photino.NET.csproj -c $(buildConfiguration) --include-symbols /p:Version=$(versionprefix)-dev-$(Build.BuildNumber) /p:PackageVersion=$(versionprefix)-dev-$(Build.BuildNumber)" - #Create NuGet package - #- task: CmdLine@2 - # displayName: 'Create NuGet package' - # inputs: - # script: 'nuget.exe pack Photino.NET/Photino.NET.nuspec -Version $(versionprefix)-$(Build.BuildNumber) -NonInteractive -Properties version=$(versionprefix)-$(Build.BuildNumber)' + #Create NuGet package + #- task: CmdLine@2 + # displayName: 'Create NuGet package' + # inputs: + # script: 'nuget.exe pack Photino.NET/Photino.NET.nuspec -Version $(versionprefix)-$(Build.BuildNumber) -NonInteractive -Properties version=$(versionprefix)-$(Build.BuildNumber)' - #Publish NuGet package to Artifacts - - task: NuGetCommand@2 - displayName: 'NuGet push' - inputs: - command: push - feedsToUse: 'select' - publishVstsFeed: 'Photino.Native/PhotinoPackages' - packagesToPush: 'Photino.NET/bin/$(buildConfiguration)/*.nupkg' - allowPackageConflicts: true + #Publish NuGet package to Artifacts + - task: NuGetCommand@2 + displayName: "NuGet push" + inputs: + command: push + feedsToUse: "select" + publishVstsFeed: "Photino.Native/PhotinoPackages" + packagesToPush: "Photino.NET/bin/$(buildConfiguration)/*.nupkg" + allowPackageConflicts: true - # Uploads the NuGet package file to nuget.org - # Important notes: - # 1. For this to work, you need to create a 'service connection' with the same name - # as the 'publishFeedCredentials' value. - # 2. For security, you *must* ensure that 'Make secrets available to builds of forks' - # is disabled in your PR validation settings (inside build -> Edit -> Triggers). - # Otherwise, PRs would be able to push new packages even without being merged. - #- job: 'PublishToNuGet' - # dependsOn: 'CombinePackages' - # steps: - # - task: DownloadBuildArtifacts@0 - # inputs: - # downloadPath: 'artifacts' - # artifactName: 'artifacts-combined' - # - task: NuGetCommand@2 - # displayName: 'Publish to nuget.org' - # condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master')) - # inputs: - # command: push - # packagesToPush: 'artifacts/artifacts-combined/*.nupkg' - # nuGetFeedType: external - # publishFeedCredentials: 'WebWindowNuGet' + # Uploads the NuGet package file to nuget.org + # Important notes: + # 1. For this to work, you need to create a 'service connection' with the same name + # as the 'publishFeedCredentials' value. + # 2. For security, you *must* ensure that 'Make secrets available to builds of forks' + # is disabled in your PR validation settings (inside build -> Edit -> Triggers). + # Otherwise, PRs would be able to push new packages even without being merged. + #- job: 'PublishToNuGet' + # dependsOn: 'CombinePackages' + # steps: + # - task: DownloadBuildArtifacts@0 + # inputs: + # downloadPath: 'artifacts' + # artifactName: 'artifacts-combined' + # - task: NuGetCommand@2 + # displayName: 'Publish to nuget.org' + # condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master')) + # inputs: + # command: push + # packagesToPush: 'artifacts/artifacts-combined/*.nupkg' + # nuGetFeedType: external + # publishFeedCredentials: 'WebWindowNuGet' diff --git a/azure-pipelines-photino.net-prod.yml b/azure-pipelines-photino.net-prod.yml index 25cb692..4d413e6 100644 --- a/azure-pipelines-photino.net-prod.yml +++ b/azure-pipelines-photino.net-prod.yml @@ -2,47 +2,46 @@ # https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core trigger: -- manual + - manual variables: major: 2 minor: 5 - patch: 0 - # patch: $[counter(variables['minor'], 0)] #this will reset when we bump minor - buildConfiguration: 'Release' + patch: $[counter(variables['minor'], 0)] #this will reset when we bump minor + buildConfiguration: "Release" jobs: - - job: 'BuildPackageAndPublish' + - job: "BuildPackageAndPublish" - pool: - vmImage: windows-latest + pool: + vmImage: windows-latest - steps: - - task: UseDotNet@2 - displayName: 'Use .NET 7 sdk' - inputs: - packageType: sdk - version: 7.0.x - installationPath: $(Agent.ToolsDirectory)/dotnet + steps: + - task: UseDotNet@2 + displayName: "Use .NET 7 sdk" + inputs: + packageType: sdk + version: 7.0.x + installationPath: $(Agent.ToolsDirectory)/dotnet - #Build and Create NuGet package - - task: CmdLine@2 - displayName: 'Build and Create NuGet package' - inputs: - script: 'dotnet pack Photino.NET/Photino.NET.csproj -c $(buildConfiguration) /p:Version=$(major).$(minor).$(patch) /p:PackageVersion=$(major).$(minor).$(patch)' + #Build and Create NuGet package + - task: CmdLine@2 + displayName: "Build and Create NuGet package" + inputs: + script: "dotnet pack Photino.NET/Photino.NET.csproj -c $(buildConfiguration) /p:Version=$(major).$(minor).$(patch) /p:PackageVersion=$(major).$(minor).$(patch)" - # Uploads the NuGet package file to nuget.org - # Important notes: - # 1. For this to work, you need to create a 'service connection' with the same name - # as the 'publishFeedCredentials' value. - # 2. For security, you *must* ensure that 'Make secrets available to builds of forks' - # is disabled in your PR validation settings (inside build -> Edit -> Triggers). - # Otherwise, PRs would be able to push new packages even without being merged. - - task: NuGetCommand@2 - displayName: 'Publish to nuget.org' - condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master')) - inputs: - command: push - packagesToPush: 'Photino.NET/bin/$(buildConfiguration)/*.nupkg' - nuGetFeedType: external - publishFeedCredentials: 'PhotinoNetNuGet' + # Uploads the NuGet package file to nuget.org + # Important notes: + # 1. For this to work, you need to create a 'service connection' with the same name + # as the 'publishFeedCredentials' value. + # 2. For security, you *must* ensure that 'Make secrets available to builds of forks' + # is disabled in your PR validation settings (inside build -> Edit -> Triggers). + # Otherwise, PRs would be able to push new packages even without being merged. + - task: NuGetCommand@2 + displayName: "Publish to nuget.org" + condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master')) + inputs: + command: push + packagesToPush: "Photino.NET/bin/$(buildConfiguration)/*.nupkg" + nuGetFeedType: external + publishFeedCredentials: "PhotinoNetNuGet" From a34d4b97c29895f871b54b0c9e27ba958cdf6d0f Mon Sep 17 00:00:00 2001 From: Loop8ack <41995252+loop8ack@users.noreply.github.com> Date: Sat, 9 Dec 2023 23:06:51 +0100 Subject: [PATCH 4/4] Logger interface to provide more flexibility in logging --- Photino.NET/DefaultPhotinoLogger.cs | 24 ++++ Photino.NET/IPhotinoLogger.cs | 17 +++ Photino.NET/LogVerbosity.cs | 20 +++ Photino.NET/PhotinoWindow.NET.cs | 194 ++++++++++++++++++---------- 4 files changed, 186 insertions(+), 69 deletions(-) create mode 100644 Photino.NET/DefaultPhotinoLogger.cs create mode 100644 Photino.NET/IPhotinoLogger.cs create mode 100644 Photino.NET/LogVerbosity.cs diff --git a/Photino.NET/DefaultPhotinoLogger.cs b/Photino.NET/DefaultPhotinoLogger.cs new file mode 100644 index 0000000..ae580de --- /dev/null +++ b/Photino.NET/DefaultPhotinoLogger.cs @@ -0,0 +1,24 @@ +using System; + +namespace PhotinoNET; + +internal sealed class DefaultPhotinoLogger : IPhotinoLogger +{ + private readonly PhotinoWindow _window; + + public DefaultPhotinoLogger(PhotinoWindow window) + { + _window = window; + } + + public void Log(int verbosity, Exception exception, string message) + { + if (_window.LogVerbosity < verbosity) + return; + + if (exception is not null) + message = $"***\n{exception.Message}\n{exception.StackTrace}\n{message}"; + + Console.WriteLine($"Photino.NET: \"{_window.Title ?? "PhotinoWindow"}\"{message}"); + } +} \ No newline at end of file diff --git a/Photino.NET/IPhotinoLogger.cs b/Photino.NET/IPhotinoLogger.cs new file mode 100644 index 0000000..10cf5af --- /dev/null +++ b/Photino.NET/IPhotinoLogger.cs @@ -0,0 +1,17 @@ +using System; + +namespace PhotinoNET; + +/// +/// Defines an interface for implementing logging functionality. +/// +public interface IPhotinoLogger +{ + /// + /// Logs a message with the specified verbosity level, exception information, and a custom message. + /// + /// The verbosity level of the log entry. + /// The exception to log. Can be null if not applicable. + /// The custom message to log. + void Log(int verbosity, Exception exception, string message); +} \ No newline at end of file diff --git a/Photino.NET/LogVerbosity.cs b/Photino.NET/LogVerbosity.cs new file mode 100644 index 0000000..e6fd3bc --- /dev/null +++ b/Photino.NET/LogVerbosity.cs @@ -0,0 +1,20 @@ +namespace PhotinoNET; + +/// +/// Defines a static class for specifying log verbosity levels in the Photino window. +/// This class provides predefined constants to easily set and understand the desired level of logging detail. +/// +public static class LogVerbosity +{ + /// Logs only critical errors. Value: 0. + public static readonly int Critical = 0; + + /// Logs critical errors and warnings. Value: 1. + public static readonly int Warning = 1; + + /// Logs detailed information, including errors and warnings. Value: 2. + public static readonly int Verbose = 2; + + /// Logs all details for debugging purposes, including verbose output. Value: 3. + public static readonly int Debug = 3; +} diff --git a/Photino.NET/PhotinoWindow.NET.cs b/Photino.NET/PhotinoWindow.NET.cs index 9be1a58..d3c775b 100644 --- a/Photino.NET/PhotinoWindow.NET.cs +++ b/Photino.NET/PhotinoWindow.NET.cs @@ -6,6 +6,8 @@ using System.Runtime.InteropServices; using System.Threading.Tasks; +using static PhotinoNET.LogVerbosity; + namespace PhotinoNET; public partial class PhotinoWindow @@ -1372,14 +1374,42 @@ public int Zoom } /// - /// Gets or sets the logging verbosity to standard output (Console/Terminal). - /// 0 = Critical Only - /// 1 = Critical and Warning - /// 2 = Verbose - /// >2 = All Details + /// Gets or sets the logging verbosity. + /// + /// + /// 0 + /// Critical Only + /// + /// + /// 1 + /// Critical and Warning + /// + /// + /// 2 + /// Verbose + /// + /// + /// >2 + /// All Details + /// + /// /// Default is 2. /// - public int LogVerbosity { get; set; } = 2; + /// + /// Use constant values: + /// + public int LogVerbosity { get; set; } = Verbose; + + private IPhotinoLogger _logger; + /// + /// Gets or sets the logger instance used by the Photino window. It allows for custom logging implementations. + /// If no custom logger is provided, a default logger that logs to the console/terminal is used. + /// + public IPhotinoLogger Logger + { + get => _logger ??= new DefaultPhotinoLogger(this); + set => _logger = value; + } //CONSTRUCTOR /// @@ -1457,7 +1487,7 @@ public PhotinoWindow Invoke(Action workItem) /// A Uri pointing to the file or the URL to load. public PhotinoWindow Load(Uri uri) { - Log($".Load({uri})"); + LogVerbose($".Load({uri})"); if (_nativeInstance == IntPtr.Zero) if (IsWindowsPlatform) _startupParameters.StartUrlWide = uri.ToString(); @@ -1480,7 +1510,7 @@ public PhotinoWindow Load(Uri uri) /// A path pointing to the ressource to load. public PhotinoWindow Load(string path) { - Log($".Load({path})"); + LogVerbose($".Load({path})"); // –––––––––––––––––––––– // SECURITY RISK! @@ -1501,7 +1531,7 @@ public PhotinoWindow Load(string path) if (File.Exists(absolutePath) == false) { - Log($" ** File \"{path}\" could not be found."); + LogVerbose($" ** File \"{path}\" could not be found."); return this; } } @@ -1523,7 +1553,7 @@ public PhotinoWindow Load(string path) public PhotinoWindow LoadRawString(string content) { var shortContent = content.Length > 50 ? string.Concat(content.AsSpan(0, 50), "...") : content; - Log($".LoadRawString({shortContent})"); + LogVerbose($".LoadRawString({shortContent})"); if (_nativeInstance == IntPtr.Zero) if (IsWindowsPlatform) _startupParameters.StartStringWide = content; @@ -1546,7 +1576,7 @@ public PhotinoWindow LoadRawString(string content) /// public PhotinoWindow Center() { - Log(".Center()"); + LogVerbose(".Center()"); Centered = true; return this; } @@ -1561,13 +1591,9 @@ public PhotinoWindow Center() /// Whether the window can go off-screen (work area) public PhotinoWindow MoveTo(Point location, bool allowOutsideWorkArea = false) { - Log($".MoveTo({location}, {allowOutsideWorkArea})"); - - if (LogVerbosity > 2) - { - Log($" Current location: {Location}"); - Log($" New location: {location}"); - } + LogVerbose($".MoveTo({location}, {allowOutsideWorkArea})"); + Log(Debug, $" Current location: {Location}"); + Log(Debug, $" New location: {location}"); // If the window is outside of the work area, // recalculate the position and continue. @@ -1631,7 +1657,7 @@ public PhotinoWindow MoveTo(Point location, bool allowOutsideWorkArea = false) /// Whether the window can go off-screen (work area) public PhotinoWindow MoveTo(int left, int top, bool allowOutsideWorkArea = false) { - Log($".MoveTo({left}, {top}, {allowOutsideWorkArea})"); + LogVerbose($".MoveTo({left}, {top}, {allowOutsideWorkArea})"); return MoveTo(new Point(left, top), allowOutsideWorkArea); } @@ -1645,7 +1671,7 @@ public PhotinoWindow MoveTo(int left, int top, bool allowOutsideWorkArea = false /// Relative offset public PhotinoWindow Offset(Point offset) { - Log($".Offset({offset})"); + LogVerbose($".Offset({offset})"); var location = Location; int left = location.X + offset.X; int top = location.Y + offset.Y; @@ -1663,7 +1689,7 @@ public PhotinoWindow Offset(Point offset) /// Relative offset from top in pixels public PhotinoWindow Offset(int left, int top) { - Log($".Offset({left}, {top})"); + LogVerbose($".Offset({left}, {top})"); return Offset(new Point(left, top)); } @@ -1680,7 +1706,7 @@ public PhotinoWindow Offset(int left, int top) /// Whether the window should be chromeless public PhotinoWindow SetChromeless(bool chromeless) { - Log($".SetChromeless({chromeless})"); + LogVerbose($".SetChromeless({chromeless})"); if (_nativeInstance != IntPtr.Zero) throw new ApplicationException("Chromeless setting cannot be used on an unitialized window."); @@ -1698,7 +1724,7 @@ public PhotinoWindow SetChromeless(bool chromeless) /// Whether the context menu should be available public PhotinoWindow SetContextMenuEnabled(bool enabled) { - Log($".SetContextMenuEnabled({enabled})"); + LogVerbose($".SetContextMenuEnabled({enabled})"); ContextMenuEnabled = enabled; return this; } @@ -1713,7 +1739,7 @@ public PhotinoWindow SetContextMenuEnabled(bool enabled) /// Whether developer tools should be available public PhotinoWindow SetDevToolsEnabled(bool enabled) { - Log($".SetDevTools({enabled})"); + LogVerbose($".SetDevTools({enabled})"); DevToolsEnabled = enabled; return this; } @@ -1728,7 +1754,7 @@ public PhotinoWindow SetDevToolsEnabled(bool enabled) /// Whether the window should be fullscreen public PhotinoWindow SetFullScreen(bool fullScreen) { - Log($".SetFullScreen({fullScreen})"); + LogVerbose($".SetFullScreen({fullScreen})"); FullScreen = fullScreen; return this; } @@ -1746,7 +1772,7 @@ public PhotinoWindow SetFullScreen(bool fullScreen) /// Whether permissions should be automatically granted. public PhotinoWindow SetGrantBrowserPermissions(bool grant) { - Log($".SetGrantBrowserPermission({grant})"); + LogVerbose($".SetGrantBrowserPermission({grant})"); GrantBrowserPermissions = grant; return this; } @@ -1758,7 +1784,7 @@ public PhotinoWindow SetGrantBrowserPermissions(bool grant) /// Returns the current instance. public PhotinoWindow SetUserAgent(string userAgent) { - Log($".SetUserAgent({userAgent})"); + LogVerbose($".SetUserAgent({userAgent})"); UserAgent = userAgent; return this; } @@ -1785,7 +1811,7 @@ public PhotinoWindow SetUserAgent(string userAgent) /// public PhotinoWindow SetBrowserControlInitParameters(string parameters) { - Log($".SetBrowserControlInitParameters({parameters})"); + LogVerbose($".SetBrowserControlInitParameters({parameters})"); BrowserControlInitParameters = parameters; return this; } @@ -1797,7 +1823,7 @@ public PhotinoWindow SetBrowserControlInitParameters(string parameters) /// Returns the current instance. public PhotinoWindow SetMediaAutoplayEnabled(bool enable) { - Log($".SetMediaAutoplayEnabled({enable})"); + LogVerbose($".SetMediaAutoplayEnabled({enable})"); MediaAutoplayEnabled = enable; return this; } @@ -1809,7 +1835,7 @@ public PhotinoWindow SetMediaAutoplayEnabled(bool enable) /// Returns the current instance. public PhotinoWindow SetFileSystemAccessEnabled(bool enable) { - Log($".SetFileSystemAccessEnabled({enable})"); + LogVerbose($".SetFileSystemAccessEnabled({enable})"); FileSystemAccessEnabled = enable; return this; } @@ -1821,7 +1847,7 @@ public PhotinoWindow SetFileSystemAccessEnabled(bool enable) /// Returns the current instance. public PhotinoWindow SetWebSecurityEnabled(bool enable) { - Log($".SetWebSecurityEnabled({enable})"); + LogVerbose($".SetWebSecurityEnabled({enable})"); WebSecurityEnabled = enable; return this; } @@ -1833,7 +1859,7 @@ public PhotinoWindow SetWebSecurityEnabled(bool enable) /// Returns the current instance. public PhotinoWindow SetJavascriptClipboardAccessEnabled(bool enable) { - Log($".SetJavascriptClipboardAccessEnabled({enable})"); + LogVerbose($".SetJavascriptClipboardAccessEnabled({enable})"); JavascriptClipboardAccessEnabled = enable; return this; } @@ -1845,7 +1871,7 @@ public PhotinoWindow SetJavascriptClipboardAccessEnabled(bool enable) /// Returns the current instance. public PhotinoWindow SetMediaStreamEnabled(bool enable) { - Log($".SetMediaStreamEnabled({enable})"); + LogVerbose($".SetMediaStreamEnabled({enable})"); MediaStreamEnabled = enable; return this; } @@ -1857,7 +1883,7 @@ public PhotinoWindow SetMediaStreamEnabled(bool enable) /// Returns the current instance. public PhotinoWindow SetSmoothScrollingEnabled(bool enable) { - Log($".SetSmoothScrollingEnabled({enable})"); + LogVerbose($".SetSmoothScrollingEnabled({enable})"); SmoothScrollingEnabled = enable; return this; } @@ -1874,7 +1900,7 @@ public PhotinoWindow SetSmoothScrollingEnabled(bool enable) /// Height in pixels public PhotinoWindow SetHeight(int height) { - Log($".SetHeight({height})"); + LogVerbose($".SetHeight({height})"); Height = height; return this; } @@ -1892,7 +1918,7 @@ public PhotinoWindow SetHeight(int height) /// The file path to the icon. public PhotinoWindow SetIconFile(string iconFile) { - Log($".SetIconFile({iconFile})"); + LogVerbose($".SetIconFile({iconFile})"); IconFile = iconFile; return this; } @@ -1908,7 +1934,7 @@ public PhotinoWindow SetIconFile(string iconFile) /// Position in pixels from the left (X). public PhotinoWindow SetLeft(int left) { - Log($".SetLeft({Left})"); + LogVerbose($".SetLeft({Left})"); Left = left; return this; } @@ -1923,7 +1949,7 @@ public PhotinoWindow SetLeft(int left) /// Whether the window is resizable public PhotinoWindow SetResizable(bool resizable) { - Log($".SetResizable({resizable})"); + LogVerbose($".SetResizable({resizable})"); Resizable = resizable; return this; } @@ -1939,7 +1965,7 @@ public PhotinoWindow SetResizable(bool resizable) /// Width & Height public PhotinoWindow SetSize(Size size) { - Log($".SetSize({size})"); + LogVerbose($".SetSize({size})"); Size = size; return this; } @@ -1956,7 +1982,7 @@ public PhotinoWindow SetSize(Size size) /// Height in pixels public PhotinoWindow SetSize(int width, int height) { - Log($".SetSize({width}, {height})"); + LogVerbose($".SetSize({width}, {height})"); Size = new Size(width, height); return this; } @@ -1972,7 +1998,7 @@ public PhotinoWindow SetSize(int width, int height) /// Location as a public PhotinoWindow SetLocation(Point location) { - Log($".SetLocation({location})"); + LogVerbose($".SetLocation({location})"); Location = location; return this; } @@ -1991,7 +2017,7 @@ public PhotinoWindow SetLocation(Point location) /// Verbosity as integer public PhotinoWindow SetLogVerbosity(int verbosity) { - Log($".SetLogVerbosity({verbosity})"); + LogVerbose($".SetLogVerbosity({verbosity})"); LogVerbosity = verbosity; return this; } @@ -2006,7 +2032,7 @@ public PhotinoWindow SetLogVerbosity(int verbosity) /// Whether the window should be maximized. public PhotinoWindow SetMaximized(bool maximized) { - Log($".SetMaximized({maximized})"); + LogVerbose($".SetMaximized({maximized})"); Maximized = maximized; return this; } @@ -2014,7 +2040,7 @@ public PhotinoWindow SetMaximized(bool maximized) ///Native window maximum Width and Height in pixels. public PhotinoWindow SetMaxSize(int maxWidth, int maxHeight) { - Log($".SetMaxSize({maxWidth}, {maxHeight})"); + LogVerbose($".SetMaxSize({maxWidth}, {maxHeight})"); MaxSize = new Point(maxWidth, maxHeight); return this; } @@ -2022,7 +2048,7 @@ public PhotinoWindow SetMaxSize(int maxWidth, int maxHeight) ///Native window maximum Height in pixels. public PhotinoWindow SetMaxHeight(int maxHeight) { - Log($".SetMaxHeight({maxHeight})"); + LogVerbose($".SetMaxHeight({maxHeight})"); MaxHeight = maxHeight; return this; } @@ -2030,7 +2056,7 @@ public PhotinoWindow SetMaxHeight(int maxHeight) ///Native window maximum Width in pixels. public PhotinoWindow SetMaxWidth(int maxWidth) { - Log($".SetMaxWidth({maxWidth})"); + LogVerbose($".SetMaxWidth({maxWidth})"); MaxWidth = maxWidth; return this; } @@ -2045,7 +2071,7 @@ public PhotinoWindow SetMaxWidth(int maxWidth) /// Whether the window should be minimized. public PhotinoWindow SetMinimized(bool minimized) { - Log($".SetMinimized({minimized})"); + LogVerbose($".SetMinimized({minimized})"); Minimized = minimized; return this; } @@ -2053,7 +2079,7 @@ public PhotinoWindow SetMinimized(bool minimized) ///Native window maximum Width and Height in pixels. public PhotinoWindow SetMinSize(int minWidth, int minHeight) { - Log($".SetMinSize({minWidth}, {minHeight})"); + LogVerbose($".SetMinSize({minWidth}, {minHeight})"); MinSize = new Point(minWidth, minHeight); return this; } @@ -2061,7 +2087,7 @@ public PhotinoWindow SetMinSize(int minWidth, int minHeight) ///Native window maximum Height in pixels. public PhotinoWindow SetMinHeight(int minHeight) { - Log($".SetMinHeight({minHeight})"); + LogVerbose($".SetMinHeight({minHeight})"); MinHeight = minHeight; return this; } @@ -2069,7 +2095,7 @@ public PhotinoWindow SetMinHeight(int minHeight) ///Native window maximum Width in pixels. public PhotinoWindow SetMinWidth(int minWidth) { - Log($".SetMinWidth({minWidth})"); + LogVerbose($".SetMinWidth({minWidth})"); MinWidth = minWidth; return this; } @@ -2090,7 +2116,7 @@ public PhotinoWindow SetMinWidth(int minWidth) /// Path to temp files directory. public PhotinoWindow SetTemporaryFilesPath(string tempFilesPath) { - Log($".SetTemporaryFilesPath({tempFilesPath})"); + LogVerbose($".SetTemporaryFilesPath({tempFilesPath})"); TemporaryFilesPath = tempFilesPath; return this; } @@ -2105,7 +2131,7 @@ public PhotinoWindow SetTemporaryFilesPath(string tempFilesPath) /// Window title public PhotinoWindow SetTitle(string title) { - Log($".SetTitle({title})"); + LogVerbose($".SetTitle({title})"); Title = title; return this; } @@ -2121,7 +2147,7 @@ public PhotinoWindow SetTitle(string title) /// Position in pixels from the top (Y). public PhotinoWindow SetTop(int top) { - Log($".SetTop({top})"); + LogVerbose($".SetTop({top})"); Top = top; return this; } @@ -2136,7 +2162,7 @@ public PhotinoWindow SetTop(int top) /// Whether the window is at the top public PhotinoWindow SetTopMost(bool topMost) { - Log($".SetTopMost({topMost})"); + LogVerbose($".SetTopMost({topMost})"); Topmost = topMost; return this; } @@ -2152,7 +2178,7 @@ public PhotinoWindow SetTopMost(bool topMost) /// Width in pixels public PhotinoWindow SetWidth(int width) { - Log($".SetWidth({width})"); + LogVerbose($".SetWidth({width})"); Width = width; return this; } @@ -2168,7 +2194,7 @@ public PhotinoWindow SetWidth(int width) /// 100 = 100%, 50 = 50% public PhotinoWindow SetZoom(int zoom) { - Log($".SetZoom({zoom})"); + LogVerbose($".SetZoom({zoom})"); Zoom = zoom; return this; } @@ -2186,7 +2212,7 @@ public PhotinoWindow SetZoom(int zoom) /// Whether the OS Default should be used. public PhotinoWindow SetUseOsDefaultLocation(bool useOsDefault) { - Log($".SetUseOsDefaultLocation({useOsDefault})"); + LogVerbose($".SetUseOsDefaultLocation({useOsDefault})"); UseOsDefaultLocation = useOsDefault; return this; } @@ -2204,7 +2230,7 @@ public PhotinoWindow SetUseOsDefaultLocation(bool useOsDefault) /// Whether the OS Default should be used. public PhotinoWindow SetUseOsDefaultSize(bool useOsDefault) { - Log($".SetUseOsDefaultSize({useOsDefault})"); + LogVerbose($".SetUseOsDefaultSize({useOsDefault})"); UseOsDefaultSize = useOsDefault; return this; } @@ -2225,7 +2251,7 @@ public PhotinoWindow Win32SetWebView2Path(string data) if (IsWindowsPlatform) Invoke(() => Photino_setWebView2RuntimePath_win32(_nativeType, data)); else - Log("Win32SetWebView2Path is only supported on the Windows platform"); + Log(Warning, "Win32SetWebView2Path is only supported on the Windows platform"); return this; } @@ -2244,8 +2270,18 @@ public PhotinoWindow ClearBrowserAutoFill() if (IsWindowsPlatform) Invoke(() => Photino_ClearBrowserAutoFill(_nativeInstance)); else - Log("ClearBrowserAutoFill is only supported on the Windows platform"); + Log(Warning, "ClearBrowserAutoFill is only supported on the Windows platform"); + + return this; + } + /// + /// Sets the logger instance used by the Photino window. It allows for custom logging implementations. + /// + public PhotinoWindow SetLogger(IPhotinoLogger logger) + { + LogVerbose($".SetLogger({logger?.GetType()?.ToString() ?? "null"})"); + Logger = logger; return this; } @@ -2290,7 +2326,7 @@ public void WaitForClose() if (IsWindowsPlatform) lastError = Marshal.GetLastWin32Error(); - Log($"***\n{ex.Message}\n{ex.StackTrace}\nError #{lastError}"); + Log(Critical, ex, $"Error #{lastError}"); throw new ApplicationException($"Native code exception. Error # {lastError} See inner exception for details.", ex); } OnWindowCreated(); @@ -2308,7 +2344,7 @@ public void WaitForClose() if (IsWindowsPlatform) lastError = Marshal.GetLastWin32Error(); - Log($"***\n{ex.Message}\n{ex.StackTrace}\nError #{lastError}"); + Log(Critical, ex, $"Error #{lastError}"); throw new ApplicationException($"Native code exception. Error # {lastError} See inner exception for details.", ex); } } @@ -2331,7 +2367,7 @@ public void WaitForClose() /// public void Close() { - Log(".Close()"); + LogVerbose(".Close()"); if (_nativeInstance == IntPtr.Zero) throw new ApplicationException("Close cannot be called until after the Photino window is initialized."); Invoke(() => Photino_Close(_nativeInstance)); @@ -2349,7 +2385,7 @@ public void Close() /// Message as string public void SendWebMessage(string message) { - Log($".SendWebMessage({message})"); + LogVerbose($".SendWebMessage({message})"); if (_nativeInstance == IntPtr.Zero) throw new ApplicationException("SendWebMessage cannot be called until after the Photino window is initialized."); Invoke(() => Photino_SendWebMessage(_nativeInstance, message)); @@ -2359,7 +2395,7 @@ public async Task SendWebMessageAsync(string message) { await Task.Run(() => { - Log($".SendWebMessage({message})"); + LogVerbose($".SendWebMessage({message})"); if (_nativeInstance == IntPtr.Zero) throw new ApplicationException("SendWebMessage cannot be called until after the Photino window is initialized."); Invoke(() => Photino_SendWebMessage(_nativeInstance, message)); @@ -2377,7 +2413,7 @@ await Task.Run(() => /// The text of the notification public void SendNotification(string title, string body) { - Log($".SendNotification({title}, {body})"); + LogVerbose($".SendNotification({title}, {body})"); if (_nativeInstance == IntPtr.Zero) throw new ApplicationException("SendNotification cannot be called until after the Photino window is initialized."); Invoke(() => Photino_ShowNotification(_nativeInstance, title, body)); @@ -2495,14 +2531,34 @@ private string[] ShowOpenDialog(bool foldersOnly, string title, string defaultPa return results; } + /// + /// Logs a message with verbosity + /// + /// Log message + private void LogVerbose(string message) + { + Log(Verbose, message); + } + + /// + /// Logs a message. + /// + /// Log verbosity + /// Log message + private void Log(int verbosity, string message) + { + Log(verbosity, exception: null, message); + } + /// /// Logs a message. /// + /// Log verbosity + /// Log exception /// Log message - private void Log(string message) + private void Log(int verbosity, Exception exception, string message) { - if (LogVerbosity < 1) return; - Console.WriteLine($"Photino.NET: \"{Title ?? "PhotinoWindow"}\"{message}"); + Logger.Log(verbosity, exception, message); } ///