From ab8dde41421292d6e9f92474993526d43b3f1601 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20Concei=C3=A7=C3=A3o?= Date: Sat, 26 Sep 2020 17:27:36 +0100 Subject: [PATCH] WPF ShowRunOperation --- UVtools.Core/Operations/OperationFlip.cs | 3 - UVtools.WPF/App.axaml.cs | 22 + UVtools.WPF/Assets/Icons/Lock-16x16.png | Bin 1261 -> 281 bytes .../Icons/{copy_16x16.png => copy-16x16.png} | Bin UVtools.WPF/Assets/Icons/crosshairs-16x16.png | Bin 3295 -> 307 bytes .../Controls/Tools/ToolControl.axaml.cs | 9 +- UVtools.WPF/MainWindow.axaml | 6 +- UVtools.WPF/MainWindow.axaml.cs | 395 +++++++++++++++++- UVtools.WPF/Windows/ToolWindow.axaml | 2 + UVtools.WPF/Windows/ToolWindow.axaml.cs | 4 + 10 files changed, 424 insertions(+), 17 deletions(-) rename UVtools.WPF/Assets/Icons/{copy_16x16.png => copy-16x16.png} (100%) diff --git a/UVtools.Core/Operations/OperationFlip.cs b/UVtools.Core/Operations/OperationFlip.cs index fa1a508..fad6768 100644 --- a/UVtools.Core/Operations/OperationFlip.cs +++ b/UVtools.Core/Operations/OperationFlip.cs @@ -56,8 +56,5 @@ namespace UVtools.Core.Operations } public static Array FlipDirections => Enum.GetValues(typeof(Enumerations.FlipDirection)); - - - } } diff --git a/UVtools.WPF/App.axaml.cs b/UVtools.WPF/App.axaml.cs index e4ebb6c..96faff3 100644 --- a/UVtools.WPF/App.axaml.cs +++ b/UVtools.WPF/App.axaml.cs @@ -9,11 +9,14 @@ using System; using System.Diagnostics; using System.Globalization; +using System.IO; +using System.Reflection; using System.Runtime.InteropServices; using System.Threading; using Avalonia; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Markup.Xaml; +using Avalonia.Platform; using Avalonia.ThemeManager; using UVtools.Core.FileFormats; @@ -112,6 +115,25 @@ namespace UVtools.WPF } + public static Stream GetAsset(string url) + { + Uri uri; + + // Allow for assembly overrides + if (url.StartsWith("avares://")) + { + uri = new Uri(url); + } + else + { + var assemblyName = Assembly.GetEntryAssembly().GetName().Name; + uri = new Uri($"avares://{assemblyName}{url}"); + } + + var res = AvaloniaLocator.Current.GetService().Open(uri); + return res; + } + #endregion } } diff --git a/UVtools.WPF/Assets/Icons/Lock-16x16.png b/UVtools.WPF/Assets/Icons/Lock-16x16.png index 8af4d268e6640085ec6335227b21befe86c4af85..4ee4208435a752d072f74d8c6c3b0393417c4e55 100644 GIT binary patch delta 253 zcmVBZPYhFBDE zyk_{X6z;*SXTtu1;eVP6ngW?dhX27j2tlr+XbMawlzcVX}0{;IZI}i%g z8W{dJh{F|F^Qu_!{pUK(slwm_f-K6si&_86CmM1?74S?35_VW1=TxWywL+~2#+MAw z8(x6J^G4?lJ}8$!6cB(wB+|w7pWzR~Pc-;nun($0a3UjC&Ad~HwL&_Z@i@aqG`NA` zl1L6zfm8<*R?Q+XH^eDRRWU5$n1&2l=5S331jh{kju_#IyFXs700000NkvXXu0mjf DDNS)O delta 1241 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 Z2LO6ruDN!jH}(Jk002ovPDHLkV1gZkD@y @@ -61,11 +61,18 @@ namespace UVtools.WPF.Controls.Tools public Operation BaseOperation = null; public ToolWindow ParentWindow = null; + public bool CanRun { get; set; } = true; + public ToolControl() { InitializeComponent(); } + public ToolControl(Operation operation) : this() + { + BaseOperation = operation; + } + private void InitializeComponent() { AvaloniaXamlLoader.Load(this); diff --git a/UVtools.WPF/MainWindow.axaml b/UVtools.WPF/MainWindow.axaml index 7a4d0ad..b81ec1e 100644 --- a/UVtools.WPF/MainWindow.axaml +++ b/UVtools.WPF/MainWindow.axaml @@ -117,7 +117,11 @@ - + diff --git a/UVtools.WPF/MainWindow.axaml.cs b/UVtools.WPF/MainWindow.axaml.cs index 7cdbc93..848cbdb 100644 --- a/UVtools.WPF/MainWindow.axaml.cs +++ b/UVtools.WPF/MainWindow.axaml.cs @@ -21,6 +21,7 @@ using Avalonia.Controls; using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.Markup.Xaml; +using Avalonia.Platform; using Avalonia.Threading; using DynamicData; using Emgu.CV; @@ -66,6 +67,159 @@ namespace UVtools.WPF public DataGrid IssuesGrid; + public static MenuItem[] MenuTools { get; } = + { + new MenuItem + { + Tag = new OperationEditParameters(), + Icon = new Avalonia.Controls.Image + { + Source = new Bitmap(App.GetAsset("/Assets/Icons/wrench-16x16.png")) + } + }, + new MenuItem + { + Tag = new OperationRepairLayers(), + Icon = new Avalonia.Controls.Image + { + Source = new Bitmap(App.GetAsset("/Assets/Icons/toolbox-16x16.png")) + } + }, + new MenuItem + { + Tag = new OperationMove(), + Icon = new Avalonia.Controls.Image + { + Source = new Bitmap(App.GetAsset("/Assets/Icons/move-16x16.png")) + } + }, + new MenuItem + { + Tag = new OperationResize(), + Icon = new Avalonia.Controls.Image + { + Source = new Bitmap(App.GetAsset("/Assets/Icons/crop-16x16.png")) + + } + }, + new MenuItem + { + Tag = new OperationFlip(), + Icon = new Avalonia.Controls.Image + { + Source = new Bitmap(App.GetAsset("/Assets/Icons/flip-16x16.png")) + } + }, + new MenuItem + { + Tag = new OperationRotate(), + Icon = new Avalonia.Controls.Image + { + Source = new Bitmap(App.GetAsset("/Assets/Icons/sync-16x16.png")) + } + }, + new MenuItem + { + Tag = new OperationSolidify(), + Icon = new Avalonia.Controls.Image + { + Source = new Bitmap(App.GetAsset("/Assets/Icons/square-solid-16x16.png")) + } + }, + new MenuItem + { + Tag = new OperationMorph(), + Icon = new Avalonia.Controls.Image + { + Source = new Bitmap(App.GetAsset("/Assets/Icons/geometry-16x16.png")) + } + }, + new MenuItem + { + Tag = new OperationMask(), + Icon = new Avalonia.Controls.Image + { + Source = new Bitmap(App.GetAsset("/Assets/Icons/mask-16x16.png")) + } + }, + new MenuItem + { + Tag = new OperationPixelDimming(), + Icon = new Avalonia.Controls.Image + { + Source = new Bitmap(App.GetAsset("/Assets/Icons/pixel-16x16.png")) + } + }, + new MenuItem + { + Tag = new OperationThreshold(), + Icon = new Avalonia.Controls.Image + { + Source = new Bitmap(App.GetAsset("/Assets/Icons/th-16x16.png")) + } + }, + new MenuItem + { + Tag = new OperationBlur(), + Icon = new Avalonia.Controls.Image + { + Source = new Bitmap(App.GetAsset("/Assets/Icons/blur-16x16.png")) + } + }, + new MenuItem + { + Tag = new OperationPattern(), + Icon = new Avalonia.Controls.Image + { + Source = new Bitmap(App.GetAsset("/Assets/Icons/pattern-16x16.png")) + } + }, + new MenuItem + { + Tag = new OperationLayerReHeight(), + Icon = new Avalonia.Controls.Image + { + Source = new Bitmap(App.GetAsset("/Assets/Icons/ladder-16x16.png")) + } + }, + new MenuItem + { + Tag = new OperationChangeResolution(), + Icon = new Avalonia.Controls.Image + { + Source = new Bitmap(App.GetAsset("/Assets/Icons/resize-16x16.png")) + } + }, + }; + + public static MenuItem[] LayerActions { get; } = + { + new MenuItem + { + Tag = new OperationLayerImport(), + Icon = new Avalonia.Controls.Image + { + Source = new Bitmap(App.GetAsset("/Assets/Icons/file-import-16x16.png")) + } + }, + new MenuItem + { + Tag = new OperationLayerClone(), + Icon = new Avalonia.Controls.Image + { + Source = new Bitmap(App.GetAsset("/Assets/Icons/copy-16x16.png")) + } + }, + new MenuItem + { + Tag = new OperationLayerRemove(), + Icon = new Avalonia.Controls.Image + { + Source = new Bitmap(App.GetAsset("/Assets/Icons/trash-16x16.png")) + } + }, + }; + #region DataSets public ObservableCollection SlicerProperties { get; } = new ObservableCollection(); public ObservableCollection Logs { get; } = new ObservableCollection(); @@ -1033,6 +1187,17 @@ namespace UVtools.WPF _showLayerOutlineLayerBoundary = Settings.LayerPreview.LayerBoundsOutline; _showLayerOutlineHollowAreas = Settings.LayerPreview.HollowOutline; + foreach (var menuItem in new[] { MenuTools, LayerActions}) + { + foreach (var menuTool in menuItem) + { + if (!(menuTool.Tag is Operation operation)) continue; + menuTool.Header = operation.Title; + menuTool.Click += (sender, args) => ShowRunOperation(operation.GetType()); + } + } + + /*LayerSlider.PropertyChanged += (sender, args) => { Debug.WriteLine(args.Property.Name); @@ -1284,17 +1449,7 @@ namespace UVtools.WPF VisibleThumbnailIndex = 1; - if (!(SlicerFile.Configs is null)) - { - foreach (var config in SlicerFile.Configs) - { - var type = config.GetType(); - foreach (var property in type.GetProperties()) - { - SlicerProperties.Add(new SlicerProperty(property.Name, property.GetValue(config, null)?.ToString(), type.Name)); - } - } - } + RefreshProperties(); UpdateTitle(); @@ -2150,6 +2305,222 @@ namespace UVtools.WPF } #endregion + #region Operations + public Operation ShowRunOperation(Type type) + { + var operation = ShowOperation(type); + RunOperation(operation.Result); + return operation.Result; + } + + public async Task ShowOperation(Type type) + { + var typeBase = typeof(ToolControl); + var classname = $"{typeBase.Namespace}.Tool{type.Name.Remove(0, Operation.ClassNameLength)}Control"; + var controlType = Type.GetType(classname); + ToolControl control; + + bool removeContent = false; + if (controlType is null) + { + controlType = typeBase; + removeContent = true; + control = new ToolControl(type.CreateInstance()); + } + else + { + control = controlType.CreateInstance(); + if (control is null) return null; + } + + if (!control.CanRun) + { + return null; + } + + if (removeContent) + { + control.IsVisible = false; + } + + var window = new ToolWindow(control); + //window.ShowDialog(this); + await window.ShowDialog(this); + if (window.DialogResult != DialogResults.OK) return null; + var operation = control.BaseOperation; + return operation; + } + + public bool RunOperation(Operation baseOperation) + { + if (baseOperation is null) return false; + + switch (baseOperation) + { + case OperationEditParameters operation: + /*foreach (var modifier in operation.Modifiers.Where(modifier => modifier.HasChanged)) + { + SlicerFile.SetValueFromPrintParameterModifier(modifier, modifier.NewValue); + }*/ + SlicerFile.SetValuesFromPrintParametersModifiers(); + RefreshProperties(); + + CanSave = true; + + return false; + case OperationRepairLayers operation: + if (ReferenceEquals(Issues, null)) + { + var islandConfig = GetIslandDetectionConfiguration(); + islandConfig.Enabled = + operation.RepairIslands && operation.RemoveIslandsBelowEqualPixelCount > 0; + var resinTrapConfig = GetResinTrapDetectionConfiguration(); + resinTrapConfig.Enabled = operation.RepairResinTraps; + var touchingBoundConfig = new TouchingBoundDetectionConfiguration { Enabled = false }; + + if (islandConfig.Enabled || resinTrapConfig.Enabled) + { + ComputeIssues(islandConfig, resinTrapConfig, touchingBoundConfig, Settings.Issues.ComputeEmptyLayers); + } + } + + operation.Issues = Issues.ToList(); + + break; + } + + IsGUIEnabled = false; + + ProgressWindow.SetTitle(baseOperation.ProgressTitle); + + var task = Task.Factory.StartNew(async () => + { + var backup = new Layer[baseOperation.LayerRangeCount]; + uint i = 0; + for (uint layerIndex = baseOperation.LayerIndexStart; layerIndex <= baseOperation.LayerIndexEnd; layerIndex++) + { + backup[i++] = SlicerFile[layerIndex].Clone(); + } + + try + { + switch (baseOperation) + { + // Tools + case OperationRepairLayers operation: + SlicerFile.LayerManager.RepairLayers(operation, ProgressWindow.RestartProgress(operation.CanCancel)); + break; + case OperationMove operation: + SlicerFile.LayerManager.Move(operation, ProgressWindow.RestartProgress(operation.CanCancel)); + break; + case OperationResize operation: + SlicerFile.LayerManager.Resize(operation, ProgressWindow.RestartProgress(operation.CanCancel)); + break; + case OperationFlip operation: + SlicerFile.LayerManager.Flip(operation, ProgressWindow.RestartProgress(operation.CanCancel)); + break; + case OperationRotate operation: + SlicerFile.LayerManager.Rotate(operation, ProgressWindow.RestartProgress(operation.CanCancel)); + break; + case OperationSolidify operation: + SlicerFile.LayerManager.Solidify(operation, ProgressWindow.RestartProgress(operation.CanCancel)); + break; + case OperationMorph operation: + SlicerFile.LayerManager.Morph(operation, BorderType.Default, new MCvScalar(), ProgressWindow.RestartProgress(operation.CanCancel)); + break; + case OperationMask operation: + SlicerFile.LayerManager.Mask(operation, ProgressWindow.RestartProgress(operation.CanCancel)); + break; + case OperationPixelDimming operation: + SlicerFile.LayerManager.PixelDimming(operation, ProgressWindow.RestartProgress(operation.CanCancel)); + break; + case OperationThreshold operation: + SlicerFile.LayerManager.ThresholdPixels(operation, ProgressWindow.RestartProgress(operation.CanCancel)); + break; + case OperationBlur operation: + SlicerFile.LayerManager.Blur(operation, ProgressWindow.RestartProgress(operation.CanCancel)); + break; + + case OperationChangeResolution operation: + SlicerFile.LayerManager.ChangeResolution(operation, ProgressWindow.RestartProgress(operation.CanCancel)); + break; + case OperationLayerReHeight operation: + SlicerFile.LayerManager.ReHeight(operation, ProgressWindow.RestartProgress(operation.CanCancel)); + break; + case OperationPattern operation: + SlicerFile.LayerManager.Pattern(operation, ProgressWindow.RestartProgress(operation.CanCancel)); + break; + // Actions + case OperationLayerImport operation: + SlicerFile.LayerManager.Import(operation, ProgressWindow.RestartProgress(operation.CanCancel)); + break; + case OperationLayerClone operation: + SlicerFile.LayerManager.CloneLayer(operation, ProgressWindow.RestartProgress(operation.CanCancel)); + break; + case OperationLayerRemove operation: + SlicerFile.LayerManager.RemoveLayers(operation, ProgressWindow.RestartProgress(operation.CanCancel)); + break; + + default: + throw new NotImplementedException(); + } + } + catch (OperationCanceledException) + { + i = 0; + for (uint layerIndex = baseOperation.LayerIndexStart; layerIndex <= baseOperation.LayerIndexEnd; layerIndex++) + { + SlicerFile[layerIndex] = backup[i++]; + } + } + catch (Exception ex) + { + await this.MessageBoxError(ex.Message, $"{baseOperation.Title} Error"); + } + finally + { + IsGUIEnabled = true; + } + }); + + ProgressWindow.ShowDialog(this); + + ShowLayer(); + RefreshProperties(); + ResetDataContext(); + + CanSave = true; + + switch (baseOperation) + { + // Tools + case OperationRepairLayers operation: + OnClickDetectIssues(); + break; + } + + + return true; + } + #endregion - } + + public void RefreshProperties() + { + SlicerProperties.Clear(); + if (!(SlicerFile.Configs is null)) + { + foreach (var config in SlicerFile.Configs) + { + var type = config.GetType(); + foreach (var property in type.GetProperties()) + { + SlicerProperties.Add(new SlicerProperty(property.Name, property.GetValue(config, null)?.ToString(), type.Name)); + } + } + } + } + + #endregion + } } diff --git a/UVtools.WPF/Windows/ToolWindow.axaml b/UVtools.WPF/Windows/ToolWindow.axaml index 858e101..048a019 100644 --- a/UVtools.WPF/Windows/ToolWindow.axaml +++ b/UVtools.WPF/Windows/ToolWindow.axaml @@ -184,7 +184,9 @@ + ContentControl is null || ContentControl.IsVisible; + public IControl ContentControl { get => _contentControl; @@ -197,6 +199,8 @@ namespace UVtools.WPF.Windows ContentControl = toolControl; ButtonOkText = toolControl.BaseOperation.ButtonOkText; + OnPropertyChanged(nameof(IsContentVisible)); + switch (toolControl.BaseOperation.LayerRangeSelection) { case Enumerations.LayerRangeSelection.None: