diff options
23 files changed, 392 insertions, 75 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 8634e02..c928c80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## 14/04/2022 - v3.3.2 + +- **UI:** + - (Add) Setting: Restore window last position - If enabled, it will restore the main window last known client position on startup (#460) + - (Add) Setting: Restore window last size - If enabled, it will restore the main window last known client size on startup (#460) + - (Improvement) If there are missing dependencies it will show a proper window with information instead of crashing application without any visuals + - (Improvement) Start maximized is set before windows spawn to prevent the flicker effect on main window +- (Add) File formats: Property `IsUsingTSMC` - Indicates whatever file globals are using TSMC or not +- (Change) Lithophane: Noise removal and gap closing iterations defaults to 0 +- (Fix) Anycubic files: Printers are unable to use TSMC values after save (#457) +- (Fix) Pixel Editor button is hidden when using screens with scalling > 100% [dirty-fix] (#458) +- (Upgrade) .NET from 6.0.3 to 6.0.4 + ## 11/04/2022 - v3.3.1 - **PrusaSlicer:** diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 38941a0..91d56c0 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,9 +1,11 @@ -- **PrusaSlicer:** - - (Add) AnyCubic M3 - - (Add) AnyCubic M3 Max - - (Add) AnyCubic M3 Plus - - (Change) AnyCubic Photon Mono 4K: Display size and remove offset from bed shape - - (Change) AnyCubic Photon Mono X 6K: Display size and remove offset from bed shape -- (Add) File format: AnyCubic PM3 and PM3M (#454) -- (Fix) Tool - Lithophane: Value unit for "Lithophane height" was in px instead of mm +- **UI:** + - (Add) Setting: Restore window last position - If enabled, it will restore the main window last known client position on startup (#460) + - (Add) Setting: Restore window last size - If enabled, it will restore the main window last known client size on startup (#460) + - (Improvement) If there are missing dependencies it will show a proper window with information instead of crashing application without any visuals + - (Improvement) Start maximized is set before windows spawn to prevent the flicker effect on main window +- (Add) File formats: Property `IsUsingTSMC` - Indicates whatever file globals are using TSMC or not +- (Change) Lithophane: Noise removal and gap closing iterations defaults to 0 +- (Fix) Anycubic files: Printers are unable to use TSMC values after save (#457) +- (Fix) Pixel Editor button is hidden when using screens with scalling > 100% [dirty-fix] (#458) +- (Upgrade) .NET from 6.0.3 to 6.0.4 diff --git a/Scripts/010 Editor/PhotonWorkshop.bt b/Scripts/010 Editor/PhotonWorkshop.bt index 2837e63..64fd785 100644 --- a/Scripts/010 Editor/PhotonWorkshop.bt +++ b/Scripts/010 Editor/PhotonWorkshop.bt @@ -52,14 +52,15 @@ struct HEADER { uint ResolutionY <fgcolor=cBlack, bgcolor=cRed>; float WeightG <fgcolor=cBlack, bgcolor=cRed>; float Price <fgcolor=cBlack, bgcolor=cRed>; - uint PriceCurrencyDec <fgcolor=cBlack, bgcolor=cRed>; + wstring PriceCurrencyDec <fgcolor=cBlack, bgcolor=cRed>; uint PerLayerOverride <fgcolor=cBlack, bgcolor=cRed>; uint PrintTime <fgcolor=cBlack, bgcolor=cRed>; uint TransitionLayerCount <fgcolor=cBlack, bgcolor=cRed>; uint Padding <fgcolor=cBlack, bgcolor=cRed>; - if(fileMark.Version > 515){ - uint Padding <fgcolor=cBlack, bgcolor=cRed>; + if(fileMark.Version >= 516){ + // 0 = Basic mode | 1 = Advanced mode which allows TSMC + uint AdvancedMode <fgcolor=cBlack, bgcolor=cRed>; } }; diff --git a/UVtools.Core/FileFormats/FileFormat.cs b/UVtools.Core/FileFormats/FileFormat.cs index 6102aef..d8b1a2a 100644 --- a/UVtools.Core/FileFormats/FileFormat.cs +++ b/UVtools.Core/FileFormats/FileFormat.cs @@ -1379,6 +1379,11 @@ public abstract class FileFormat : BindableBase, IDisposable, IEquatable<FileFor /// </summary> public bool AnyLayerIsUsingTSMC => this.Any(layer => layer.IsUsingTSMC); + /// <summary> + /// True if the file global property is using TSMC, otherwise false when not using + /// </summary> + public bool IsUsingTSMC => (CanUseAnyLiftHeight2 || CanUseAnyRetractHeight2) && (LiftHeight2 > 0 || RetractHeight2 > 0); + /// <summary> /// Gets if any layer got modified, otherwise false diff --git a/UVtools.Core/FileFormats/PhotonWorkshopFile.cs b/UVtools.Core/FileFormats/PhotonWorkshopFile.cs index 3025610..43ab3a4 100644 --- a/UVtools.Core/FileFormats/PhotonWorkshopFile.cs +++ b/UVtools.Core/FileFormats/PhotonWorkshopFile.cs @@ -334,7 +334,7 @@ public class PhotonWorkshopFile : FileFormat [FieldOrder(15)] public float Price { get; set; } /// <summary> - /// 24 00 00 00 $ or ¥ C2 A5 00 or € = E2 82 AC 00 + /// 24 00 00 00 $ or ¥ C2 A5 00 00 or € = E2 82 AC 00 /// 7C /// </summary> [FieldOrder(16)] public uint PriceCurrencyDec { get; set; } = 0x24; @@ -1644,8 +1644,8 @@ public class PhotonWorkshopFile : FileFormat Helpers.SerializeWriteFileStream(outputFile, HeaderSettings); if (FileMarkSettings.Version >= VERSION_516) { - //outputFile.WriteUIntLittleEndian(0); - outputFile.Seek(4, SeekOrigin.Current); // Extra padding + outputFile.WriteUIntLittleEndian(System.Convert.ToUInt32(IsUsingTSMC)); + //outputFile.Seek(4, SeekOrigin.Current); // Extra padding } if (CreatedThumbnailsCount > 0) diff --git a/UVtools.Core/Operations/OperationLithophane.cs b/UVtools.Core/Operations/OperationLithophane.cs index e40caa7..e0e6786 100644 --- a/UVtools.Core/Operations/OperationLithophane.cs +++ b/UVtools.Core/Operations/OperationLithophane.cs @@ -49,8 +49,8 @@ public class OperationLithophane : Operation private decimal _resizeFactor = 100; private bool _enhanceContrast; private sbyte _brightnessGain; - private byte _gapClosingIterations = 4; - private byte _removeNoiseIterations = 4; + private byte _gapClosingIterations; + private byte _removeNoiseIterations; private byte _gaussianBlur; private byte _startThresholdRange = 1; private byte _endThresholdRange = byte.MaxValue; diff --git a/UVtools.Core/SystemOS/SystemAware.cs b/UVtools.Core/SystemOS/SystemAware.cs index 33a8d43..a7d7573 100644 --- a/UVtools.Core/SystemOS/SystemAware.cs +++ b/UVtools.Core/SystemOS/SystemAware.cs @@ -300,4 +300,29 @@ public static class SystemAware /// Gets if is running under MacOS and under app format /// </summary> public static bool IsRunningMacOSApp => OperatingSystem.IsMacOS() && AppContext.BaseDirectory.EndsWith(".app/Contents/MacOS"); + + /// <summary> + /// Gets the main name of the operative system + /// </summary> + public static string OperatingSystemName + { + get + { + if (OperatingSystem.IsWindows()) return "Windows"; + if (OperatingSystem.IsMacOS()) return "macOS"; + if (OperatingSystem.IsLinux()) return "Linux"; + if (OperatingSystem.IsFreeBSD()) return "FreeBSD"; + if (OperatingSystem.IsAndroid()) return "Android"; + if (OperatingSystem.IsIOS()) return "iOS"; + if (OperatingSystem.IsTvOS()) return "Tv OS"; + if (OperatingSystem.IsWatchOS()) return "WatchOS"; + if (OperatingSystem.IsBrowser()) return "Browser"; + return "Unknown"; + } + } + + /// <summary> + /// Gets the main name of the operative system with architecture + /// </summary> + public static string OperatingSystemNameWithArch => $"{OperatingSystemName} {RuntimeInformation.OSArchitecture}"; }
\ No newline at end of file diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj index a78d002..6b451da 100644 --- a/UVtools.Core/UVtools.Core.csproj +++ b/UVtools.Core/UVtools.Core.csproj @@ -10,7 +10,7 @@ <RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl> <PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl> <Description>MSLA/DLP, file analysis, calibration, repair, conversion and manipulation</Description> - <Version>3.3.1</Version> + <Version>3.3.2</Version> <Copyright>Copyright © 2020 PTRTECH</Copyright> <PackageIcon>UVtools.png</PackageIcon> <Platforms>AnyCPU;x64</Platforms> @@ -70,7 +70,7 @@ <PackageReference Include="Portable.BouncyCastle" Version="1.9.0" /> <PackageReference Include="System.Memory" Version="4.5.4" /> <PackageReference Include="System.Reflection.TypeExtensions" Version="4.7.0" /> - <PackageReference Include="System.Text.Json" Version="6.0.2" /> + <PackageReference Include="System.Text.Json" Version="6.0.3" /> </ItemGroup> <Target Name="PreparePackageReleaseNotesFromFile" BeforeTargets="GenerateNuspec"> diff --git a/UVtools.InstallerMM/UVtools.InstallerMM.wxs b/UVtools.InstallerMM/UVtools.InstallerMM.wxs index 428cfbe..c641e82 100644 --- a/UVtools.InstallerMM/UVtools.InstallerMM.wxs +++ b/UVtools.InstallerMM/UVtools.InstallerMM.wxs @@ -2,7 +2,7 @@ <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> <?define ComponentRules="OneToOne"?> <!-- SourceDir instructs IsWiX the location of the directory that contains files for this merge module --> - <?define SourceDir="..\publish\UVtools_win-x64_v3.3.1"?> + <?define SourceDir="..\publish\UVtools_win-x64_v3.3.2"?> <Module Id="UVtools" Language="1033" Version="1.0.0.0"> <Package Id="12aaa1cf-ff06-4a02-abd5-2ac01ac4f83b" Manufacturer="PTRTECH" InstallerVersion="200" Keywords="MSLA, DLP" Description="MSLA/DLP, file analysis, repair, conversion and manipulation" InstallScope="perMachine" Platform="x64" /> <Directory Id="TARGETDIR" Name="SourceDir"> @@ -1500,9 +1500,6 @@ <Component Id="owc8DBF076FA26C4EC39811CAD12FD3937C" Guid="8DBF076F-A26C-4EC3-9811-CAD12FD3937C"> <File Id="owf8DBF076FA26C4EC39811CAD12FD3937C" Source="$(var.SourceDir)\api-ms-win-core-fibers-l1-1-0.dll" KeyPath="yes" /> </Component> - <Component Id="owc04789579CAEC4E9D884765B39BA4BC5D" Guid="04789579-CAEC-4E9D-8847-65B39BA4BC5D"> - <File Id="owf04789579CAEC4E9D884765B39BA4BC5D" Source="$(var.SourceDir)\mscordaccore_amd64_amd64_6.0.322.12309.dll" KeyPath="yes" /> - </Component> <Component Id="owcF431B2B5B6264D78AAFA361A07841A68" Guid="F431B2B5-B626-4D78-AAFA-361A07841A68"> <File Id="owfF431B2B5B6264D78AAFA361A07841A68" Source="$(var.SourceDir)\msquic.dll" KeyPath="yes" /> </Component> @@ -1557,6 +1554,9 @@ <Component Id="owcD2245B900E5C448485AD96FE57629D9D" Guid="D2245B90-0E5C-4484-85AD-96FE57629D9D"> <File Id="owfD2245B900E5C448485AD96FE57629D9D" Source="$(var.SourceDir)\UVtoolsCmd.runtimeconfig.json" KeyPath="yes" /> </Component> + <Component Id="owc47E738FB97A34F13812E87CF7F2B4643" Guid="47E738FB-97A3-4F13-812E-87CF7F2B4643"> + <File Id="owf47E738FB97A34F13812E87CF7F2B4643" Source="$(var.SourceDir)\mscordaccore_amd64_amd64_6.0.422.16404.dll" KeyPath="yes" /> + </Component> </Directory> <Directory Id="ProgramMenuFolder"> <Directory Id="scd220707349D4C8FA275285514283F3E2A" Name="UVtools" /> diff --git a/UVtools.WPF/App.axaml.cs b/UVtools.WPF/App.axaml.cs index 61f3b8b..163df81 100644 --- a/UVtools.WPF/App.axaml.cs +++ b/UVtools.WPF/App.axaml.cs @@ -27,6 +27,7 @@ using UVtools.Core.Managers; using UVtools.Core.SystemOS; using UVtools.WPF.Extensions; using UVtools.WPF.Structures; +using UVtools.WPF.Windows; using Bitmap = Avalonia.Media.Imaging.Bitmap; namespace UVtools.WPF; @@ -172,21 +173,8 @@ public class App : Application AvaloniaXamlLoader.Load(this); } - public override async void OnFrameworkInitializationCompleted() + public override void OnFrameworkInitializationCompleted() { - if (Design.IsDesignMode) - { - SlicerFile = new ChituboxFile - { - LayerHeight = 0.05f, - Resolution = new (1440, 2560), - Display = new (68.04f, 120.96f), - DisplayMirror = FlipDirection.Horizontally, - MachineZ = 155, - BottomLayerCount = 3, - MachineName = "Epax X1" - }; - } if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { UserSettings.Load(); @@ -208,21 +196,70 @@ public class App : Application } }*/ - if (!CvInvoke.Init()) + /*if (!CvInvoke.Init()) { Console.WriteLine("UVtools can not init OpenCV library\n" + "Please build or install this dependencies in order to run UVtools\n" + "Check manual or page at 'Requirements' section for help"); - } + }*/ if (UserSettings.Instance.General.Theme != ApplicationTheme.FluentLight) { ApplyTheme(); } - MainWindow = new MainWindow(); try { + if (CvInvoke.Init()) + { + if (Design.IsDesignMode) + { + SlicerFile = new ChituboxFile + { + LayerHeight = 0.05f, + Resolution = new(1440, 2560), + Display = new(68.04f, 120.96f), + DisplayMirror = FlipDirection.Horizontally, + MachineZ = 155, + BottomLayerCount = 3, + MachineName = "Epax X1" + }; + } + + MainWindow = new MainWindow(); + if (UserSettings.Instance.General.StartMaximized) + { + MainWindow.WindowState = WindowState.Maximized; + } + else + { + if (UserSettings.Instance.General.RestoreWindowLastSize) + { + MainWindow.Width = UserSettings.Instance.General.LastWindowBounds.Width; + MainWindow.Height = UserSettings.Instance.General.LastWindowBounds.Height; + } + + if (UserSettings.Instance.General.RestoreWindowLastPosition) + { + MainWindow.Position = new PixelPoint(UserSettings.Instance.General.LastWindowBounds.Location.X, UserSettings.Instance.General.LastWindowBounds.Location.Y); + } + } + desktop.MainWindow = MainWindow; + } + else + { + desktop.MainWindow = new CantRunWindow(); + } + } + catch (Exception e) + { + desktop.MainWindow = new CantRunWindow(); + Console.WriteLine(e.ToString()); + } + + + /*try + { if(!CvInvoke.Init()) await MainWindow.MessageBoxError("UVtools can not init OpenCV library\n" + "Please build or install this dependencies in order to run UVtools\n" + @@ -237,9 +274,9 @@ public class App : Application "Additional information:\n" + $"{e}", "UVtools can not run"); return; - } + }*/ - desktop.MainWindow = MainWindow; + //desktop.Exit += (sender, e) => ThemeSelector.SaveSelectedTheme(Path.Combine(UserSettings.SettingsFolder, "selected.theme")); } diff --git a/UVtools.WPF/Assets/Styles/Styles.xaml b/UVtools.WPF/Assets/Styles/Styles.xaml index 05e5ccf..144009a 100644 --- a/UVtools.WPF/Assets/Styles/Styles.xaml +++ b/UVtools.WPF/Assets/Styles/Styles.xaml @@ -5,6 +5,10 @@ <Border Padding="20"></Border> </Design.PreviewWith> + <Styles.Resources> + <SolidColorBrush x:Key="LogoColor" Color="#660066" /> + </Styles.Resources> + <Style Selector="Border.LayerNavigationToolTip"> <Setter Property="BorderThickness" Value="5"/> diff --git a/UVtools.WPF/Controls/ButtonWithIcon.cs b/UVtools.WPF/Controls/ButtonWithIcon.cs index 11edc87..576df3a 100644 --- a/UVtools.WPF/Controls/ButtonWithIcon.cs +++ b/UVtools.WPF/Controls/ButtonWithIcon.cs @@ -11,6 +11,7 @@ using Avalonia.Controls; using Avalonia.Layout; using Avalonia.Styling; using Avalonia.Threading; +using JetBrains.Annotations; namespace UVtools.WPF.Controls; @@ -44,9 +45,10 @@ public class ButtonWithIcon : Button, IStyleable set => SetValue(IconPlacementProperty, value); } - public static readonly StyledProperty<string> IconProperty = - AvaloniaProperty.Register<ButtonWithIcon, string>(nameof(Icon)); + public static readonly StyledProperty<string?> IconProperty = + AvaloniaProperty.Register<ButtonWithIcon, string?>(nameof(Icon)); + [CanBeNull] public string Icon { get => GetValue(IconProperty); diff --git a/UVtools.WPF/Controls/Tools/ToolLithophaneControl.axaml b/UVtools.WPF/Controls/Tools/ToolLithophaneControl.axaml index 050866f..e1a68a0 100644 --- a/UVtools.WPF/Controls/Tools/ToolLithophaneControl.axaml +++ b/UVtools.WPF/Controls/Tools/ToolLithophaneControl.axaml @@ -122,7 +122,7 @@ <TextBlock Grid.Row="12" Grid.Column="0" VerticalAlignment="Center" - Text="Remove noise:"/> + Text="Noise removal:"/> <NumericUpDown Grid.Row="12" Grid.Column="2" Classes="ValueLabel ValueLabel_px" diff --git a/UVtools.WPF/MainWindow.axaml b/UVtools.WPF/MainWindow.axaml index 95b010c..64266e2 100644 --- a/UVtools.WPF/MainWindow.axaml +++ b/UVtools.WPF/MainWindow.axaml @@ -1838,7 +1838,7 @@ Command="{Binding OpenContextMenu}" CommandParameter="LayerPreviewOutline" VerticalAlignment="Stretch" - Margin="1,0,0,0" + Margin="1,0,2,0" Text="Outline ⮟" Spacing="5" Icon="fas fa-vector-square"> @@ -1895,11 +1895,11 @@ </uc:ButtonWithIcon> - <uc:ToggleButtonWithIcon HorizontalAlignment="Right" + <uc:ToggleButtonWithIcon IsChecked="{Binding IsPixelEditorActive}" ToolTip.Tip="Edit layer image: Draw pixels, add supports and/or drain holes." VerticalAlignment="Stretch" - Margin="0,0,0,0" + Margin="-1,0,0,0" Text="Pixel editor" Spacing="5" Icon="fas fa-drafting-compass"/> diff --git a/UVtools.WPF/MainWindow.axaml.cs b/UVtools.WPF/MainWindow.axaml.cs index efdda1d..d2b2fb5 100644 --- a/UVtools.WPF/MainWindow.axaml.cs +++ b/UVtools.WPF/MainWindow.axaml.cs @@ -431,20 +431,9 @@ public partial class MainWindow : WindowEx UpdateTitle(); - var clientSizeObs = this.GetObservable(ClientSizeProperty); - clientSizeObs.Subscribe(size => UpdateLayerTrackerHighlightIssues()); - var windowStateObs = this.GetObservable(WindowStateProperty); - windowStateObs.Subscribe(windowsState => UpdateLayerTrackerHighlightIssues()); - - + DataContext = this; - AddHandler(DragDrop.DropEvent, (sender, e) => - { - if (!_isGUIEnabled) return; - ProcessFiles(e.Data.GetFileNames()?.ToArray()); - }); - _menuFileSendTo = this.FindControl<MenuItem>("MainMenu.File.SendTo"); this.FindControl<MenuItem>("MainMenu.File").SubmenuOpened += (sender, e) => { @@ -853,9 +842,28 @@ public partial class MainWindow : WindowEx base.OnOpened(e); var windowSize = this.GetScreenWorkingArea(); - if (Settings.General.StartMaximized - || ClientSize.Width > windowSize.Width - || ClientSize.Height > windowSize.Height) + var clientSizeObs = this.GetObservable(ClientSizeProperty); + clientSizeObs.Subscribe(size => + { + Settings.General._lastWindowBounds.Width = (int)size.Width; + Settings.General._lastWindowBounds.Height = (int)size.Height; + UpdateLayerTrackerHighlightIssues(); + }); + var windowStateObs = this.GetObservable(WindowStateProperty); + windowStateObs.Subscribe(windowsState => UpdateLayerTrackerHighlightIssues()); + PositionChanged += (sender, args) => + { + Settings.General._lastWindowBounds.X = Math.Max(0, Position.X); + Settings.General._lastWindowBounds.Y = Math.Max(0, Position.Y); + }; + + AddHandler(DragDrop.DropEvent, (sender, args) => + { + if (!_isGUIEnabled) return; + ProcessFiles(args.Data.GetFileNames()?.ToArray()); + }); + + if (!Settings.General.StartMaximized && (ClientSize.Width >= windowSize.Width || ClientSize.Height >= windowSize.Height)) { WindowState = WindowState.Maximized; } @@ -898,6 +906,18 @@ public partial class MainWindow : WindowEx }*/ } + protected override void OnClosed(EventArgs e) + { + base.OnClosed(e); + + if (!UserSettings.Instance.General.StartMaximized && + (UserSettings.Instance.General.RestoreWindowLastPosition || + UserSettings.Instance.General.RestoreWindowLastSize)) + { + UserSettings.Save(); + } + } + private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) { Debug.WriteLine(e.PropertyName); @@ -1348,6 +1368,8 @@ public partial class MainWindow : WindowEx } } + //title += $" [{RuntimeInformation.RuntimeIdentifier}]"; + #if DEBUG title += " [DEBUG]"; #endif diff --git a/UVtools.WPF/Program.cs b/UVtools.WPF/Program.cs index 0fb088d..67389bd 100644 --- a/UVtools.WPF/Program.cs +++ b/UVtools.WPF/Program.cs @@ -58,6 +58,8 @@ public static class Program AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException; //AppDomain.CurrentDomain.FirstChanceException += CurrentDomainOnFirstChanceException; BuildAvaloniaApp().StartWithClassicDesktopLifetime(args); + + // Closing } private static void CurrentDomainOnFirstChanceException(object? sender, FirstChanceExceptionEventArgs e) diff --git a/UVtools.WPF/UVtools.WPF.csproj b/UVtools.WPF/UVtools.WPF.csproj index 8708537..5cec53c 100644 --- a/UVtools.WPF/UVtools.WPF.csproj +++ b/UVtools.WPF/UVtools.WPF.csproj @@ -12,7 +12,7 @@ <PackageLicenseFile>LICENSE</PackageLicenseFile> <RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl> <RepositoryType>Git</RepositoryType> - <Version>3.3.1</Version> + <Version>3.3.2</Version> <Platforms>AnyCPU;x64</Platforms> <PackageIcon>UVtools.png</PackageIcon> <PackageReadmeFile>README.md</PackageReadmeFile> diff --git a/UVtools.WPF/UserSettings.cs b/UVtools.WPF/UserSettings.cs index 898fd6f..37adc53 100644 --- a/UVtools.WPF/UserSettings.cs +++ b/UVtools.WPF/UserSettings.cs @@ -10,6 +10,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; +using System.Drawing; using System.IO; using System.Xml.Serialization; using Avalonia.Media; @@ -38,7 +39,10 @@ public sealed class UserSettings : BindableBase public sealed class GeneralUserSettings : BindableBase { private App.ApplicationTheme _theme = App.ApplicationTheme.FluentLight; + internal Rectangle _lastWindowBounds = new(40, 40, 1024, 600); private bool _startMaximized = true; + private bool _restoreWindowLastPosition; + private bool _restoreWindowLastSize; private bool _checkForUpdatesOnStartup = true; private bool _loadDemoFileOnStartup = true; private bool _loadLastRecentFileOnStartup; @@ -68,12 +72,30 @@ public sealed class UserSettings : BindableBase set => RaiseAndSetIfChanged(ref _theme, value); } + public Rectangle LastWindowBounds + { + get => _lastWindowBounds; + set => RaiseAndSetIfChanged(ref _lastWindowBounds, value); + } + public bool StartMaximized { get => _startMaximized; set => RaiseAndSetIfChanged(ref _startMaximized, value); } + public bool RestoreWindowLastPosition + { + get => _restoreWindowLastPosition; + set => RaiseAndSetIfChanged(ref _restoreWindowLastPosition, value); + } + + public bool RestoreWindowLastSize + { + get => _restoreWindowLastSize; + set => RaiseAndSetIfChanged(ref _restoreWindowLastSize, value); + } + public bool CheckForUpdatesOnStartup { get => _checkForUpdatesOnStartup; diff --git a/UVtools.WPF/Windows/AboutWindow.axaml b/UVtools.WPF/Windows/AboutWindow.axaml index c39f539..0a93a82 100644 --- a/UVtools.WPF/Windows/AboutWindow.axaml +++ b/UVtools.WPF/Windows/AboutWindow.axaml @@ -42,8 +42,7 @@ VerticalContentAlignment="Center" HorizontalAlignment="Right" Icon="fas fa-sign-out-alt" - Text="Close"> - </controls:ButtonWithIcon> + Text="Close"/> </Grid> </Border> diff --git a/UVtools.WPF/Windows/AboutWindow.axaml.cs b/UVtools.WPF/Windows/AboutWindow.axaml.cs index a4a8966..9fa0726 100644 --- a/UVtools.WPF/Windows/AboutWindow.axaml.cs +++ b/UVtools.WPF/Windows/AboutWindow.axaml.cs @@ -13,7 +13,23 @@ namespace UVtools.WPF.Windows; public class AboutWindow : WindowEx { - public static string OpenCVBuildInformation => CvInvoke.BuildInformation; + public static string OpenCVBuildInformation + { + get + { + try + { + return CvInvoke.BuildInformation; + } + catch + { + // ignored + } + + return "Error: Unable to load the library."; + } + } + public static string LoadedAssemblies { get @@ -41,12 +57,20 @@ public class AboutWindow : WindowEx { get { - var match = Regex.Match(CvInvoke.BuildInformation, @"(?:Version control:\s*)(\S*)"); - if (!match.Success) return "Not found!"; - var index = match.Groups[1].Value.LastIndexOf('-'); - if (index < 0) return match.Groups[1].Value; - return match.Groups[1].Value[..index]; - //return match.Groups[1].Value; + try + { + var match = Regex.Match(CvInvoke.BuildInformation, @"(?:Version control:\s*)(\S*)"); + if (!match.Success) return "Not found!"; + var index = match.Groups[1].Value.LastIndexOf('-'); + if (index < 0) return match.Groups[1].Value; + return match.Groups[1].Value[..index]; + } + catch + { + // ignored + } + + return "???"; } } @@ -81,7 +105,8 @@ public class AboutWindow : WindowEx var result = new StringBuilder(); for (var i = 0; i < Screens.All.Count; i++) { - var onScreen = Screens.ScreenFromVisual(App.MainWindow); + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + var onScreen = Screens.ScreenFromVisual(App.MainWindow is not null ? App.MainWindow : this); var screen = Screens.All[i]; result.AppendLine($"{i+1}: {screen.Bounds.Width} x {screen.Bounds.Height} @ {screen.PixelDensity * 100}%" + (screen.Primary ? " (Primary)" : string.Empty) + diff --git a/UVtools.WPF/Windows/CantRunWindow.axaml b/UVtools.WPF/Windows/CantRunWindow.axaml new file mode 100644 index 0000000..18e5307 --- /dev/null +++ b/UVtools.WPF/Windows/CantRunWindow.axaml @@ -0,0 +1,102 @@ +<Window xmlns="https://github.com/avaloniaui" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:i="clr-namespace:Projektanker.Icons.Avalonia;assembly=Projektanker.Icons.Avalonia" + xmlns:core="clr-namespace:UVtools.Core;assembly=UVtools.Core" + xmlns:uc="clr-namespace:UVtools.WPF.Controls" + xmlns:systemOs="clr-namespace:UVtools.Core.SystemOS;assembly=UVtools.Core" + mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" + x:Class="UVtools.WPF.Windows.CantRunWindow" + Icon="/Assets/Icons/UVtools.ico" + WindowStartupLocation="CenterScreen" + CanResize="False" + SizeToContent="WidthAndHeight" + Title="{Binding Source={x:Static core:About.SoftwareWithVersion}, StringFormat={}{0} is unable to run}}"> + <Grid RowDefinitions="Auto,*,Auto"> + <Border Grid.Row="0" + Padding="20" + Classes="Header"> + <StackPanel Orientation="Horizontal" + Spacing="10"> + <i:Icon FontSize="64" + FontWeight="Bold" + Value="far fa-frown" + Foreground="{StaticResource LogoColor}" + HorizontalAlignment="Center"/> + + <TextBox Classes="TransparentReadOnly" + FontWeight="Bold"> + <TextBlock.Text> + <MultiBinding StringFormat="{}{0} [{1}] +
Unable to run due one or more missing dependencies. +
Triggered by: libcvextern (OpenCV)"> + <Binding Source="{x:Static core:About.SoftwareWithVersionArch}"/> + <Binding Source="{x:Static systemOs:SystemAware.OperatingSystemName}"/> + </MultiBinding> + </TextBlock.Text> + </TextBox> + + </StackPanel> + </Border> + + + <TextBox Grid.Row="1" + Classes="TransparentReadOnly" + Padding="20" + Text="Your system doesn't have the required dependencies in order to run. +
Those dependencies are required at libcvextern/OpenCV library. +
UVtools is built on top of the OpenCV and therefore cannot run. +
 +
