diff --git a/UVtools.Core/FileFormats/ChituboxZipFile.cs b/UVtools.Core/FileFormats/ChituboxZipFile.cs
index 014a72e..7760b1a 100644
--- a/UVtools.Core/FileFormats/ChituboxZipFile.cs
+++ b/UVtools.Core/FileFormats/ChituboxZipFile.cs
@@ -9,6 +9,7 @@
using System;
using System.ComponentModel;
using System.Drawing;
+using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
@@ -386,11 +387,17 @@ namespace UVtools.Core.FileFormats
{
HeaderSettings.LightPWM = byte.Parse(pwm.Groups[1].Value);
}
+ var asd = exposureTime.NextMatch();
+ var asd1 = currPos.Groups[1].Value;
+ var asd2 = exposureTime.NextMatch().Groups[1].Value;
+
+ var posZ = float.Parse(asd1, CultureInfo.InvariantCulture);
+ var exp = float.Parse(asd2, CultureInfo.InvariantCulture) / 1000f;
LayerManager[layerIndex] = new Layer(layerIndex, entry.Open(), entry.Name)
{
- PositionZ = float.Parse(currPos.Groups[1].Value),
- ExposureTime = float.Parse(exposureTime.NextMatch().Groups[1].Value) / 1000f
+ PositionZ = posZ,
+ ExposureTime = exp
};
progress++;
}
diff --git a/UVtools.Core/Objects/BindableBase.cs b/UVtools.Core/Objects/BindableBase.cs
index 946b5ca..f2ce458 100644
--- a/UVtools.Core/Objects/BindableBase.cs
+++ b/UVtools.Core/Objects/BindableBase.cs
@@ -6,6 +6,7 @@
* of this license document, but changing it is not allowed.
*/
+using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
@@ -19,7 +20,14 @@ namespace UVtools.Core.Objects
///
/// Multicast event for property change notifications.
///
- public event PropertyChangedEventHandler PropertyChanged;
+ private PropertyChangedEventHandler _propertyChanged;
+ private List events = new List();
+
+ public event PropertyChangedEventHandler PropertyChanged
+ {
+ add { _propertyChanged += value; events.Add("added"); }
+ remove { _propertyChanged -= value; events.Add("removed"); }
+ }
///
/// Checks if a property already matches a desired value. Sets the property and
@@ -37,7 +45,7 @@ namespace UVtools.Core.Objects
/// True if the value was changed, false if the existing value matched the
/// desired value.
///
- protected bool SetProperty(ref T storage, T value, [CallerMemberName] string propertyName = null)
+ /*protected bool SetProperty(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (Equals(storage, value))
{
@@ -45,14 +53,21 @@ namespace UVtools.Core.Objects
}
storage = value;
- OnPropertyChanged(propertyName);
+ RaisePropertyChanged(propertyName);
+ return true;
+ }*/
+
+ protected bool RaiseAndSetIfChanged(ref T field, T value, [CallerMemberName] string propertyName = null)
+ {
+ if (EqualityComparer.Default.Equals(field, value)) return false;
+ field = value;
+ RaisePropertyChanged(propertyName);
return true;
}
- protected bool SetProperty([CallerMemberName] string propertyName = null)
+
+ protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
- OnPropertyChanged(propertyName);
- return true;
}
///
@@ -63,10 +78,11 @@ namespace UVtools.Core.Objects
/// value is optional and can be provided automatically when invoked from compilers
/// that support .
///
- protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
- var eventHandler = PropertyChanged;
- eventHandler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ var e = new PropertyChangedEventArgs(propertyName);
+ OnPropertyChanged(e);
+ _propertyChanged?.Invoke(this, e);
}
}
}
diff --git a/UVtools.Core/Operations/OperationChangeResolution.cs b/UVtools.Core/Operations/OperationChangeResolution.cs
index 5f6b0e9..9fa8eb1 100644
--- a/UVtools.Core/Operations/OperationChangeResolution.cs
+++ b/UVtools.Core/Operations/OperationChangeResolution.cs
@@ -91,13 +91,13 @@ namespace UVtools.Core.Operations
public uint NewResolutionX
{
get => _newResolutionX;
- set => SetProperty(ref _newResolutionX, value);
+ set => RaiseAndSetIfChanged(ref _newResolutionX, value);
}
public uint NewResolutionY
{
get => _newResolutionY;
- set => SetProperty(ref _newResolutionY, value);
+ set => RaiseAndSetIfChanged(ref _newResolutionY, value);
}
public Rectangle VolumeBonds { get; }
diff --git a/UVtools.Core/Operations/OperationProgress.cs b/UVtools.Core/Operations/OperationProgress.cs
index 3ffce1f..5400f16 100644
--- a/UVtools.Core/Operations/OperationProgress.cs
+++ b/UVtools.Core/Operations/OperationProgress.cs
@@ -70,7 +70,7 @@ namespace UVtools.Core.Operations
if (!_canCancel) return _canCancel;
return !Token.IsCancellationRequested && Token.CanBeCanceled && _canCancel;
}
- set => SetProperty(ref _canCancel, value);
+ set => RaiseAndSetIfChanged(ref _canCancel, value);
}
///
@@ -79,7 +79,7 @@ namespace UVtools.Core.Operations
public string Title
{
get => _title;
- set => SetProperty(ref _title, value);
+ set => RaiseAndSetIfChanged(ref _title, value);
}
public string ElapsedTimeStr => $"{StopWatch.Elapsed.Minutes}m {StopWatch.Elapsed.Seconds}s {StopWatch.Elapsed.Milliseconds}ms";
@@ -90,7 +90,7 @@ namespace UVtools.Core.Operations
public string ItemName
{
get => _itemName;
- set => SetProperty(ref _itemName, value);
+ set => RaiseAndSetIfChanged(ref _itemName, value);
}
///
@@ -102,9 +102,9 @@ namespace UVtools.Core.Operations
set
{
//_processedItems = value;
- SetProperty(ref _processedItems, value);
- OnPropertyChanged(nameof(ProgressPercent));
- OnPropertyChanged(nameof(Description));
+ RaiseAndSetIfChanged(ref _processedItems, value);
+ RaisePropertyChanged(nameof(ProgressPercent));
+ RaisePropertyChanged(nameof(Description));
}
}
@@ -116,10 +116,10 @@ namespace UVtools.Core.Operations
get => _itemCount;
set
{
- SetProperty(ref _itemCount, value);
- OnPropertyChanged(nameof(IsIndeterminate));
- OnPropertyChanged(nameof(ProgressPercent));
- OnPropertyChanged(nameof(Description));
+ RaiseAndSetIfChanged(ref _itemCount, value);
+ RaisePropertyChanged(nameof(IsIndeterminate));
+ RaisePropertyChanged(nameof(ProgressPercent));
+ RaisePropertyChanged(nameof(Description));
}
}
@@ -174,8 +174,8 @@ namespace UVtools.Core.Operations
public void TriggerRefresh()
{
- OnPropertyChanged(nameof(ElapsedTimeStr));
- OnPropertyChanged(nameof(CanCancel));
+ RaisePropertyChanged(nameof(ElapsedTimeStr));
+ RaisePropertyChanged(nameof(CanCancel));
//OnPropertyChanged(nameof(ProgressPercent));
//OnPropertyChanged(nameof(Description));
}
diff --git a/UVtools.Core/Operations/OperationResize.cs b/UVtools.Core/Operations/OperationResize.cs
index b921a8d..2225067 100644
--- a/UVtools.Core/Operations/OperationResize.cs
+++ b/UVtools.Core/Operations/OperationResize.cs
@@ -51,7 +51,7 @@ namespace UVtools.Core.Operations
get => _x;
set
{
- SetProperty(ref _x, value);
+ RaiseAndSetIfChanged(ref _x, value);
if (_constrainXy)
Y = value;
}
@@ -60,7 +60,7 @@ namespace UVtools.Core.Operations
public decimal Y
{
get => _y;
- set => SetProperty(ref _y, value);
+ set => RaiseAndSetIfChanged(ref _y, value);
}
public bool ConstrainXY
@@ -68,7 +68,7 @@ namespace UVtools.Core.Operations
get => _constrainXy;
set
{
- if (!SetProperty(ref _constrainXy, value)) return;
+ if (!RaiseAndSetIfChanged(ref _constrainXy, value)) return;
if (_constrainXy)
{
Y = _x;
@@ -79,7 +79,7 @@ namespace UVtools.Core.Operations
public bool IsFade
{
get => _isFade;
- set => SetProperty(ref _isFade, value);
+ set => RaiseAndSetIfChanged(ref _isFade, value);
}
diff --git a/UVtools.Core/Operations/OperationRotate.cs b/UVtools.Core/Operations/OperationRotate.cs
index c52bacf..e95991f 100644
--- a/UVtools.Core/Operations/OperationRotate.cs
+++ b/UVtools.Core/Operations/OperationRotate.cs
@@ -28,7 +28,7 @@ namespace UVtools.Core.Operations
public decimal AngleDegrees
{
get => _angleDegrees;
- set => SetProperty(ref _angleDegrees, value);
+ set => RaiseAndSetIfChanged(ref _angleDegrees, value);
}
}
}
diff --git a/UVtools.Core/Operations/OperationThreshold.cs b/UVtools.Core/Operations/OperationThreshold.cs
index 183bc00..8854ac7 100644
--- a/UVtools.Core/Operations/OperationThreshold.cs
+++ b/UVtools.Core/Operations/OperationThreshold.cs
@@ -35,19 +35,19 @@ namespace UVtools.Core.Operations
public byte Threshold
{
get => _threshold;
- set => SetProperty(ref _threshold, value);
+ set => RaiseAndSetIfChanged(ref _threshold, value);
}
public byte Maximum
{
get => _maximum;
- set => SetProperty(ref _maximum, value);
+ set => RaiseAndSetIfChanged(ref _maximum, value);
}
public ThresholdType Type
{
get => _type;
- set => SetProperty(ref _type, value);
+ set => RaiseAndSetIfChanged(ref _type, value);
}
public static Array ThresholdTypes => Enum.GetValues(typeof(ThresholdType));
diff --git a/UVtools.GUI/Program.cs b/UVtools.GUI/Program.cs
index ed723a1..cf00d74 100644
--- a/UVtools.GUI/Program.cs
+++ b/UVtools.GUI/Program.cs
@@ -79,7 +79,8 @@ namespace UVtools.GUI
static void Main(string[] args)
{
Args = args;
- Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
+ CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
+ CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.InvariantCulture;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
diff --git a/UVtools.WPF/App.axaml.cs b/UVtools.WPF/App.axaml.cs
index 4c01abb..7faf6d8 100644
--- a/UVtools.WPF/App.axaml.cs
+++ b/UVtools.WPF/App.axaml.cs
@@ -39,7 +39,9 @@ namespace UVtools.WPF
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
- Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
+ CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
+ CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.InvariantCulture;
+
UserSettings.Load();
UserSettings.SetVersion();
diff --git a/UVtools.WPF/Controls/AdvancedImageBox.cs b/UVtools.WPF/Controls/AdvancedImageBox.cs
index 5b785da..80cb86f 100644
--- a/UVtools.WPF/Controls/AdvancedImageBox.cs
+++ b/UVtools.WPF/Controls/AdvancedImageBox.cs
@@ -30,40 +30,25 @@ namespace UVtools.WPF.Controls
///
/// Multicast event for property change notifications.
///
- public event PropertyChangedEventHandler ImageBoxPropertyChanged;
+ private PropertyChangedEventHandler _propertyChanged;
+ private List events = new List();
- ///
- /// Checks if a property already matches a desired value. Sets the property and
- /// notifies listeners only when necessary.
- ///
- /// Type of the property.
- /// Reference to a property with both getter and setter.
- /// Desired value for the property.
- ///
- /// Name of the property used to notify listeners. This
- /// value is optional and can be provided automatically when invoked from compilers that
- /// support CallerMemberName.
- ///
- ///
- /// True if the value was changed, false if the existing value matched the
- /// desired value.
- ///
- protected bool SetProperty(ref T storage, T value, [CallerMemberName] string propertyName = null)
+ public event PropertyChangedEventHandler PropertyChanged
{
- if (Equals(storage, value))
- {
- return false;
- }
-
- storage = value;
- OnPropertyChanged(propertyName);
+ add { _propertyChanged += value; events.Add("added"); }
+ remove { _propertyChanged -= value; events.Add("removed"); }
+ }
+ protected bool RaiseAndSetIfChanged(ref T field, T value, [CallerMemberName] string propertyName = null)
+ {
+ if (EqualityComparer.Default.Equals(field, value)) return false;
+ field = value;
+ RaisePropertyChanged(propertyName);
return true;
}
- protected bool SetProperty([CallerMemberName] string propertyName = null)
+
+ protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
- OnPropertyChanged(propertyName);
- return true;
}
///
@@ -74,10 +59,11 @@ namespace UVtools.WPF.Controls
/// value is optional and can be provided automatically when invoked from compilers
/// that support .
///
- protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
- var eventHandler = ImageBoxPropertyChanged;
- eventHandler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ var e = new PropertyChangedEventArgs(propertyName);
+ OnPropertyChanged(e);
+ _propertyChanged?.Invoke(this, e);
}
#endregion
@@ -443,7 +429,7 @@ namespace UVtools.WPF.Controls
public byte GridCellSize
{
get => _gridCellSize;
- set => SetProperty(ref _gridCellSize, value);
+ set => RaiseAndSetIfChanged(ref _gridCellSize, value);
}
///
@@ -452,7 +438,7 @@ namespace UVtools.WPF.Controls
public ISolidColorBrush GridColor
{
get => _gridColor;
- set => SetProperty(ref _gridColor, value);
+ set => RaiseAndSetIfChanged(ref _gridColor, value);
}
///
@@ -461,7 +447,7 @@ namespace UVtools.WPF.Controls
public ISolidColorBrush GridColorAlternate
{
get => _gridColorAlternate;
- set => SetProperty(ref _gridColorAlternate, value);
+ set => RaiseAndSetIfChanged(ref _gridColorAlternate, value);
}
///
@@ -472,7 +458,7 @@ namespace UVtools.WPF.Controls
get => _image;
set
{
- if (!SetProperty(ref _image, value)) return;
+ if (!RaiseAndSetIfChanged(ref _image, value)) return;
if (_image is null)
{
SizedContainer.Width = 0;
@@ -513,7 +499,7 @@ namespace UVtools.WPF.Controls
public bool ShowGrid
{
get => _showGrid;
- set => SetProperty(ref _showGrid, value);
+ set => RaiseAndSetIfChanged(ref _showGrid, value);
}
public bool IsPanning
@@ -521,7 +507,7 @@ namespace UVtools.WPF.Controls
get => _isPanning;
protected set
{
- if (!SetProperty(ref _isPanning, value)) return;
+ if (!RaiseAndSetIfChanged(ref _isPanning, value)) return;
_startScrollPosition = Offset;
if (value)
@@ -549,44 +535,44 @@ namespace UVtools.WPF.Controls
public bool AutoPan
{
get => _autoPan;
- set => SetProperty(ref _autoPan, value);
+ set => RaiseAndSetIfChanged(ref _autoPan, value);
}
public PanMouseButtons PanWithMouseButtons
{
get => _panWithMouseButtons;
- set => SetProperty(ref _panWithMouseButtons, value);
+ set => RaiseAndSetIfChanged(ref _panWithMouseButtons, value);
}
public bool PanWithArrows
{
get => _panWithArrows;
- set => SetProperty(ref _panWithArrows, value);
+ set => RaiseAndSetIfChanged(ref _panWithArrows, value);
}
public bool InvertMouse
{
get => _invertMouse;
- set => SetProperty(ref _invertMouse, value);
+ set => RaiseAndSetIfChanged(ref _invertMouse, value);
}
public bool AutoCenter
{
get => _autoCenter;
- set => SetProperty(ref _autoCenter, value);
+ set => RaiseAndSetIfChanged(ref _autoCenter, value);
}
public SizeModes SizeMode
{
get => _sizeMode;
- set => SetProperty(ref _sizeMode, value);
+ set => RaiseAndSetIfChanged(ref _sizeMode, value);
}
private bool _allowZoom = true;
public virtual bool AllowZoom
{
get => _allowZoom;
- set => SetProperty(ref _allowZoom, value);
+ set => RaiseAndSetIfChanged(ref _allowZoom, value);
}
ZoomLevelCollection _zoomLevels = ZoomLevelCollection.Default;
@@ -597,7 +583,7 @@ namespace UVtools.WPF.Controls
public virtual ZoomLevelCollection ZoomLevels
{
get => _zoomLevels;
- set => SetProperty(ref _zoomLevels, value);
+ set => RaiseAndSetIfChanged(ref _zoomLevels, value);
}
private int _zoom = 100;
@@ -621,7 +607,7 @@ namespace UVtools.WPF.Controls
public virtual ISolidColorBrush PixelGridColor
{
get => _pixelGridColor;
- set => SetProperty(ref _pixelGridColor, value);
+ set => RaiseAndSetIfChanged(ref _pixelGridColor, value);
}
private int _pixelGridThreshold = 5;
@@ -633,13 +619,13 @@ namespace UVtools.WPF.Controls
public virtual int PixelGridThreshold
{
get => _pixelGridThreshold;
- set => SetProperty(ref _pixelGridThreshold, value);
+ set => RaiseAndSetIfChanged(ref _pixelGridThreshold, value);
}
public Rect SelectionRegion
{
get => _selectionRegion;
- set => SetProperty(ref _selectionRegion, value);
+ set => RaiseAndSetIfChanged(ref _selectionRegion, value);
}
@@ -687,7 +673,7 @@ namespace UVtools.WPF.Controls
//Container.PointerPressed += ScrollViewerOnPointerPressed;
//Container.PointerReleased += ScrollViewerOnPointerReleased;
- PropertyChanged += EventOnPropertyChanged;
+ base.PropertyChanged += EventOnPropertyChanged;
}
private void FillContainerOnPointerWheelChanged(object? sender, PointerWheelEventArgs e)
@@ -935,7 +921,7 @@ namespace UVtools.WPF.Controls
InvalidateArrange();
}
- OnPropertyChanged(nameof(Zoom));
+ RaisePropertyChanged(nameof(Zoom));
//this.OnZoomChanged(EventArgs.Empty);
//this.OnZoomed(new ImageBoxZoomEventArgs(actions, source, previousZoom, this.Zoom));
}
diff --git a/UVtools.WPF/Controls/Tools/ToolChangeResolutionControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolChangeResolutionControl.axaml.cs
index 97260e8..6254a2b 100644
--- a/UVtools.WPF/Controls/Tools/ToolChangeResolutionControl.axaml.cs
+++ b/UVtools.WPF/Controls/Tools/ToolChangeResolutionControl.axaml.cs
@@ -14,7 +14,7 @@ namespace UVtools.WPF.Controls.Tools
get => _selectedPresetItem;
set
{
- SetProperty(ref _selectedPresetItem, value);
+ RaiseAndSetIfChanged(ref _selectedPresetItem, value);
if (_selectedPresetItem is null || _selectedPresetItem.IsEmpty) return;
Operation.NewResolutionX = _selectedPresetItem.ResolutionX;
Operation.NewResolutionY = _selectedPresetItem.ResolutionY;
diff --git a/UVtools.WPF/Controls/Tools/ToolControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolControl.axaml.cs
index 799c071..4a3cfa8 100644
--- a/UVtools.WPF/Controls/Tools/ToolControl.axaml.cs
+++ b/UVtools.WPF/Controls/Tools/ToolControl.axaml.cs
@@ -1,4 +1,5 @@
-using System.ComponentModel;
+using System.Collections.Generic;
+using System.ComponentModel;
using System.Runtime.CompilerServices;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
@@ -15,36 +16,27 @@ namespace UVtools.WPF.Controls.Tools
///
/// Multicast event for property change notifications.
///
- public event PropertyChangedEventHandler PropertyChanged;
+ private PropertyChangedEventHandler _propertyChanged;
+ private List events = new List();
- ///
- /// Checks if a property already matches a desired value. Sets the property and
- /// notifies listeners only when necessary.
- ///
- /// Type of the property.
- /// Reference to a property with both getter and setter.
- /// Desired value for the property.
- ///
- /// Name of the property used to notify listeners. This
- /// value is optional and can be provided automatically when invoked from compilers that
- /// support CallerMemberName.
- ///
- ///
- /// True if the value was changed, false if the existing value matched the
- /// desired value.
- ///
- protected bool SetProperty(ref T storage, T value, [CallerMemberName] string propertyName = null)
+ public event PropertyChangedEventHandler PropertyChanged
{
- if (Equals(storage, value))
- {
- return false;
- }
+ add { _propertyChanged += value; events.Add("added"); }
+ remove { _propertyChanged -= value; events.Add("removed"); }
+ }
- storage = value;
- OnPropertyChanged(propertyName);
+ protected bool RaiseAndSetIfChanged(ref T field, T value, [CallerMemberName] string propertyName = null)
+ {
+ if (EqualityComparer.Default.Equals(field, value)) return false;
+ field = value;
+ RaisePropertyChanged(propertyName);
return true;
}
+ protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
+ {
+ }
+
///
/// Notifies listeners that a property value has changed.
///
@@ -53,10 +45,11 @@ namespace UVtools.WPF.Controls.Tools
/// value is optional and can be provided automatically when invoked from compilers
/// that support .
///
- protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
- var eventHandler = PropertyChanged;
- eventHandler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ var e = new PropertyChangedEventArgs(propertyName);
+ OnPropertyChanged(e);
+ _propertyChanged?.Invoke(this, e);
}
#endregion
diff --git a/UVtools.WPF/Controls/Tools/ToolThresholdControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolThresholdControl.axaml.cs
index 6776c84..7d5b9cb 100644
--- a/UVtools.WPF/Controls/Tools/ToolThresholdControl.axaml.cs
+++ b/UVtools.WPF/Controls/Tools/ToolThresholdControl.axaml.cs
@@ -22,19 +22,19 @@ namespace UVtools.WPF.Controls.Tools
public bool IsThresholdEnabled
{
get => _isThresholdEnabled;
- set => SetProperty(ref _isThresholdEnabled, value);
+ set => RaiseAndSetIfChanged(ref _isThresholdEnabled, value);
}
public bool IsMaximumEnabled
{
get => _isMaximumEnabled;
- set => SetProperty(ref _isMaximumEnabled, value);
+ set => RaiseAndSetIfChanged(ref _isMaximumEnabled, value);
}
public bool IsTypeEnabled
{
get => _isTypeEnabled;
- set => SetProperty(ref _isTypeEnabled, value);
+ set => RaiseAndSetIfChanged(ref _isTypeEnabled, value);
}
public int SelectedPresetIndex
@@ -42,7 +42,7 @@ namespace UVtools.WPF.Controls.Tools
get => _selectedPresetIndex;
set
{
- if (!SetProperty(ref _selectedPresetIndex, value)) return;
+ if (!RaiseAndSetIfChanged(ref _selectedPresetIndex, value)) return;
switch (_selectedPresetIndex)
{
diff --git a/UVtools.WPF/Controls/WindowEx.cs b/UVtools.WPF/Controls/WindowEx.cs
index 25b7ed8..f3b062d 100644
--- a/UVtools.WPF/Controls/WindowEx.cs
+++ b/UVtools.WPF/Controls/WindowEx.cs
@@ -6,6 +6,7 @@
* of this license document, but changing it is not allowed.
*/
+using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
@@ -19,36 +20,28 @@ namespace UVtools.WPF.Controls
///
/// Multicast event for property change notifications.
///
- public event PropertyChangedEventHandler PropertyChanged;
+ private PropertyChangedEventHandler _propertyChanged;
+ private List events = new List();
- ///
- /// Checks if a property already matches a desired value. Sets the property and
- /// notifies listeners only when necessary.
- ///
- /// Type of the property.
- /// Reference to a property with both getter and setter.
- /// Desired value for the property.
- ///
- /// Name of the property used to notify listeners. This
- /// value is optional and can be provided automatically when invoked from compilers that
- /// support CallerMemberName.
- ///
- ///
- /// True if the value was changed, false if the existing value matched the
- /// desired value.
- ///
- protected bool SetProperty(ref T storage, T value, [CallerMemberName] string propertyName = null)
+ public event PropertyChangedEventHandler PropertyChanged
{
- if (Equals(storage, value))
- {
- return false;
- }
+ add { _propertyChanged += value; events.Add("added"); }
+ remove { _propertyChanged -= value; events.Add("removed"); }
+ }
- storage = value;
- OnPropertyChanged(propertyName);
+ protected bool RaiseAndSetIfChanged(ref T field, T value, [CallerMemberName] string propertyName = null)
+ {
+ if (EqualityComparer.Default.Equals(field, value)) return false;
+ field = value;
+ RaisePropertyChanged(propertyName);
return true;
}
+
+ protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
+ {
+ }
+
///
/// Notifies listeners that a property value has changed.
///
@@ -57,10 +50,11 @@ namespace UVtools.WPF.Controls
/// value is optional and can be provided automatically when invoked from compilers
/// that support .
///
- protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
- var eventHandler = PropertyChanged;
- eventHandler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ var e = new PropertyChangedEventArgs(propertyName);
+ OnPropertyChanged(e);
+ _propertyChanged?.Invoke(this, e);
}
#endregion
diff --git a/UVtools.WPF/MainWindow.axaml.cs b/UVtools.WPF/MainWindow.axaml.cs
index af4f9b5..493c684 100644
--- a/UVtools.WPF/MainWindow.axaml.cs
+++ b/UVtools.WPF/MainWindow.axaml.cs
@@ -226,7 +226,7 @@ namespace UVtools.WPF
public ObservableCollection Issues
{
get => _issues;
- private set => SetProperty(ref _issues, value);
+ private set => RaiseAndSetIfChanged(ref _issues, value);
}
public ObservableCollection Drawings { get; } = new ObservableCollection();
@@ -268,7 +268,7 @@ namespace UVtools.WPF
get => _isGUIEnabled;
set
{
- if (!SetProperty(ref _isGUIEnabled, value)) return;
+ if (!RaiseAndSetIfChanged(ref _isGUIEnabled, value)) return;
if (!_isGUIEnabled)
{
ProgressWindow = new ProgressWindow();
@@ -301,32 +301,32 @@ namespace UVtools.WPF
public bool IsFileLoaded
{
get => !(SlicerFile is null);
- set => OnPropertyChanged();
+ set => RaisePropertyChanged();
}
public int TabSelectedIndex
{
get => _tabSelectedIndex;
- set => SetProperty(ref _tabSelectedIndex, value);
+ set => RaiseAndSetIfChanged(ref _tabSelectedIndex, value);
}
#endregion
public uint SavesCount
{
get => _savesCount;
- set => SetProperty(ref _savesCount, value);
+ set => RaiseAndSetIfChanged(ref _savesCount, value);
}
public bool CanSave
{
get => IsFileLoaded && _canSave;
- set => SetProperty(ref _canSave, value);
+ set => RaiseAndSetIfChanged(ref _canSave, value);
}
public MenuItem[] MenuFileConvertItems
{
get => _menuFileConvertItems;
- set => SetProperty(ref _menuFileConvertItems, value);
+ set => RaiseAndSetIfChanged(ref _menuFileConvertItems, value);
}
@@ -338,9 +338,9 @@ namespace UVtools.WPF
{
if (value == 0)
{
- SetProperty(ref _visibleThumbnailIndex, value);
- OnPropertyChanged(nameof(ThumbnailCanGoPrevious));
- OnPropertyChanged(nameof(ThumbnailCanGoNext));
+ RaiseAndSetIfChanged(ref _visibleThumbnailIndex, value);
+ RaisePropertyChanged(nameof(ThumbnailCanGoPrevious));
+ RaisePropertyChanged(nameof(ThumbnailCanGoNext));
VisibleThumbnailImage = null;
return;
}
@@ -349,11 +349,11 @@ namespace UVtools.WPF
var index = value-1;
if (index >= SlicerFile.CreatedThumbnailsCount) return;
if (SlicerFile.Thumbnails[index] is null) return;
- if (!SetProperty(ref _visibleThumbnailIndex, value)) return;
+ if (!RaiseAndSetIfChanged(ref _visibleThumbnailIndex, value)) return;
VisibleThumbnailImage = SlicerFile.Thumbnails[index].ToBitmap();
- OnPropertyChanged(nameof(ThumbnailCanGoPrevious));
- OnPropertyChanged(nameof(ThumbnailCanGoNext));
+ RaisePropertyChanged(nameof(ThumbnailCanGoPrevious));
+ RaisePropertyChanged(nameof(ThumbnailCanGoNext));
}
}
@@ -377,8 +377,8 @@ namespace UVtools.WPF
get => _visibleThumbnailImage;
set
{
- SetProperty(ref _visibleThumbnailImage, value);
- OnPropertyChanged(nameof(VisibleThumbnailResolution));
+ RaiseAndSetIfChanged(ref _visibleThumbnailImage, value);
+ RaisePropertyChanged(nameof(VisibleThumbnailResolution));
}
}
@@ -509,8 +509,8 @@ namespace UVtools.WPF
{
if (!HaveGCode) return;
SlicerFile.RebuildGCode();
- OnPropertyChanged(nameof(GCodeLines));
- OnPropertyChanged(nameof(GCodeStr));
+ RaisePropertyChanged(nameof(GCodeLines));
+ RaisePropertyChanged(nameof(GCodeStr));
}
public async void OnClickGCodeSaveFile()
@@ -790,10 +790,10 @@ namespace UVtools.WPF
get => _issueSelectedIndex;
set
{
- if (!SetProperty(ref _issueSelectedIndex, value)) return;
- OnPropertyChanged(nameof(IssueSelectedIndexStr));
- OnPropertyChanged(nameof(IssueCanGoPrevious));
- OnPropertyChanged(nameof(IssueCanGoNext));
+ if (!RaiseAndSetIfChanged(ref _issueSelectedIndex, value)) return;
+ RaisePropertyChanged(nameof(IssueSelectedIndexStr));
+ RaisePropertyChanged(nameof(IssueCanGoPrevious));
+ RaisePropertyChanged(nameof(IssueCanGoNext));
IssuesGridOnSelectionChanged();
}
}
@@ -905,9 +905,9 @@ namespace UVtools.WPF
if (resultIssues is null) return;
Issues.AddRange(resultIssues);
- OnPropertyChanged(nameof(IssueSelectedIndexStr));
- OnPropertyChanged(nameof(IssueCanGoPrevious));
- OnPropertyChanged(nameof(IssueCanGoNext));
+ RaisePropertyChanged(nameof(IssueSelectedIndexStr));
+ RaisePropertyChanged(nameof(IssueCanGoPrevious));
+ RaisePropertyChanged(nameof(IssueCanGoNext));
}
@@ -952,7 +952,7 @@ namespace UVtools.WPF
public bool IsVerbose
{
get => _isVerbose;
- set => SetProperty(ref _isVerbose, value);
+ set => RaiseAndSetIfChanged(ref _isVerbose, value);
}
public void AddLog(LogItem log)
@@ -980,7 +980,7 @@ namespace UVtools.WPF
get => _showLayerImageRotated;
set
{
- if (SetProperty(ref _showLayerImageRotated, value))
+ if (RaiseAndSetIfChanged(ref _showLayerImageRotated, value))
{
ShowLayer();
}
@@ -992,7 +992,7 @@ namespace UVtools.WPF
get => _showLayerImageDifference;
set
{
- if (SetProperty(ref _showLayerImageDifference, value))
+ if (RaiseAndSetIfChanged(ref _showLayerImageDifference, value))
{
ShowLayer();
}
@@ -1004,7 +1004,7 @@ namespace UVtools.WPF
get => _showLayerImageIssues;
set
{
- if (SetProperty(ref _showLayerImageIssues, value))
+ if (RaiseAndSetIfChanged(ref _showLayerImageIssues, value))
{
ShowLayer();
}
@@ -1016,7 +1016,7 @@ namespace UVtools.WPF
get => _showLayerImageCrosshairs;
set
{
- if (SetProperty(ref _showLayerImageCrosshairs, value))
+ if (RaiseAndSetIfChanged(ref _showLayerImageCrosshairs, value))
{
ShowLayer();
}
@@ -1028,7 +1028,7 @@ namespace UVtools.WPF
get => _showLayerOutlinePrintVolumeBoundary;
set
{
- if (SetProperty(ref _showLayerOutlinePrintVolumeBoundary, value))
+ if (RaiseAndSetIfChanged(ref _showLayerOutlinePrintVolumeBoundary, value))
{
ShowLayer();
}
@@ -1040,7 +1040,7 @@ namespace UVtools.WPF
get => _showLayerOutlineLayerBoundary;
set
{
- if (SetProperty(ref _showLayerOutlineLayerBoundary, value))
+ if (RaiseAndSetIfChanged(ref _showLayerOutlineLayerBoundary, value))
{
ShowLayer();
}
@@ -1052,7 +1052,7 @@ namespace UVtools.WPF
get => _showLayerOutlineHollowAreas;
set
{
- if (SetProperty(ref _showLayerOutlineHollowAreas, value))
+ if (RaiseAndSetIfChanged(ref _showLayerOutlineHollowAreas, value))
{
ShowLayer();
}
@@ -1064,7 +1064,7 @@ namespace UVtools.WPF
get => _showLayerOutlineEdgeDetection;
set
{
- if (SetProperty(ref _showLayerOutlineEdgeDetection, value))
+ if (RaiseAndSetIfChanged(ref _showLayerOutlineEdgeDetection, value))
{
ShowLayer();
}
@@ -1074,7 +1074,7 @@ namespace UVtools.WPF
public bool IsPixelEditorActive
{
get => _isPixelEditorActive;
- set => SetProperty(ref _isPixelEditorActive, value);
+ set => RaiseAndSetIfChanged(ref _isPixelEditorActive, value);
}
public string MinimumLayerString => SlicerFile is null ? "???" : $"{SlicerFile.LayerHeight}mm\n0";
@@ -1104,7 +1104,7 @@ namespace UVtools.WPF
public long ShowLayerRenderMs
{
get => _showLayerRenderMs;
- set => SetProperty(ref _showLayerRenderMs, value);
+ set => RaiseAndSetIfChanged(ref _showLayerRenderMs, value);
}
public PixelPicker LayerPixelPicker { get; } = new PixelPicker();
@@ -1118,7 +1118,7 @@ namespace UVtools.WPF
get => _actualLayer;
set
{
- if (!SetProperty(ref _actualLayer, value)) return;
+ if (!RaiseAndSetIfChanged(ref _actualLayer, value)) return;
ShowLayer();
InvalidateLayerNavigation();
}
@@ -1129,17 +1129,17 @@ namespace UVtools.WPF
_actualLayer = layerIndex;
ShowLayer();
InvalidateLayerNavigation();
- OnPropertyChanged(nameof(ActualLayer));
+ RaisePropertyChanged(nameof(ActualLayer));
}
public void InvalidateLayerNavigation()
{
- OnPropertyChanged(nameof(CanGoDown));
- OnPropertyChanged(nameof(CanGoUp));
- OnPropertyChanged(nameof(ActualLayerTooltip));
- OnPropertyChanged(nameof(LayerNavigationTooltipMargin));
- OnPropertyChanged(nameof(LayerPixelCountStr));
- OnPropertyChanged(nameof(LayerBoundsStr));
+ RaisePropertyChanged(nameof(CanGoDown));
+ RaisePropertyChanged(nameof(CanGoUp));
+ RaisePropertyChanged(nameof(ActualLayerTooltip));
+ RaisePropertyChanged(nameof(LayerNavigationTooltipMargin));
+ RaisePropertyChanged(nameof(LayerPixelCountStr));
+ RaisePropertyChanged(nameof(LayerBoundsStr));
}
public Thickness LayerNavigationTooltipMargin
diff --git a/UVtools.WPF/Structures/LogItem.cs b/UVtools.WPF/Structures/LogItem.cs
index 4dc6872..afd192b 100644
--- a/UVtools.WPF/Structures/LogItem.cs
+++ b/UVtools.WPF/Structures/LogItem.cs
@@ -21,25 +21,25 @@ namespace UVtools.WPF.Structures
public int Index
{
get => _index;
- set => SetProperty(ref _index, value);
+ set => RaiseAndSetIfChanged(ref _index, value);
}
public string StartTime
{
get => _startTime;
- set => SetProperty(ref _startTime, value);
+ set => RaiseAndSetIfChanged(ref _startTime, value);
}
public double ElapsedTime
{
get => _elapsedTime;
- set => SetProperty(ref _elapsedTime, Math.Round(value, 2));
+ set => RaiseAndSetIfChanged(ref _elapsedTime, Math.Round(value, 2));
}
public string Description
{
get => _description;
- set => SetProperty(ref _description, value);
+ set => RaiseAndSetIfChanged(ref _description, value);
}
public LogItem(int index, string description, double elapsedTime = 0)
diff --git a/UVtools.WPF/UserSettings.cs b/UVtools.WPF/UserSettings.cs
index a68a1c9..4ada331 100644
--- a/UVtools.WPF/UserSettings.cs
+++ b/UVtools.WPF/UserSettings.cs
@@ -13,7 +13,6 @@ using System.Xml.Serialization;
using Avalonia.Media;
using JetBrains.Annotations;
using ReactiveUI;
-using UVtools.WPF.Extensions;
using Color=UVtools.WPF.Structures.Color;
namespace UVtools.WPF
@@ -21,6 +20,10 @@ namespace UVtools.WPF
[Serializable]
public sealed class UserSettings : ReactiveObject
{
+ #region Constants
+ public const ushort SETTINGS_VERSION = 1;
+ #endregion
+
#region Sub classes
[Serializable]
public sealed class GeneralUserSettings : ReactiveObject
@@ -35,6 +38,7 @@ namespace UVtools.WPF
private bool _promptOverwriteFileSave = true;
private string _fileSaveNamePrefix;
private string _fileSaveNameSuffix = "_copy";
+ private int _maxDegreeOfParallelism;
public bool StartMaximized
{
@@ -96,6 +100,20 @@ namespace UVtools.WPF
set => this.RaiseAndSetIfChanged(ref _fileSaveNameSuffix, value);
}
+ ///
+ /// Gets or sets the maximum number of concurrent tasks enabled by a ParallelOptions instance.
+ ///
+ public int MaxDegreeOfParallelism
+ {
+ get => _maxDegreeOfParallelism;
+ set => this.RaiseAndSetIfChanged(ref _maxDegreeOfParallelism, value);
+ }
+
+ public GeneralUserSettings()
+ {
+ MaxDegreeOfParallelism = Environment.ProcessorCount;
+ }
+
public GeneralUserSettings Clone()
{
return MemberwiseClone() as GeneralUserSettings;
@@ -836,11 +854,12 @@ namespace UVtools.WPF
private IssuesUserSettings _issues;
private PixelEditorUserSettings _pixelEditor;
private LayerRepairUserSettings _layerRepair;
- private string _version;
+ private ushort _settingsVersion = SETTINGS_VERSION;
+ private string _appVersion;
private uint _savesCount;
private DateTime _modifiedDateTime;
-
+
public GeneralUserSettings General
{
get => _general ??= new GeneralUserSettings();
@@ -882,14 +901,20 @@ namespace UVtools.WPF
public uint ResetCount { get; set; }
*/
+ public ushort SettingsVersion
+ {
+ get => _settingsVersion;
+ set => this.RaiseAndSetIfChanged(ref _settingsVersion, value);
+ }
+
///
/// Gets or sets the last running version of UVtools with these settings
///
[NotNull]
- public string Version
+ public string AppVersion
{
- get => _version ??= AppSettings.Version.ToString();
- set => this.RaiseAndSetIfChanged(ref _version, value);
+ get => _appVersion ??= AppSettings.Version.ToString();
+ set => this.RaiseAndSetIfChanged(ref _appVersion, value);
}
///
@@ -939,10 +964,21 @@ namespace UVtools.WPF
}
var serializer = new XmlSerializer(typeof(UserSettings));
- using StreamReader myXmlReader = new StreamReader(FilePath);
+ using var myXmlReader = new StreamReader(FilePath);
try
{
_instance = (UserSettings)serializer.Deserialize(myXmlReader);
+ if (_instance.General.MaxDegreeOfParallelism <= 0)
+ _instance.General.MaxDegreeOfParallelism = Environment.ProcessorCount;
+
+ if (_instance.SettingsVersion < SETTINGS_VERSION)
+ {
+ // Upgrade
+
+ _instance.SettingsVersion = SETTINGS_VERSION;
+ }
+
+
}
catch (Exception e)
{
@@ -960,7 +996,7 @@ namespace UVtools.WPF
Instance.SavesCount++;
_instance.ModifiedDateTime = DateTime.Now;
var serializer = new XmlSerializer(_instance.GetType());
- using StreamWriter myXmlWriter = new StreamWriter(FilePath);
+ using var myXmlWriter = new StreamWriter(FilePath);
try
{
serializer.Serialize(myXmlWriter, _instance);
@@ -973,7 +1009,7 @@ namespace UVtools.WPF
public static void SetVersion()
{
- Instance.Version = AppSettings.Version.ToString();
+ Instance.AppVersion = AppSettings.Version.ToString();
}
public static object[] PackObjects =>
@@ -987,6 +1023,8 @@ namespace UVtools.WPF
};
#endregion
+ #region Methods
+
public UserSettings Clone()
{
var clone = MemberwiseClone() as UserSettings;
@@ -997,5 +1035,7 @@ namespace UVtools.WPF
clone.LayerRepair = clone.LayerRepair.Clone();
return clone;
}
+
+ #endregion
}
}
diff --git a/UVtools.WPF/Windows/ProgressWindow.axaml.cs b/UVtools.WPF/Windows/ProgressWindow.axaml.cs
index f492c79..2b6ae99 100644
--- a/UVtools.WPF/Windows/ProgressWindow.axaml.cs
+++ b/UVtools.WPF/Windows/ProgressWindow.axaml.cs
@@ -33,7 +33,7 @@ namespace UVtools.WPF.Windows
set
{
Progress.CanCancel = value;
- OnPropertyChanged();
+ RaisePropertyChanged();
}
}
@@ -69,7 +69,7 @@ namespace UVtools.WPF.Windows
{
if (!CanCancel) return;
DialogResult = DialogResults.Cancel;
- OnPropertyChanged(nameof(CanCancel));
+ RaisePropertyChanged(nameof(CanCancel));
Progress.TokenSource.Cancel();
}
diff --git a/UVtools.WPF/Windows/ToolWindow.axaml.cs b/UVtools.WPF/Windows/ToolWindow.axaml.cs
index f87d0a9..d88bc18 100644
--- a/UVtools.WPF/Windows/ToolWindow.axaml.cs
+++ b/UVtools.WPF/Windows/ToolWindow.axaml.cs
@@ -38,13 +38,13 @@ namespace UVtools.WPF.Windows
public string Description
{
get => _description;
- set => SetProperty(ref _description, value);
+ set => RaiseAndSetIfChanged(ref _description, value);
}
public double DescriptionMaxWidth
{
get => _descriptionMaxWidth;
- set => SetProperty(ref _descriptionMaxWidth, value);
+ set => RaiseAndSetIfChanged(ref _descriptionMaxWidth, value);
}
#endregion
@@ -54,7 +54,7 @@ namespace UVtools.WPF.Windows
public bool LayerRangeVisible
{
get => _layerRangeVisible;
- set => SetProperty(ref _layerRangeVisible, value);
+ set => RaiseAndSetIfChanged(ref _layerRangeVisible, value);
}
public uint LayerIndexStart
@@ -65,9 +65,9 @@ namespace UVtools.WPF.Windows
if (!(ToolControl?.BaseOperation is null))
ToolControl.BaseOperation.LayerIndexStart = value;
- if (!SetProperty(ref _layerIndexStart, value)) return;
- OnPropertyChanged(nameof(LayerStartMM));
- OnPropertyChanged(nameof(LayerRangeCountStr));
+ if (!RaiseAndSetIfChanged(ref _layerIndexStart, value)) return;
+ RaisePropertyChanged(nameof(LayerStartMM));
+ RaisePropertyChanged(nameof(LayerRangeCountStr));
}
}
@@ -81,9 +81,9 @@ namespace UVtools.WPF.Windows
if (!(ToolControl?.BaseOperation is null))
ToolControl.BaseOperation.LayerIndexEnd = value;
- if (!SetProperty(ref _layerIndexEnd, value)) return;
- OnPropertyChanged(nameof(LayerEndMM));
- OnPropertyChanged(nameof(LayerRangeCountStr));
+ if (!RaiseAndSetIfChanged(ref _layerIndexEnd, value)) return;
+ RaisePropertyChanged(nameof(LayerEndMM));
+ RaisePropertyChanged(nameof(LayerRangeCountStr));
}
}
@@ -140,19 +140,19 @@ namespace UVtools.WPF.Windows
public bool IsROIVisible
{
get => ToolControl?.BaseOperation.HaveROI ?? _isROIVisible;
- set => SetProperty(ref _isROIVisible, value);
+ set => RaiseAndSetIfChanged(ref _isROIVisible, value);
}
public Rect ROI
{
get => _roi;
- set => SetProperty(ref _roi, value);
+ set => RaiseAndSetIfChanged(ref _roi, value);
}
public bool ClearROIAfterOperation
{
get => _clearRoiAfterOperation;
- set => SetProperty(ref _clearRoiAfterOperation, value);
+ set => RaiseAndSetIfChanged(ref _clearRoiAfterOperation, value);
}
public async void ClearROI()
@@ -174,7 +174,7 @@ namespace UVtools.WPF.Windows
public IControl ContentControl
{
get => _contentControl;
- set => SetProperty(ref _contentControl, value);
+ set => RaiseAndSetIfChanged(ref _contentControl, value);
}
#endregion
@@ -184,13 +184,13 @@ namespace UVtools.WPF.Windows
public bool ButtonOkEnabled
{
get => _buttonOkEnabled;
- set => SetProperty(ref _buttonOkEnabled, value);
+ set => RaiseAndSetIfChanged(ref _buttonOkEnabled, value);
}
public string ButtonOkText
{
get => _buttonOkText;
- set => SetProperty(ref _buttonOkText, value);
+ set => RaiseAndSetIfChanged(ref _buttonOkText, value);
}
#endregion
@@ -219,7 +219,7 @@ namespace UVtools.WPF.Windows
ContentControl = toolControl;
ButtonOkText = toolControl.BaseOperation.ButtonOkText;
- OnPropertyChanged(nameof(IsContentVisible));
+ RaisePropertyChanged(nameof(IsContentVisible));
switch (toolControl.BaseOperation.LayerRangeSelection)
{