diff options
author | Tiago Conceição <Tiago_caza@hotmail.com> | 2020-10-14 01:02:40 +0300 |
---|---|---|
committer | Tiago Conceição <Tiago_caza@hotmail.com> | 2020-10-14 01:02:40 +0300 |
commit | 4230f8753dd0fad63c0b1a4b496494a07ed7c114 (patch) | |
tree | b143e28c04fa3d7b13c3c05fa640de643178479f | |
parent | 1a0229a654c49385d9c757383d30f0d38882d3d7 (diff) |
WPF progress
-rw-r--r-- | UVtools.Core/UVtools.Core.csproj | 6 | ||||
-rw-r--r-- | UVtools.GUI/Properties/AssemblyInfo.cs | 4 | ||||
-rw-r--r-- | UVtools.WPF/App.axaml.cs | 3 | ||||
-rw-r--r-- | UVtools.WPF/AppSettings.cs | 13 | ||||
-rw-r--r-- | UVtools.WPF/Controls/AdvancedImageBox.cs | 188 | ||||
-rw-r--r-- | UVtools.WPF/MainWindow.LayerPreview.cs | 3 | ||||
-rw-r--r-- | UVtools.WPF/MainWindow.axaml | 9 | ||||
-rw-r--r-- | UVtools.WPF/MainWindow.axaml.cs | 19 | ||||
-rw-r--r-- | UVtools.WPF/Structures/AppVersionChecker.cs | 69 | ||||
-rw-r--r-- | UVtools.WPF/Windows/ToolWindow.axaml.cs | 20 |
10 files changed, 225 insertions, 109 deletions
diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj index 3e9ed20..a24e981 100644 --- a/UVtools.Core/UVtools.Core.csproj +++ b/UVtools.Core/UVtools.Core.csproj @@ -10,12 +10,12 @@ <RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl> <PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl> <Description>MSLA/DLP, file analysis, repair, conversion and manipulation</Description> - <Version>0.8.4.3</Version> + <Version>0.8.4.4</Version> <Copyright>Copyright © 2020 PTRTECH</Copyright> <PackageIcon>UVtools.png</PackageIcon> <Platforms>AnyCPU;x64</Platforms> - <AssemblyVersion>0.8.4.3</AssemblyVersion> - <FileVersion>0.8.4.3</FileVersion> + <AssemblyVersion>0.8.4.4</AssemblyVersion> + <FileVersion>0.8.4.4</FileVersion> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> diff --git a/UVtools.GUI/Properties/AssemblyInfo.cs b/UVtools.GUI/Properties/AssemblyInfo.cs index 36d551e..9708a4b 100644 --- a/UVtools.GUI/Properties/AssemblyInfo.cs +++ b/UVtools.GUI/Properties/AssemblyInfo.cs @@ -35,5 +35,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.8.4.3")] -[assembly: AssemblyFileVersion("0.8.4.3")] +[assembly: AssemblyVersion("0.8.4.4")] +[assembly: AssemblyFileVersion("0.8.4.4")] diff --git a/UVtools.WPF/App.axaml.cs b/UVtools.WPF/App.axaml.cs index 7a819ce..e1b6fdb 100644 --- a/UVtools.WPF/App.axaml.cs +++ b/UVtools.WPF/App.axaml.cs @@ -22,6 +22,7 @@ using Avalonia.ThemeManager; using Emgu.CV; using UVtools.Core.FileFormats; using UVtools.WPF.Extensions; +using UVtools.WPF.Structures; namespace UVtools.WPF { @@ -31,6 +32,8 @@ namespace UVtools.WPF public static MainWindow MainWindow; public static FileFormat SlicerFile = null; + public static AppVersionChecker VersionChecker { get; } = new AppVersionChecker(); + public override void Initialize() { AvaloniaXamlLoader.Load(this); diff --git a/UVtools.WPF/AppSettings.cs b/UVtools.WPF/AppSettings.cs index b3d7ac6..95d1825 100644 --- a/UVtools.WPF/AppSettings.cs +++ b/UVtools.WPF/AppSettings.cs @@ -1,8 +1,13 @@ -using System; -using System.Collections.Generic; +/* + * 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 System; using System.Linq; using System.Reflection; -using System.Text; using UVtools.Core.FileFormats; namespace UVtools.WPF @@ -14,7 +19,7 @@ namespace UVtools.WPF // These settings eliminate very small zoom factors from the ImageBox default values, // while ensuring that 4K/5K build plates can still easily fit on screen. public static readonly int[] ZoomLevels = - {20, 25, 30, 50, 75, 100, 150, 200, 300, 400, 500, 600, 700, 800, 1200, 1600}; + {20, 25, 30, 50, 75, 100, 150, 200, 300, 400, 500, 600, 700, 800, 1200, 1600, 3200}; // Count of the bottom portion of the full zoom range which will be skipped for // assignable actions such as auto-zoom level, and crosshair fade level. If values diff --git a/UVtools.WPF/Controls/AdvancedImageBox.cs b/UVtools.WPF/Controls/AdvancedImageBox.cs index 7fda650..1e68063 100644 --- a/UVtools.WPF/Controls/AdvancedImageBox.cs +++ b/UVtools.WPF/Controls/AdvancedImageBox.cs @@ -11,8 +11,6 @@ using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Input; using Avalonia.Media; -using Avalonia.Media.Imaging; -using Avalonia.Skia; using Avalonia.Styling; using Avalonia.Threading; using UVtools.Core.Extensions; @@ -116,7 +114,7 @@ namespace UVtools.WPF.Controls { return new ZoomLevelCollection(new[] { - 7, 10, 15, 20, 25, 30, 50, 70, 100, 150, 200, 300, 400, 500, 600, 700, 800, 1200, 1600 + 7, 10, 15, 20, 25, 30, 50, 70, 100, 150, 200, 300, 400, 500, 600, 700, 800, 1200, 1600, 3200 }); } } @@ -444,6 +442,16 @@ namespace UVtools.WPF.Controls public static readonly int MaxZoom = 3500; #endregion + public bool CanRender + { + get => _canRender; + set + { + if(!RaiseAndSetIfChanged(ref _canRender, value)) return; + if(_canRender) TriggerRender(); + } + } + /// <summary> /// Gets or sets the basic cell size /// </summary> @@ -480,20 +488,10 @@ namespace UVtools.WPF.Controls set { if (!RaiseAndSetIfChanged(ref _image, value)) return; - if (_image is null) - { - SizedContainer.Width = 0; - SizedContainer.Height = 0; - SelectNone(); - } - else - { - UpdateViewPort(); - //SizedContainer.Width = _image.Size.Width; - //SizedContainer.Height = _image.Size.Height; - } - InvalidateVisual(); + SelectNone(); + UpdateViewPort(); + TriggerRender(); } } @@ -642,15 +640,13 @@ namespace UVtools.WPF.Controls get => _zoom; set { - var previousZoom = _zoom; var newZoom = value.Clamp(MinZoom, MaxZoom); if (_zoom == newZoom) return; + var previousZoom = _zoom; _zoom = newZoom; - if (!UpdateViewPort()) - { - InvalidateArrange(); - } + UpdateViewPort(); + TriggerRender(); OldZoom = previousZoom; RaisePropertyChanged(nameof(Zoom)); @@ -703,7 +699,7 @@ namespace UVtools.WPF.Controls set { if(!RaiseAndSetIfChanged(ref _selectionRegion, value)) return; - InvalidateArrange(); + TriggerRender(); RaisePropertyChanged(nameof(HaveSelection)); } } @@ -731,16 +727,17 @@ namespace UVtools.WPF.Controls private ISolidColorBrush _selectionColor = new SolidColorBrush(new Color(127, 0, 128, 255)); private Rect _selectionRegion = Rect.Empty; private SelectionModes _selectionMode = SelectionModes.None; - + private bool _canRender = true; + public ContentControl FillContainer { get; } = new ContentControl { Background = Brushes.Transparent }; - public ContentControl SizedContainer { get; } = new ContentControl + public ContentControl SizedContainer { get; private set; } = new ContentControl { - Background = Brushes.Transparent + }; Type IStyleable.StyleKey => typeof(ScrollViewer); @@ -757,29 +754,45 @@ namespace UVtools.WPF.Controls //Container.PointerMoved += ScrollViewerOnPointerMoved; //Container.PointerPressed += ScrollViewerOnPointerPressed; //Container.PointerReleased += ScrollViewerOnPointerReleased; - - base.PropertyChanged += EventOnPropertyChanged; + } + + protected override void OnScrollChanged(ScrollChangedEventArgs e) + { + Debug.WriteLine($"ViewportDelta: {e.ViewportDelta} | OffsetDelta: {e.OffsetDelta} | ExtentDelta: {e.ExtentDelta}"); + if (!e.ViewportDelta.IsDefault) + { + UpdateViewPort(); + } + + TriggerRender(); + + base.OnScrollChanged(e); } private void FillContainerOnPointerWheelChanged(object? sender, PointerWheelEventArgs e) { - if (Image is null) return; + Debug.WriteLine("mouse whell"); e.Handled = true; + if (Image is null) return; if (AllowZoom && SizeMode == SizeModes.Normal) { // The MouseWheel event can contain multiple "spins" of the wheel so we need to adjust accordingly - double spins = Math.Abs(e.Delta.Y); + //double spins = Math.Abs(e.Delta.Y); //Debug.WriteLine(e.GetPosition(this)); // TODO: Really should update the source method to handle multiple increments rather than calling it multiple times - for (int i = 0; i < spins; i++) - { - ProcessMouseZoom(e.Delta.Y > 0, e.GetPosition(this)); - } - - //InvalidateVisual(); + /*for (int i = 0; i < spins; i++) + {*/ + ProcessMouseZoom(e.Delta.Y > 0, e.GetPosition(this)); + //} } } + public void TriggerRender() + { + if (!_canRender) return; + InvalidateVisual(); + } + private void ProcessMouseZoom(bool isZoomIn, Point cursorPosition) => PerformZoom(isZoomIn ? ZoomActions.ZoomIn : ZoomActions.ZoomOut, true, cursorPosition); @@ -835,6 +848,9 @@ namespace UVtools.WPF.Controls int currentZoom = Zoom; int newZoom = GetZoomLevel(action); + if (preservePosition && Zoom != currentZoom) + CanRender = false; + RestoreSizeMode(); Zoom = newZoom; @@ -972,10 +988,40 @@ namespace UVtools.WPF.Controls /// <param name="relativeDisplayPoint">The relative display point to offset scrolling by.</param> public virtual void ScrollTo(Point imageLocation, Point relativeDisplayPoint) { + CanRender = false; var x = imageLocation.X * ZoomFactor - relativeDisplayPoint.X; var y = imageLocation.Y * ZoomFactor - relativeDisplayPoint.Y; - - Offset = new Vector(x, y); + + //Offset = new Vector(x, y); + + _canRender = true; + + DispatcherTimer.RunOnce(() => + { + // TODO: Remove this delay? + //Debug.WriteLine($"1ms delayed viewport: {Viewport}"); + //CenterAt(new Point(cx, cy)); + + Offset = new Vector(x, y); + }, TimeSpan.FromTicks(1), DispatcherPriority.MaxValue); + + + /*Timer timer = new Timer(0.1) + { + AutoReset = false, + }; + timer.Elapsed += (sender, args) => + { + Dispatcher.UIThread.InvokeAsync(() => + { + Offset = new Vector(x, y); + CanRender = true; + timer.Dispose(); + }); + }; + timer.Start();*/ + + /*Debug.WriteLine( $"X/Y: {x},{y} | \n" + $"Offset: {Offset} | \n" + @@ -1095,28 +1141,9 @@ namespace UVtools.WPF.Controls var cx = rectangle.X + rectangle.Width / 2; var cy = rectangle.Y + rectangle.Height / 2; - - Debug.WriteLine($"Before zoom: {Viewport}"); + CanRender = false; Zoom = (int) (zoomFactor * 100); // This function sets the zoom so viewport will change - Debug.WriteLine($"After zoom, viewport changed: {Viewport}"); - - //CenterAt(new Point(cx, cy)); // If i call this here, it will move to the wrong position due wrong viewport - - Timer timer = new Timer(1) - { - AutoReset = false, - }; - timer.Elapsed += (sender, args) => - { - Dispatcher.UIThread.InvokeAsync(() => - { - // This will fix centerAt position - Debug.WriteLine($"1ms delayed viewport: {Viewport}"); - CenterAt(new Point(cx, cy)); - }); - }; - timer.Start(); - + CenterAt(new Point(cx, cy)); // If i call this here, it will move to the wrong position due wrong viewport } /// <summary> @@ -1168,13 +1195,20 @@ namespace UVtools.WPF.Controls private bool UpdateViewPort() { - if (Image is null) return false; + if (Image is null) + { + SizedContainer.Width = 0; + SizedContainer.Height = 0; + return true; + } var scaledImageWidth = ScaledImageWidth; var scaledImageHeight = ScaledImageHeight; var width = scaledImageWidth <= Viewport.Width ? Viewport.Width : scaledImageWidth; var height = scaledImageHeight <= Viewport.Height ? Viewport.Height : scaledImageHeight; + + bool changed = false; if (SizedContainer.Width != width) { @@ -1188,11 +1222,17 @@ namespace UVtools.WPF.Controls changed = true; } - if (changed) + /*if (changed) { - Debug.WriteLine($"Update ViewPort: {DateTime.Now.Ticks}"); - InvalidateArrange(); - } + var newContainer = new ContentControl + { + Width = width, + Height = height + }; + FillContainer.Content = SizedContainer = newContainer; + Debug.WriteLine($"Updated ViewPort: {DateTime.Now.Ticks}"); + //TriggerRender(); + }*/ return changed; } @@ -1208,24 +1248,6 @@ namespace UVtools.WPF.Controls Zoom = 100; } - private void EventOnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e) - { - //Debug.WriteLine(e.Property.Name); - if (e.Property.Name == nameof(VerticalScrollBarValue) || - e.Property.Name == nameof(HorizontalScrollBarValue)) - { - InvalidateArrange(); - return; - } - - if(e.Property.Name.Equals(nameof(Viewport))) - { - //if (SupressViewPortPropertyChange) return; - UpdateViewPort(); - return; - } - } - #region Overrides @@ -1410,8 +1432,6 @@ namespace UVtools.WPF.Controls public void LoadImage(string path) { Image = new Bitmap(path); - //ImageControl.Source = Image; - //ImageControl.InvalidateVisual(); } public override void Render(DrawingContext context) @@ -1732,7 +1752,7 @@ namespace UVtools.WPF.Controls /// <value>The height of the scaled image.</value> protected virtual double ScaledImageHeight => Image.Size.Height * ZoomFactor; - public double ZoomFactor => Zoom / 100.0; + public double ZoomFactor => _zoom / 100.0; protected override void OnPointerPressed(PointerPressedEventArgs e) { diff --git a/UVtools.WPF/MainWindow.LayerPreview.cs b/UVtools.WPF/MainWindow.LayerPreview.cs index 80a3fcd..bc55b2f 100644 --- a/UVtools.WPF/MainWindow.LayerPreview.cs +++ b/UVtools.WPF/MainWindow.LayerPreview.cs @@ -44,7 +44,7 @@ namespace UVtools.WPF private Canvas _issuesSliderCanvas; - private Timer _layerNavigationTooltipTimer = new Timer(1) { AutoReset = false }; + private Timer _layerNavigationTooltipTimer = new Timer(0.1) { AutoReset = false }; private uint _actualLayer; private bool _showLayerImageRotated; @@ -81,6 +81,7 @@ namespace UVtools.WPF _showLayerOutlineLayerBoundary = Settings.LayerPreview.LayerBoundsOutline; _showLayerOutlineHollowAreas = Settings.LayerPreview.HollowOutline; + LayerImageBox.ZoomLevels = new AdvancedImageBox.ZoomLevelCollection(AppSettings.ZoomLevels); LayerImageBox.PropertyChanged += (sender, e) => { if (e.PropertyName == nameof(LayerImageBox.Zoom)) diff --git a/UVtools.WPF/MainWindow.axaml b/UVtools.WPF/MainWindow.axaml index 3e56e71..aa31be5 100644 --- a/UVtools.WPF/MainWindow.axaml +++ b/UVtools.WPF/MainWindow.axaml @@ -183,6 +183,15 @@ </MenuItem> </MenuItem> + + <MenuItem + Background="LimeGreen" + IsVisible="{Binding VersionChecker.HaveNewVersion}" + Header="{Binding VersionChecker.VersionAnnouncementText}" + Command="{Binding MenuNewVersionClicked}" + > + </MenuItem> + </Menu> <Border Padding="5" DockPanel.Dock="Bottom" Background="WhiteSmoke" IsVisible="{Binding IsFileLoaded}"> diff --git a/UVtools.WPF/MainWindow.axaml.cs b/UVtools.WPF/MainWindow.axaml.cs index 1863f08..add99a9 100644 --- a/UVtools.WPF/MainWindow.axaml.cs +++ b/UVtools.WPF/MainWindow.axaml.cs @@ -11,6 +11,7 @@ using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; +using System.Net; using System.Threading.Tasks; using Avalonia; using Avalonia.Controls; @@ -19,6 +20,7 @@ using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.Markup.Xaml; using Avalonia.Media; +using Avalonia.Platform; using Avalonia.Threading; using Emgu.CV; using Emgu.CV.CvEnum; @@ -31,6 +33,7 @@ using UVtools.Core.Operations; using UVtools.WPF.Controls; using UVtools.WPF.Controls.Tools; using UVtools.WPF.Extensions; +using UVtools.WPF.Structures; using UVtools.WPF.Windows; using Bitmap = Avalonia.Media.Imaging.Bitmap; using Ellipse = Avalonia.Controls.Shapes.Ellipse; @@ -42,6 +45,8 @@ namespace UVtools.WPF public partial class MainWindow : WindowEx { #region Redirects + + public AppVersionChecker VersionChecker => App.VersionChecker; public UserSettings Settings => UserSettings.Instance; public FileFormat SlicerFile => App.SlicerFile; #endregion @@ -360,7 +365,7 @@ namespace UVtools.WPF return; } };*/ - PropertyChanged += OnPropertyChanged; + //PropertyChanged += OnPropertyChanged; var clientSizeObs = this.GetObservable(ClientSizeProperty); clientSizeObs.Subscribe(size => UpdateLayerTrackerHighlightIssues()); var windowStateObs = this.GetObservable(WindowStateProperty); @@ -369,7 +374,9 @@ namespace UVtools.WPF UpdateTitle(); - if (Settings.General.StartMaximized) + if (Settings.General.StartMaximized + || ClientSize.Width > Screens.Primary.Bounds.Width + || ClientSize.Height > Screens.Primary.Bounds.Height) { WindowState = WindowState.Maximized; } @@ -383,6 +390,12 @@ namespace UVtools.WPF AddLog($"{About.Software} start"); + + if (Settings.General.CheckForUpdatesOnStartup) + { + Task.Factory.StartNew(VersionChecker.Check); + } + ProcessFiles(Program.Args); } @@ -639,6 +652,8 @@ namespace UVtools.WPF await new PrusaSlicerManager().ShowDialog(this); } + public void MenuNewVersionClicked() => App.OpenBrowser(VersionChecker.Url); + #endregion #region Methods diff --git a/UVtools.WPF/Structures/AppVersionChecker.cs b/UVtools.WPF/Structures/AppVersionChecker.cs new file mode 100644 index 0000000..93d6bf1 --- /dev/null +++ b/UVtools.WPF/Structures/AppVersionChecker.cs @@ -0,0 +1,69 @@ +/* + * 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 System; +using System.Diagnostics; +using System.Net; +using Avalonia.Threading; +using UVtools.Core; +using UVtools.Core.Objects; + +namespace UVtools.WPF.Structures +{ + public class AppVersionChecker : BindableBase + { + private string _version; + private string _url; + + public string Version + { + get => _version; + set + { + if(!RaiseAndSetIfChanged(ref _version, value)) return; + RaisePropertyChanged(nameof(VersionAnnouncementText)); + RaisePropertyChanged(nameof(HaveNewVersion)); + } + } + + public string VersionAnnouncementText => $"New version {_version} is available!"; + + public string Url => $"{About.Website}/releases/tag/{_version}"; + + public bool HaveNewVersion => !string.IsNullOrEmpty(Version); + + public bool Check() + { + try + { + using (WebClient client = new WebClient()) + { + string htmlCode = client.DownloadString($"{About.Website}/releases"); + const string searchFor = "/releases/tag/"; + var startIndex = htmlCode.IndexOf(searchFor, StringComparison.InvariantCultureIgnoreCase) + + searchFor.Length; + var endIndex = htmlCode.IndexOf("\"", startIndex, StringComparison.InvariantCultureIgnoreCase); + var version = htmlCode.Substring(startIndex, endIndex - startIndex); + if (string.Compare(version, $"v{AppSettings.AssemblyVersion}", StringComparison.OrdinalIgnoreCase) > 0) + { + Dispatcher.UIThread.InvokeAsync(() => + { + Version = version;; + }); + return true; + } + } + } + catch (Exception e) + { + Debug.WriteLine(e.ToString()); + } + + return false; + } + } +} diff --git a/UVtools.WPF/Windows/ToolWindow.axaml.cs b/UVtools.WPF/Windows/ToolWindow.axaml.cs index 8e378c4..132520f 100644 --- a/UVtools.WPF/Windows/ToolWindow.axaml.cs +++ b/UVtools.WPF/Windows/ToolWindow.axaml.cs @@ -1,9 +1,8 @@ using System; using System.Drawing; -using System.Timers; -using Avalonia; using Avalonia.Controls; using Avalonia.Markup.Xaml; +using Avalonia.Threading; using MessageBox.Avalonia.Enums; using UVtools.Core; using UVtools.WPF.Controls; @@ -301,19 +300,14 @@ namespace UVtools.WPF.Windows RaisePropertyChanged(nameof(IsROIVisible)); // Ensure the description don't stretch window - var timer = new Timer(10) + DispatcherTimer.Run(() => { - AutoReset = true - }; - timer.Elapsed += (sender, args) => - { - if (Bounds.Width == 0) return; - DescriptionMaxWidth = Math.Max(Bounds.Width, ToolControl?.Bounds.Width ?? 0)-40; + if (Bounds.Width == 0) return true; + DescriptionMaxWidth = Math.Max(Bounds.Width, ToolControl?.Bounds.Width ?? 0) - 40; Description = toolControl.BaseOperation.Description; - timer.Stop(); - timer.Dispose(); - }; - timer.Start(); + return false; + }, TimeSpan.FromMilliseconds(1)); + toolControl.Callback(Callbacks.Init); toolControl.DataContext = toolControl; |