diff --git a/UVtools.Core/Enumerations.cs b/UVtools.Core/Enumerations.cs index 052e28a..45f7ad6 100644 --- a/UVtools.Core/Enumerations.cs +++ b/UVtools.Core/Enumerations.cs @@ -6,6 +6,17 @@ namespace UVtools.Core { public class Enumerations { + public enum LayerRangeSelection : byte + { + None, + All, + Current, + Bottom, + Normal, + First, + Last + } + public enum FlipDirection : byte { Horizontally, diff --git a/UVtools.Core/Operations/Operation.cs b/UVtools.Core/Operations/Operation.cs index 7bc3b79..648d540 100644 --- a/UVtools.Core/Operations/Operation.cs +++ b/UVtools.Core/Operations/Operation.cs @@ -21,11 +21,18 @@ namespace UVtools.Core.Operations /// public string Id => GetType().Name.Remove(0, ClassNameLength); + public virtual Enumerations.LayerRangeSelection LayerRangeSelection => Enumerations.LayerRangeSelection.All; + /// /// Gets if this operation should set layer range to the actual layer index on layer preview /// public virtual bool PassActualLayerIndex => false; + /// + /// Gets if this control can make use of ROI + /// + public virtual bool CanROI { get; set; } = true; + /// /// Gets if this operation supports cancellation /// diff --git a/UVtools.Core/Operations/OperationChangeResolution.cs b/UVtools.Core/Operations/OperationChangeResolution.cs index 9c7e161..b1af86f 100644 --- a/UVtools.Core/Operations/OperationChangeResolution.cs +++ b/UVtools.Core/Operations/OperationChangeResolution.cs @@ -41,6 +41,8 @@ namespace UVtools.Core.Operations #region Overrides + public override Enumerations.LayerRangeSelection LayerRangeSelection => Enumerations.LayerRangeSelection.None; + public override bool CanROI { get; set; } = false; public override string Title => "Change print resolution"; public override string Description => "Crops or resizes all layer images to fit an alternate print area\n\n" + diff --git a/UVtools.Core/Operations/OperationEditParameters.cs b/UVtools.Core/Operations/OperationEditParameters.cs index 7d55dca..77e08c0 100644 --- a/UVtools.Core/Operations/OperationEditParameters.cs +++ b/UVtools.Core/Operations/OperationEditParameters.cs @@ -12,6 +12,10 @@ namespace UVtools.Core.Operations { public class OperationEditParameters : Operation { + public override Enumerations.LayerRangeSelection LayerRangeSelection => Enumerations.LayerRangeSelection.None; + + public override bool CanROI { get; set; } = false; + public override string Title => "Edit print parameters"; public override string Description => diff --git a/UVtools.Core/Operations/OperationFlip.cs b/UVtools.Core/Operations/OperationFlip.cs index fe24205..fa1a508 100644 --- a/UVtools.Core/Operations/OperationFlip.cs +++ b/UVtools.Core/Operations/OperationFlip.cs @@ -6,6 +6,7 @@ * of this license document, but changing it is not allowed. */ +using System; using Emgu.CV.CvEnum; namespace UVtools.Core.Operations @@ -27,8 +28,8 @@ namespace UVtools.Core.Operations : $"Flipping {(MakeCopy == true ? "and blending " : "")}layers {LayerIndexStart} through {LayerIndexEnd} {FlipDirection}"; public override string ProgressAction => "Flipped layers"; - - public Enumerations.FlipDirection FlipDirection { get; set; } + + public Enumerations.FlipDirection FlipDirection { get; set; } = Enumerations.FlipDirection.Horizontally; public bool MakeCopy { get; set; } @@ -54,6 +55,8 @@ namespace UVtools.Core.Operations } } + public static Array FlipDirections => Enum.GetValues(typeof(Enumerations.FlipDirection)); + } diff --git a/UVtools.Core/Operations/OperationLayerClone.cs b/UVtools.Core/Operations/OperationLayerClone.cs index db078cb..1d6214e 100644 --- a/UVtools.Core/Operations/OperationLayerClone.cs +++ b/UVtools.Core/Operations/OperationLayerClone.cs @@ -14,6 +14,8 @@ namespace UVtools.Core.Operations { #region Overrides + public override Enumerations.LayerRangeSelection LayerRangeSelection => Enumerations.LayerRangeSelection.Current; + public override bool CanROI { get; set; } = false; public override bool PassActualLayerIndex => true; public override string Title => "Clone layer(s)"; diff --git a/UVtools.Core/Operations/OperationLayerImport.cs b/UVtools.Core/Operations/OperationLayerImport.cs index b7c8502..7756a6a 100644 --- a/UVtools.Core/Operations/OperationLayerImport.cs +++ b/UVtools.Core/Operations/OperationLayerImport.cs @@ -21,6 +21,9 @@ namespace UVtools.Core.Operations public sealed class OperationLayerImport : Operation { #region Overrides + + public override Enumerations.LayerRangeSelection LayerRangeSelection => Enumerations.LayerRangeSelection.None; + public override bool CanROI { get; set; } = false; public override string Title => "Import Layers"; public override string Description => diff --git a/UVtools.Core/Operations/OperationLayerReHeight.cs b/UVtools.Core/Operations/OperationLayerReHeight.cs index 60da0dd..a7f4f8b 100644 --- a/UVtools.Core/Operations/OperationLayerReHeight.cs +++ b/UVtools.Core/Operations/OperationLayerReHeight.cs @@ -18,6 +18,8 @@ namespace UVtools.Core.Operations { #region Overrides + public override Enumerations.LayerRangeSelection LayerRangeSelection => Enumerations.LayerRangeSelection.None; + public override bool CanROI { get; set; } = false; public override string Title => "Adjust layer height"; public override string Description => "Adjust the layer height of the model\n\n" + diff --git a/UVtools.Core/Operations/OperationLayerRemove.cs b/UVtools.Core/Operations/OperationLayerRemove.cs index cc71e62..b2fb9ca 100644 --- a/UVtools.Core/Operations/OperationLayerRemove.cs +++ b/UVtools.Core/Operations/OperationLayerRemove.cs @@ -13,6 +13,8 @@ namespace UVtools.Core.Operations { #region Overrides + public override Enumerations.LayerRangeSelection LayerRangeSelection => Enumerations.LayerRangeSelection.Current; + public override bool CanROI { get; set; } = false; public override bool PassActualLayerIndex => true; public override string Title => "Remove layers"; diff --git a/UVtools.Core/Operations/OperationRepairLayers.cs b/UVtools.Core/Operations/OperationRepairLayers.cs index 0b90180..4291576 100644 --- a/UVtools.Core/Operations/OperationRepairLayers.cs +++ b/UVtools.Core/Operations/OperationRepairLayers.cs @@ -14,6 +14,7 @@ namespace UVtools.Core.Operations { public class OperationRepairLayers : Operation { + public override bool CanROI { get; set; } = false; public override string Title => "Repair layers and issues"; public override string Description => null; diff --git a/UVtools.GUI/Forms/FrmToolWindow.Designer.cs b/UVtools.GUI/Forms/FrmToolWindow.Designer.cs index fe732e0..65cd767 100644 --- a/UVtools.GUI/Forms/FrmToolWindow.Designer.cs +++ b/UVtools.GUI/Forms/FrmToolWindow.Designer.cs @@ -41,6 +41,7 @@ namespace UVtools.GUI.Forms this.lbLayerRangeFromMM = new System.Windows.Forms.Label(); this.lbLayerRangeToMM = new System.Windows.Forms.Label(); this.nmLayerRangeEnd = new System.Windows.Forms.NumericUpDown(); + this.btnLayerRangeSelect = new UVtools.GUI.Controls.SplitButton(); this.cmLayerRange = new System.Windows.Forms.ContextMenuStrip(this.components); this.btnLayerRangeAllLayers = new System.Windows.Forms.ToolStripMenuItem(); this.btnLayerRangeCurrentLayer = new System.Windows.Forms.ToolStripMenuItem(); @@ -61,11 +62,10 @@ namespace UVtools.GUI.Forms this.btnOk = new System.Windows.Forms.Button(); this.pnROI = new System.Windows.Forms.Panel(); this.gbROI = new System.Windows.Forms.GroupBox(); + this.cbClearRoiAfterOperation = new System.Windows.Forms.CheckBox(); this.lbRoi = new System.Windows.Forms.Label(); this.btnClearRoi = new System.Windows.Forms.Button(); this.toolTip = new System.Windows.Forms.ToolTip(this.components); - this.cbClearRoiAfterOperation = new System.Windows.Forms.CheckBox(); - this.btnLayerRangeSelect = new UVtools.GUI.Controls.SplitButton(); this.pnDescription.SuspendLayout(); this.pnLayerRange.SuspendLayout(); this.gbLayerRange.SuspendLayout(); @@ -193,6 +193,16 @@ namespace UVtools.GUI.Forms this.nmLayerRangeEnd.TabIndex = 14; this.nmLayerRangeEnd.ValueChanged += new System.EventHandler(this.EventValueChanged); // + // btnLayerRangeSelect + // + this.btnLayerRangeSelect.Location = new System.Drawing.Point(359, 31); + this.btnLayerRangeSelect.Menu = this.cmLayerRange; + this.btnLayerRangeSelect.Name = "btnLayerRangeSelect"; + this.btnLayerRangeSelect.Size = new System.Drawing.Size(180, 26); + this.btnLayerRangeSelect.TabIndex = 18; + this.btnLayerRangeSelect.Text = "Select"; + this.btnLayerRangeSelect.UseVisualStyleBackColor = true; + // // cmLayerRange // this.cmLayerRange.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -434,6 +444,16 @@ namespace UVtools.GUI.Forms this.gbROI.Text = "ROI - Region of interest"; this.toolTip.SetToolTip(this.gbROI, "The impact of the operation will be limited to the ROI, which can be set directly" + " from the layer preview window."); + // + // cbClearRoiAfterOperation + // + this.cbClearRoiAfterOperation.AutoSize = true; + this.cbClearRoiAfterOperation.Location = new System.Drawing.Point(11, 61); + this.cbClearRoiAfterOperation.Name = "cbClearRoiAfterOperation"; + this.cbClearRoiAfterOperation.Size = new System.Drawing.Size(292, 24); + this.cbClearRoiAfterOperation.TabIndex = 3; + this.cbClearRoiAfterOperation.Text = "Clear ROI after perform the operation"; + this.cbClearRoiAfterOperation.UseVisualStyleBackColor = true; // // lbRoi // @@ -464,26 +484,6 @@ namespace UVtools.GUI.Forms this.toolTip.ToolTipIcon = System.Windows.Forms.ToolTipIcon.Info; this.toolTip.ToolTipTitle = "Information"; // - // cbClearRoiAfterOperation - // - this.cbClearRoiAfterOperation.AutoSize = true; - this.cbClearRoiAfterOperation.Location = new System.Drawing.Point(11, 61); - this.cbClearRoiAfterOperation.Name = "cbClearRoiAfterOperation"; - this.cbClearRoiAfterOperation.Size = new System.Drawing.Size(292, 24); - this.cbClearRoiAfterOperation.TabIndex = 3; - this.cbClearRoiAfterOperation.Text = "Clear ROI after perform the operation"; - this.cbClearRoiAfterOperation.UseVisualStyleBackColor = true; - // - // btnLayerRangeSelect - // - this.btnLayerRangeSelect.Location = new System.Drawing.Point(359, 31); - this.btnLayerRangeSelect.Menu = this.cmLayerRange; - this.btnLayerRangeSelect.Name = "btnLayerRangeSelect"; - this.btnLayerRangeSelect.Size = new System.Drawing.Size(180, 26); - this.btnLayerRangeSelect.TabIndex = 18; - this.btnLayerRangeSelect.Text = "Select"; - this.btnLayerRangeSelect.UseVisualStyleBackColor = true; - // // FrmToolWindow // this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); diff --git a/UVtools.WPF/Controls/AdvancedImageBox.cs b/UVtools.WPF/Controls/AdvancedImageBox.cs index 04f3033..5b785da 100644 --- a/UVtools.WPF/Controls/AdvancedImageBox.cs +++ b/UVtools.WPF/Controls/AdvancedImageBox.cs @@ -636,7 +636,7 @@ namespace UVtools.WPF.Controls set => SetProperty(ref _pixelGridThreshold, value); } - public RectangleF SelectionRegion + public Rect SelectionRegion { get => _selectionRegion; set => SetProperty(ref _selectionRegion, value); @@ -660,7 +660,7 @@ namespace UVtools.WPF.Controls private bool _invertMouse = false; private bool _autoCenter = true; private SizeModes _sizeMode = SizeModes.Normal; - private RectangleF _selectionRegion; + private Rect _selectionRegion; public ContentControl FillContainer { get; } = new ContentControl { @@ -1313,7 +1313,7 @@ namespace UVtools.WPF.Controls public virtual void SelectAll() { if (Image is null) return; - SelectionRegion = new RectangleF(0, 0, (float) Image.Size.Width, (float) Image.Size.Height); + SelectionRegion = new Rect(0, 0, Image.Size.Width, Image.Size.Height); } /// @@ -1321,7 +1321,7 @@ namespace UVtools.WPF.Controls /// public virtual void SelectNone() { - SelectionRegion = RectangleF.Empty; + SelectionRegion = Rect.Empty; } #endregion diff --git a/UVtools.WPF/Controls/Tools/ToolControl.axaml b/UVtools.WPF/Controls/Tools/ToolControl.axaml new file mode 100644 index 0000000..dafec5a --- /dev/null +++ b/UVtools.WPF/Controls/Tools/ToolControl.axaml @@ -0,0 +1,8 @@ + + diff --git a/UVtools.WPF/Controls/Tools/ToolControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolControl.axaml.cs new file mode 100644 index 0000000..f5ae257 --- /dev/null +++ b/UVtools.WPF/Controls/Tools/ToolControl.axaml.cs @@ -0,0 +1,78 @@ +using System.ComponentModel; +using System.Runtime.CompilerServices; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; +using UVtools.Core.Operations; +using UVtools.WPF.Windows; + +namespace UVtools.WPF.Controls.Tools +{ + public abstract class ToolControl : UserControl, INotifyPropertyChanged + { + #region BindableBase + /// + /// Multicast event for property change notifications. + /// + public event PropertyChangedEventHandler PropertyChanged; + + /// + /// 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) + { + if (Equals(storage, value)) + { + return false; + } + + storage = value; + OnPropertyChanged(propertyName); + return true; + } + + /// + /// Notifies listeners that a property value has changed. + /// + /// + /// Name of the property used to notify listeners. This + /// value is optional and can be provided automatically when invoked from compilers + /// that support . + /// + protected void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + var eventHandler = PropertyChanged; + eventHandler?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + #endregion + + public Operation BaseOperation = null; + public ToolWindow ParentWindow = null; + + public ToolControl() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + + public virtual void Callback(ToolWindow.Callbacks callback) { } + + public virtual bool ValidateForm() => true; + } +} diff --git a/UVtools.WPF/Controls/Tools/ToolFlipControl.axaml b/UVtools.WPF/Controls/Tools/ToolFlipControl.axaml new file mode 100644 index 0000000..dc56f52 --- /dev/null +++ b/UVtools.WPF/Controls/Tools/ToolFlipControl.axaml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/UVtools.WPF/Controls/Tools/ToolFlipControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolFlipControl.axaml.cs new file mode 100644 index 0000000..eda1fca --- /dev/null +++ b/UVtools.WPF/Controls/Tools/ToolFlipControl.axaml.cs @@ -0,0 +1,22 @@ +using Avalonia.Markup.Xaml; +using UVtools.Core.Operations; + +namespace UVtools.WPF.Controls.Tools +{ + public class ToolFlipControl : ToolControl + { + public OperationFlip Operation { get; } + + public ToolFlipControl() + { + InitializeComponent(); + BaseOperation = Operation = new OperationFlip(); + DataContext = this; + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + } +} diff --git a/UVtools.WPF/MainWindow.axaml.cs b/UVtools.WPF/MainWindow.axaml.cs index 3320117..7cdbc93 100644 --- a/UVtools.WPF/MainWindow.axaml.cs +++ b/UVtools.WPF/MainWindow.axaml.cs @@ -32,8 +32,10 @@ using ReactiveUI; using UVtools.Core; using UVtools.Core.Extensions; using UVtools.Core.FileFormats; +using UVtools.Core.Operations; using UVtools.Core.PixelEditor; using UVtools.WPF.Controls; +using UVtools.WPF.Controls.Tools; using UVtools.WPF.Extensions; using UVtools.WPF.Structures; using UVtools.WPF.Windows; @@ -640,7 +642,7 @@ namespace UVtools.WPF private void IssuesGridOnSelectionChanged(PointerPressedEventArgs pointer = null) { - if (IssuesGrid.SelectedItems.Count > 1) return; + if (IssuesGrid.SelectedItems.Count != 1) return; if (!(IssuesGrid.SelectedItem is LayerIssue issue)) return; if (issue.Type == LayerIssue.IssueType.TouchingBound || issue.Type == LayerIssue.IssueType.EmptyLayer || @@ -674,26 +676,26 @@ namespace UVtools.WPF private void IssuesGridOnCellPointerPressed(object? sender, DataGridCellPointerPressedEventArgs e) { - if(!(IssuesGrid.SelectedItem is LayerIssue issue)) return; + if (IssuesGrid.SelectedItems.Count != 1 || e.PointerPressedEventArgs.ClickCount == 2) return; + if (!(IssuesGrid.SelectedItem is LayerIssue issue)) return; // Double clicking an issue will center and zoom into the // selected issue. Left click on an issue will zoom to fit. var pointer = e.PointerPressedEventArgs.GetCurrentPoint(IssuesGrid); - if (e.PointerPressedEventArgs.ClickCount == 2) + if (pointer.Properties.IsLeftButtonPressed) { - if (pointer.Properties.IsLeftButtonPressed) - { - ZoomToIssue(issue, e.PointerPressedEventArgs); - return; - } - - if (pointer.Properties.IsRightButtonPressed) - { - ZoomToFit(e.PointerPressedEventArgs); - return; - } + ZoomToIssue(issue, e.PointerPressedEventArgs); + return; } + if (pointer.Properties.IsRightButtonPressed) + { + ZoomToFit(e.PointerPressedEventArgs); + return; + } + + ForceUpdateActualLayer(issue.LayerIndex); + } public void OnClickDetectIssues() @@ -1156,6 +1158,7 @@ namespace UVtools.WPF public async void MenuHelpAboutClicked() { + new ToolWindow(new ToolFlipControl()).Show(this); await new AboutWindow().ShowDialog(this); } diff --git a/UVtools.WPF/Windows/ToolWindow.axaml b/UVtools.WPF/Windows/ToolWindow.axaml new file mode 100644 index 0000000..858e101 --- /dev/null +++ b/UVtools.WPF/Windows/ToolWindow.axaml @@ -0,0 +1,243 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/UVtools.WPF/Windows/ToolWindow.axaml.cs b/UVtools.WPF/Windows/ToolWindow.axaml.cs new file mode 100644 index 0000000..f967baf --- /dev/null +++ b/UVtools.WPF/Windows/ToolWindow.axaml.cs @@ -0,0 +1,275 @@ +using System; +using System.Timers; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; +using MessageBox.Avalonia.Enums; +using UVtools.Core; +using UVtools.WPF.Controls; +using UVtools.WPF.Controls.Tools; +using UVtools.WPF.Extensions; + +namespace UVtools.WPF.Windows +{ + public class ToolWindow : WindowEx + { + public enum Callbacks : byte + { + ClearROI, + Button1, // Reset to defaults + Checkbox1, // Show Advanced + } + public ToolControl ToolControl; + private string _description; + private double _descriptionMaxWidth; + private bool _layerRangeVisible = true; + private uint _layerIndexStart; + private uint _layerIndexEnd; + private bool _buttonOkEnabled = true; + private string _buttonOkText = "Ok"; + private bool _isROIVisible; + private Rect _roi = Rect.Empty; + private bool _clearRoiAfterOperation; + + private IControl _contentControl; + + #region Description + + public string Description + { + get => _description; + set => SetProperty(ref _description, value); + } + + public double DescriptionMaxWidth + { + get => _descriptionMaxWidth; + set => SetProperty(ref _descriptionMaxWidth, value); + } + + #endregion + + #region Layer Selector + + public bool LayerRangeVisible + { + get => _layerRangeVisible; + set => SetProperty(ref _layerRangeVisible, value); + } + + public uint LayerIndexStart + { + get => _layerIndexStart; + set + { + SetProperty(ref _layerIndexStart, value); + if(!(ToolControl?.BaseOperation is null)) + ToolControl.BaseOperation.LayerIndexStart = _layerIndexStart; + } + } + + public uint LayerIndexEnd + { + get => _layerIndexEnd; + set + { + SetProperty(ref _layerIndexEnd, value); + if (!(ToolControl?.BaseOperation is null)) + ToolControl.BaseOperation.LayerIndexEnd = _layerIndexEnd; + } + } + + public uint MaximumLayerIndex => App.MainWindow?.SliderMaximumValue ?? 0; + + public void SelectAllLayers() + { + LayerIndexStart = 0; + LayerIndexEnd = MaximumLayerIndex; + } + + public void SelectCurrentLayer() + { + LayerIndexStart = LayerIndexEnd = App.MainWindow.ActualLayer; + } + + public void SelectBottomLayers() + { + LayerIndexStart = 0; + LayerIndexEnd = App.SlicerFile.BottomLayerCount-1u; + } + + public void SelectNormalLayers() + { + LayerIndexStart = App.SlicerFile.BottomLayerCount; + LayerIndexEnd = MaximumLayerIndex; + } + + public void SelectFirstLayer() + { + LayerIndexStart = LayerIndexEnd = 0; + } + + public void SelectLastLayer() + { + LayerIndexStart = LayerIndexEnd = MaximumLayerIndex; + } + #endregion + + #region ROI + + public bool IsROIVisible + { + get => ToolControl?.BaseOperation.HaveROI ?? _isROIVisible; + set => SetProperty(ref _isROIVisible, value); + } + + public Rect ROI + { + get => _roi; + set => SetProperty(ref _roi, value); + } + + public bool ClearROIAfterOperation + { + get => _clearRoiAfterOperation; + set => SetProperty(ref _clearRoiAfterOperation, value); + } + + public async void ClearROI() + { + if (await this.MessageBoxQuestion("Are you sure you want to clear the current ROI?\n" + + "This action can not be reverted, to select another ROI you must quit this window and select it on layer preview.", + "Clear the current ROI?") != ButtonResult.Yes) return; + IsROIVisible = false; + App.MainWindow.LayerImageBox.SelectNone(); + ToolControl?.Callback(Callbacks.ClearROI); + } + + #endregion + + #region Content + + public IControl ContentControl + { + get => _contentControl; + set => SetProperty(ref _contentControl, value); + } + + #endregion + + #region Actions + + public bool ButtonOkEnabled + { + get => _buttonOkEnabled; + set => SetProperty(ref _buttonOkEnabled, value); + } + + public string ButtonOkText + { + get => _buttonOkText; + set => SetProperty(ref _buttonOkText, value); + } + + #endregion + + public ToolWindow() + { + InitializeComponent(); + DataContext = this; + SelectAllLayers(); + } + + public ToolWindow(string description = null, bool layerRangeVisible = true) : this() + { + Description = description; + LayerRangeVisible = layerRangeVisible; + } + + public ToolWindow(ToolControl toolControl) : this( ) + { + ToolControl = toolControl; + toolControl.ParentWindow = this; + + Title = toolControl.BaseOperation.Title; + LayerRangeVisible = toolControl.BaseOperation.LayerRangeSelection != Enumerations.LayerRangeSelection.None; + IsROIVisible = toolControl.BaseOperation.CanROI; + ContentControl = toolControl; + ButtonOkText = toolControl.BaseOperation.ButtonOkText; + + switch (toolControl.BaseOperation.LayerRangeSelection) + { + case Enumerations.LayerRangeSelection.None: + break; + case Enumerations.LayerRangeSelection.All: + SelectAllLayers(); + break; + case Enumerations.LayerRangeSelection.Current: + SelectCurrentLayer(); + break; + case Enumerations.LayerRangeSelection.Bottom: + SelectBottomLayers(); + break; + case Enumerations.LayerRangeSelection.Normal: + SelectNormalLayers(); + break; + case Enumerations.LayerRangeSelection.First: + SelectFirstLayer(); + break; + case Enumerations.LayerRangeSelection.Last: + SelectLastLayer(); + break; + default: + throw new ArgumentOutOfRangeException(); + } + + // Ensure the description don't stretch window + var timer = new Timer(10) + { + AutoReset = true + }; + timer.Elapsed += (sender, args) => + { + if (Bounds.Width == 0) return; + DescriptionMaxWidth = Math.Max(Bounds.Width, ToolControl?.Bounds.Width ?? 0); + Description = toolControl.BaseOperation.Description; + timer.Stop(); + timer.Dispose(); + }; + timer.Start(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + + public async void Process() + { + if (LayerIndexStart > LayerIndexEnd) + { + await this.MessageBoxError("Layer range start can't be higher than layer end.\nPlease fix and try again."); + return; + } + + if (!ReferenceEquals(ToolControl, null)) + { + if(!ToolControl.ValidateForm()) return; + if (!string.IsNullOrEmpty(ToolControl.BaseOperation.ConfirmationText)) + { + if (await this.MessageBoxQuestion( + $"Are you sure you want to {ToolControl.BaseOperation.ConfirmationText}") != + ButtonResult.Yes) return; + } + } + + if (ClearROIAfterOperation) + { + App.MainWindow.LayerImageBox.SelectNone(); + } + + DialogResult = DialogResults.OK; + Close(DialogResult); + } + } +}