WPF progress

This commit is contained in:
Tiago Conceição
2020-10-13 23:02:40 +01:00
parent 1a0229a654
commit 4230f8753d
10 changed files with 225 additions and 109 deletions
+3 -3
View File
@@ -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'">
+2 -2
View File
@@ -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")]
+3
View File
@@ -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);
+9 -4
View File
@@ -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
+101 -81
View File
@@ -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,6 +727,7 @@ 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
@@ -738,9 +735,9 @@ namespace UVtools.WPF.Controls
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)
{
+2 -1
View File
@@ -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))
+9
View File
@@ -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}">
+17 -2
View File
@@ -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
@@ -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;
}
}
}
+7 -13
View File
@@ -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;