Please install or build the dependencies in order to run the software. +
Check the manual page at 'Requirements' section for help."/> + + <Border Grid.Row="2" + Margin="0" + Classes="FooterActions"> + + <Grid ColumnDefinitions="Auto,*"> + <Button Grid.Column="0" + Command="{Binding OpenAboutWindow}"> + <StackPanel Orientation="Horizontal" Spacing="10"> + <Image Source="/Assets/Icons/UVtools.ico" + Height="26"/> + + <TextBlock VerticalAlignment="Center" + Text="About"/> + </StackPanel> + </Button> + + <StackPanel Grid.Column="1" Orientation="Horizontal" + Spacing="5" + HorizontalAlignment="Right"> + + <uc:ButtonWithIcon Padding="10" + VerticalContentAlignment="Center" + Icon="fab fa-edge" + Text="Open manual" + Command="{Binding OpenBrowser}" + CommandParameter="https://github.com/sn4k3/UVtools#requirements"/> + + <uc:ButtonWithIcon Padding="10" + VerticalContentAlignment="Center" + Icon="fas fa-question" + Text="Ask for help" + Command="{Binding OpenBrowser}" + CommandParameter="https://github.com/sn4k3/UVtools/discussions/categories/q-a"/> + + <uc:ButtonWithIcon Command="{Binding Close}" + IsCancel="True" + Padding="10" + VerticalContentAlignment="Center" + Icon="fas fa-sign-out-alt" + Text="Exit"/> + </StackPanel> + </Grid> + + + + + </Border> + </Grid> +</Window> diff --git a/UVtools.WPF/Windows/CantRunWindow.axaml.cs b/UVtools.WPF/Windows/CantRunWindow.axaml.cs new file mode 100644 index 0000000..d3cb4db --- /dev/null +++ b/UVtools.WPF/Windows/CantRunWindow.axaml.cs @@ -0,0 +1,41 @@ +/* + * GNU AFFERO GENERAL PUBLIC LICENSE + * Version 3, 19 November 2007 + * Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> + * Everyone is permitted to copy and distribute verbatim copies + * of this license document, but changing it is not allowed. + */ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; +using UVtools.Core.SystemOS; + +namespace UVtools.WPF.Windows +{ + public partial class CantRunWindow : Window + { + public CantRunWindow() + { + InitializeComponent(); + DataContext = this; +#if DEBUG + this.AttachDevTools(); +#endif + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + + public void OpenBrowser(string url) + { + SystemAware.OpenBrowser(url); + } + + public async void OpenAboutWindow() + { + await new AboutWindow().ShowDialog(this); + } + } +} diff --git a/UVtools.WPF/Windows/SettingsWindow.axaml b/UVtools.WPF/Windows/SettingsWindow.axaml index e5b44ab..88c8e5d 100644 --- a/UVtools.WPF/Windows/SettingsWindow.axaml +++ b/UVtools.WPF/Windows/SettingsWindow.axaml @@ -34,8 +34,23 @@ SelectedItem="{Binding Settings.General.Theme, Converter={StaticResource FromValueDescriptionToEnumConverter}}"/> </StackPanel> - <CheckBox IsChecked="{Binding Settings.General.StartMaximized}" Content="Start maximized"/> - <CheckBox IsChecked="{Binding Settings.General.CheckForUpdatesOnStartup}" Content="Check for updates on startup"/> + + <StackPanel Orientation="Horizontal" Spacing="20"> + <CheckBox IsChecked="{Binding Settings.General.StartMaximized}" + ToolTip.Tip="If enabled, the main window will show up maximized" + Content="Start maximized"/> + + <CheckBox IsChecked="{Binding Settings.General.RestoreWindowLastPosition}" + IsEnabled="{Binding !Settings.General.StartMaximized}" + ToolTip.Tip="If enabled, it will restore the main window last known client position on startup" + Content="Restore window last position"/> + + <CheckBox IsChecked="{Binding Settings.General.RestoreWindowLastSize}" + IsEnabled="{Binding !Settings.General.StartMaximized}" + ToolTip.Tip="If enabled, it will restore the main window last known client size on startup" + Content="Restore window last size"/> + </StackPanel> + <CheckBox IsChecked="{Binding Settings.General.CheckForUpdatesOnStartup}" Content="Check for updates on startup"/> <CheckBox IsChecked="{Binding Settings.General.LoadDemoFileOnStartup}" Content="Loads a demo file on startup if no file was specified"/> <CheckBox IsChecked="{Binding Settings.General.LoadLastRecentFileOnStartup}" Content="Loads the last recent file on startup if no file was specified"/> </StackPanel> |