From 374e590574e6be0c5d5d08f49bc1f638f46d82b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20Concei=C3=A7=C3=A3o?= Date: Tue, 15 Feb 2022 22:14:52 +0000 Subject: v2.28.1 - (Add) File - Terminal: Inject C# code into UVtools with an interactive terminal - (Improvement) Modifiers: Better increment values for the spin up/down buttons - (Improvement) Tool - Timelapse: Better lift and feeds for virtual layer, also allow to set custom lift speed for that mode - (Fix) Tool - Edit print parameters: Disallow to change PositionZ in layers with an active alternating pattern - (Fix) GCode: When generating layers higher than the next, it will not return to the correct position z --- CHANGELOG.md | 8 + UVtools.Core/FileFormats/FileFormat.cs | 50 +++--- UVtools.Core/GCode/GCodeBuilder.cs | 6 +- UVtools.Core/Operations/OperationEditParameters.cs | 19 +- UVtools.Core/Operations/OperationTimelapse.cs | 60 ++++--- UVtools.Core/UVtools.Core.csproj | 2 +- UVtools.WPF/Assets/Icons/terminal-16x16.png | Bin 0 -> 123 bytes .../Tools/ToolEditParametersControl.axaml.cs | 4 +- .../Controls/Tools/ToolTimelapseControl.axaml | 38 +++- UVtools.WPF/Extensions/WindowExtensions.cs | 19 +- UVtools.WPF/MainWindow.axaml | 15 +- UVtools.WPF/MainWindow.axaml.cs | 11 +- UVtools.WPF/UVtools.WPF.csproj | 4 +- UVtools.WPF/Windows/TerminalWindow.axaml | 78 ++++++++ UVtools.WPF/Windows/TerminalWindow.axaml.cs | 200 +++++++++++++++++++++ UVtools.WPF/Windows/ToolWindow.axaml.cs | 9 +- 16 files changed, 439 insertions(+), 84 deletions(-) create mode 100644 UVtools.WPF/Assets/Icons/terminal-16x16.png create mode 100644 UVtools.WPF/Windows/TerminalWindow.axaml create mode 100644 UVtools.WPF/Windows/TerminalWindow.axaml.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index f0e0b26..72c96dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 15/02/2022 - v2.28.1 + +- (Add) File - Terminal: Inject C# code into UVtools with an interactive terminal +- (Improvement) Modifiers: Better increment values for the spin up/down buttons +- (Improvement) Tool - Timelapse: Better lift and feeds for virtual layer, also allow to set custom lift speed for that mode +- (Fix) Tool - Edit print parameters: Disallow to change PositionZ in layers with an active alternating pattern +- (Fix) GCode: When generating layers higher than the next, it will not return to the correct position z + ## 13/02/2022 - v2.28.0 - **Core:** diff --git a/UVtools.Core/FileFormats/FileFormat.cs b/UVtools.Core/FileFormats/FileFormat.cs index 007dbff..ce5ad49 100644 --- a/UVtools.Core/FileFormats/FileFormat.cs +++ b/UVtools.Core/FileFormats/FileFormat.cs @@ -147,46 +147,46 @@ namespace UVtools.Core.FileFormats { #region Instances - public static PrintParameterModifier PositionZ { get; } = new ("Position Z", "Absolute Z position", "mm",0, 100000, Layer.HeightPrecision); - public static PrintParameterModifier BottomLayerCount { get; } = new ("Bottom layers count", "Number of bottom/burn-in layers", "layers",0, ushort.MaxValue, 0); - + public static PrintParameterModifier PositionZ { get; } = new ("Position Z", "Absolute Z position", "mm",0, 100000, 0.01, Layer.HeightPrecision); + public static PrintParameterModifier BottomLayerCount { get; } = new ("Bottom layers count", "Number of bottom/burn-in layers", "layers",0, ushort.MaxValue, 1, 0); + public static PrintParameterModifier BottomLightOffDelay { get; } = new("Bottom light-off seconds", "Total motor movement time + rest time to wait before cure a new bottom layer", "s"); public static PrintParameterModifier LightOffDelay { get; } = new("Light-off seconds", "Total motor movement time + rest time to wait before cure a new layer", "s"); - public static PrintParameterModifier BottomWaitTimeBeforeCure { get; } = new ("Bottom wait before cure", "Time to wait/rest before cure a new bottom layer\nChitubox: Rest after retract\nLychee: Wait before print", "s", 0, 1000, 2); - public static PrintParameterModifier WaitTimeBeforeCure { get; } = new ("Wait before cure", "Time to wait/rest before cure a new layer\nChitubox: Rest after retract\nLychee: Wait before print", "s", 0, 1000, 2); + public static PrintParameterModifier BottomWaitTimeBeforeCure { get; } = new ("Bottom wait before cure", "Time to wait/rest before cure a new bottom layer\nChitubox: Rest after retract\nLychee: Wait before print", "s"); + public static PrintParameterModifier WaitTimeBeforeCure { get; } = new ("Wait before cure", "Time to wait/rest before cure a new layer\nChitubox: Rest after retract\nLychee: Wait before print", "s"); - public static PrintParameterModifier BottomExposureTime { get; } = new ("Bottom exposure time", "Bottom layers cure time", "s", 0.1M, 1000, 2); - public static PrintParameterModifier ExposureTime { get; } = new ("Exposure time", "Layers cure time", "s", 0.1M, 1000, 2); + public static PrintParameterModifier BottomExposureTime { get; } = new ("Bottom exposure time", "Bottom layers cure time", "s", 0.1M); + public static PrintParameterModifier ExposureTime { get; } = new ("Exposure time", "Layers cure time", "s", 0.1M); - public static PrintParameterModifier BottomWaitTimeAfterCure { get; } = new("Bottom wait after cure", "Time to wait/rest after cure a new bottom layer\nChitubox: Rest before lift\nLychee: Wait after print", "s", 0, 1000, 2); - public static PrintParameterModifier WaitTimeAfterCure { get; } = new("Wait after cure", "Time to wait/rest after cure a new bottom layer\nChitubox: Rest before lift\nLychee: Wait after print", "s", 0, 1000, 2); + public static PrintParameterModifier BottomWaitTimeAfterCure { get; } = new("Bottom wait after cure", "Time to wait/rest after cure a new bottom layer\nChitubox: Rest before lift\nLychee: Wait after print", "s"); + public static PrintParameterModifier WaitTimeAfterCure { get; } = new("Wait after cure", "Time to wait/rest after cure a new bottom layer\nChitubox: Rest before lift\nLychee: Wait after print", "s"); public static PrintParameterModifier BottomLiftHeight { get; } = new ("Bottom lift height", "Bottom lift/peel height between layers", "mm", 1); public static PrintParameterModifier LiftHeight { get; } = new ("Lift height", @"Lift/peel height between layers", "mm", 1); - public static PrintParameterModifier BottomLiftSpeed { get; } = new ("Bottom lift speed", null, "mm/min", 10, 5000, 2); - public static PrintParameterModifier LiftSpeed { get; } = new ("Lift speed", null, "mm/min", 10, 5000, 2); + public static PrintParameterModifier BottomLiftSpeed { get; } = new ("Bottom lift speed", null, "mm/min", 10, 5000, 5); + public static PrintParameterModifier LiftSpeed { get; } = new ("Lift speed", null, "mm/min", 10, 5000, 5); public static PrintParameterModifier BottomLiftHeight2 { get; } = new("2) Bottom lift height", "Bottom second lift/peel height between layers", "mm"); public static PrintParameterModifier LiftHeight2 { get; } = new("2) Lift height", @"Second lift/peel height between layers", "mm"); - public static PrintParameterModifier BottomLiftSpeed2 { get; } = new("2) Bottom lift speed", null, "mm/min", 10, 5000, 2); - public static PrintParameterModifier LiftSpeed2 { get; } = new("2) Lift speed", null, "mm/min", 10, 5000, 2); + public static PrintParameterModifier BottomLiftSpeed2 { get; } = new("2) Bottom lift speed", null, "mm/min", 10, 5000, 5); + public static PrintParameterModifier LiftSpeed2 { get; } = new("2) Lift speed", null, "mm/min", 10, 5000, 5); - public static PrintParameterModifier BottomWaitTimeAfterLift { get; } = new("Bottom wait after lift", "Time to wait/rest after a lift/peel sequence at bottom layers\nChitubox: Rest after lift\nLychee: Wait after lift", "s", 0, 1000, 2); - public static PrintParameterModifier WaitTimeAfterLift { get; } = new("Wait after lift", "Time to wait/rest after a lift/peel sequence at layers\nChitubox: Rest after lift\nLychee: Wait after lift", "s", 0, 1000, 2); + public static PrintParameterModifier BottomWaitTimeAfterLift { get; } = new("Bottom wait after lift", "Time to wait/rest after a lift/peel sequence at bottom layers\nChitubox: Rest after lift\nLychee: Wait after lift", "s"); + public static PrintParameterModifier WaitTimeAfterLift { get; } = new("Wait after lift", "Time to wait/rest after a lift/peel sequence at layers\nChitubox: Rest after lift\nLychee: Wait after lift", "s"); - public static PrintParameterModifier BottomRetractSpeed { get; } = new ("Bottom retract speed", "Bottom down speed from lift height to next layer cure position", "mm/min", 10, 5000, 2); - public static PrintParameterModifier RetractSpeed { get; } = new ("Retract speed", "Down speed from lift height to next layer cure position", "mm/min", 10, 5000, 2); + public static PrintParameterModifier BottomRetractSpeed { get; } = new ("Bottom retract speed", "Bottom down speed from lift height to next layer cure position", "mm/min", 10, 5000, 5); + public static PrintParameterModifier RetractSpeed { get; } = new ("Retract speed", "Down speed from lift height to next layer cure position", "mm/min", 10, 5000, 5); public static PrintParameterModifier BottomRetractHeight2 { get; } = new("2) Bottom retract height", null, "mm"); public static PrintParameterModifier RetractHeight2 { get; } = new("2) Retract height", null, "mm"); - public static PrintParameterModifier BottomRetractSpeed2 { get; } = new("2) Bottom retract speed", null, "mm/min", 10, 5000, 2); - public static PrintParameterModifier RetractSpeed2 { get; } = new("2) Retract speed", null, "mm/min", 10, 5000, 2); + public static PrintParameterModifier BottomRetractSpeed2 { get; } = new("2) Bottom retract speed", null, "mm/min", 10, 5000, 5); + public static PrintParameterModifier RetractSpeed2 { get; } = new("2) Retract speed", null, "mm/min", 10, 5000, 5); - public static PrintParameterModifier BottomLightPWM { get; } = new ("Bottom light PWM", "UV LED power for bottom layers", "☀", 1, byte.MaxValue, 0); - public static PrintParameterModifier LightPWM { get; } = new ("Light PWM", "UV LED power for layers", "☀", 1, byte.MaxValue, 0); + public static PrintParameterModifier BottomLightPWM { get; } = new ("Bottom light PWM", "UV LED power for bottom layers", "☀", 1, byte.MaxValue, 5, 0); + public static PrintParameterModifier LightPWM { get; } = new ("Light PWM", "UV LED power for layers", "☀", 1, byte.MaxValue, 5, 0); /*public static PrintParameterModifier[] Parameters = { BottomLayerCount, @@ -240,6 +240,11 @@ namespace UVtools.Core.FileFormats /// public decimal Maximum { get; } + /// + /// Gets the incrementing value for the dropdown + /// + public double Increment { get; set; } = 1; + /// /// Gets the number of decimal plates /// @@ -268,13 +273,14 @@ namespace UVtools.Core.FileFormats #endregion #region Constructor - public PrintParameterModifier(string name, string description = null, string valueUnit = null, decimal minimum = 0, decimal maximum = 1000, byte decimalPlates = 2) + public PrintParameterModifier(string name, string description = null, string valueUnit = null, decimal minimum = 0, decimal maximum = 1000, double increment = 0.5, byte decimalPlates = 2) { Name = name; Description = description ?? $"Modify '{name}'"; ValueUnit = valueUnit ?? string.Empty; Minimum = minimum; Maximum = maximum; + Increment = decimalPlates == 0 ? Math.Max(1, increment) : increment; DecimalPlates = decimalPlates; } #endregion diff --git a/UVtools.Core/GCode/GCodeBuilder.cs b/UVtools.Core/GCode/GCodeBuilder.cs index 6081be0..4ee83cc 100644 --- a/UVtools.Core/GCode/GCodeBuilder.cs +++ b/UVtools.Core/GCode/GCodeBuilder.cs @@ -673,15 +673,15 @@ namespace UVtools.Core.GCode { AppendLiftMoveGx(lifts, retracts, waitAfterLift, 0, layer); } - else if (lastZPosition < layer.PositionZ) // Ensure Z is on correct position + else if (lastZPosition != layer.PositionZ) // Ensure Z is on correct position { switch (GCodePositioningType) { case GCodePositioningTypes.Absolute: - AppendMoveGx(layer.PositionZ, liftSpeed); + AppendMoveGx(layer.PositionZ, lastZPosition < layer.PositionZ ? Math.Max(liftSpeed, liftSpeed2) : Math.Max(retractSpeed, retractSpeed2)); break; case GCodePositioningTypes.Partial: - AppendMoveGx(Layer.RoundHeight(layer.PositionZ - lastZPosition), liftSpeed); + AppendMoveGx(Layer.RoundHeight(layer.PositionZ - lastZPosition), lastZPosition < layer.PositionZ ? Math.Max(liftSpeed, liftSpeed2) : Math.Max(retractSpeed, retractSpeed2)); break; } diff --git a/UVtools.Core/Operations/OperationEditParameters.cs b/UVtools.Core/Operations/OperationEditParameters.cs index 7e6e8f3..99d1b8a 100644 --- a/UVtools.Core/Operations/OperationEditParameters.cs +++ b/UVtools.Core/Operations/OperationEditParameters.cs @@ -22,7 +22,7 @@ namespace UVtools.Core.Operations private bool _propagateModificationsToLayers = true; private bool _perLayerOverride; private uint _setNumberOfLayer = 1; - private uint _skipNumberOfLayer = 0; + private uint _skipNumberOfLayer; #endregion @@ -92,6 +92,15 @@ namespace UVtools.Core.Operations sb.AppendLine("Nothing changed\nDo some changes or cancel the operation."); } + if (Modifiers.Contains(FileFormat.PrintParameterModifier.PositionZ) + && FileFormat.PrintParameterModifier.PositionZ.HasChanged + && _skipNumberOfLayer > 0 + && LayerRangeCount > 1 + && _setNumberOfLayer + _skipNumberOfLayer < LayerRangeCount) + { + sb.AppendLine("Can not change the PositionZ in layers with an active alternating pattern."); + } + return sb.ToString(); } @@ -156,18 +165,18 @@ namespace UVtools.Core.Operations protected override bool ExecuteInternally(OperationProgress progress) { - if (PerLayerOverride) + if (_perLayerOverride) { uint setLayers = 0; for (uint layerIndex = LayerIndexStart; layerIndex <= LayerIndexEnd; layerIndex++) { SlicerFile[layerIndex].SetValuesFromPrintParametersModifiers(Modifiers); - if (SkipNumberOfLayer <= 0) continue; + if (_skipNumberOfLayer == 0) continue; setLayers++; - if (setLayers >= SetNumberOfLayer) + if (setLayers >= _setNumberOfLayer) { setLayers = 0; - layerIndex += SkipNumberOfLayer; + layerIndex += _skipNumberOfLayer; } } diff --git a/UVtools.Core/Operations/OperationTimelapse.cs b/UVtools.Core/Operations/OperationTimelapse.cs index 084ea57..075bee4 100644 --- a/UVtools.Core/Operations/OperationTimelapse.cs +++ b/UVtools.Core/Operations/OperationTimelapse.cs @@ -105,11 +105,6 @@ namespace UVtools.Core.Operations #region Properties - /// - /// Gets the minimum possible - /// - public float MinimumPositionZ => Layer.RoundHeight(SlicerFile.PrintHeight + SlicerFile.LayerHeight); - public TimelapseRaiseMode RaiseMode { get => _raiseMode; @@ -178,6 +173,8 @@ namespace UVtools.Core.Operations set => RaiseAndSetIfChanged(ref _useCustomLift, value); } + public bool CanUseCustomLift => _useCustomLift && SlicerFile.CanUseLayerLiftHeight; + public decimal SlowLiftHeight { get => _slowLiftHeight; @@ -307,7 +304,7 @@ namespace UVtools.Core.Operations switch (_raiseMode) { case TimelapseRaiseMode.LiftHeight: - if (_useCustomLift) + if (CanUseCustomLift) { layer.LiftSpeed = (float)_liftSpeed; layer.RetractSpeed = (float)_retractSpeed; @@ -333,7 +330,7 @@ namespace UVtools.Core.Operations } } - if (SlicerFile.CanUseLayerLiftHeight2 && (layer.LiftHeight2 > 0 || _useCustomLift && _slowLiftHeight > 0)) // TSMC + if (SlicerFile.CanUseLayerLiftHeight2 && (layer.LiftHeight2 > 0 || CanUseCustomLift && _slowLiftHeight > 0)) // TSMC { layer.LiftHeight2 = Math.Max(0, (float)_raisePositionZ - layer.PositionZ - layer.LiftHeight); } @@ -375,37 +372,52 @@ namespace UVtools.Core.Operations RetractHeight2 = 0 }; - layer.SetNoDelays(); - - /*if (_useCustomLift) + if (CanUseCustomLift) { - layer.LiftSpeed = (float) _liftSpeed; - layer.RetractSpeed = (float) _retractSpeed; + layer.LiftSpeed = (float)_liftSpeed; + layer.RetractSpeed = (float)_retractSpeed; + + /*if (SlicerFile.CanUseLayerLiftHeight2) + { + layer.LiftHeight = (float)_slowLiftHeight; + }*/ if (SlicerFile.CanUseLayerLiftSpeed2) { - layer.LiftSpeed2 = (float) _liftSpeed2; + layer.LiftSpeed2 = (float)_liftSpeed2; } if (SlicerFile.CanUseLayerRetractSpeed2) { - layer.RetractSpeed2 = (float) _retractSpeed2; + layer.RetractSpeed2 = (float)_retractSpeed2; } - }*/ + } + + layer.SetNoDelays(); var layers = SlicerFile.ToList(); for (int i = 0; i < virtualLayers.Count; i++) { - /*var newLayer = layer.Clone(); - if (!_useCustomLift) + int insertIndex = (int)virtualLayers[i]; + SlicerFile[insertIndex].LiftHeightTotal = SlicerFile.SupportsGCode ? 0 : 0.1f; + + if (CanUseCustomLift) { - var intersectLayer = Math.Clamp(virtualLayers[i] + i, 0, SlicerFile.LastLayerIndex); - SlicerFile[intersectLayer].CopyLiftTo(newLayer); - // This layer does not require a lift procedure - newLayer.LiftHeightTotal = SlicerFile.SupportsGCode ? 0 : 0.1f; - newLayer.RetractHeight2 = 0; - }*/ - layers.Insert((int)(virtualLayers[i] + i), layer.Clone()); + SlicerFile[insertIndex].LiftSpeed = (float)_liftSpeed; + SlicerFile[insertIndex].RetractSpeed = (float)_retractSpeed; + + if (SlicerFile.CanUseLayerLiftSpeed2) + { + SlicerFile[insertIndex].LiftSpeed2 = (float)_retractSpeed2; + } + + if (SlicerFile.CanUseLayerRetractSpeed2) + { + SlicerFile[insertIndex].RetractSpeed2 = (float)_retractSpeed2; + } + } + + layers.Insert(insertIndex + i, layer.Clone()); } SlicerFile.SuppressRebuildPropertiesWork(() => SlicerFile.LayerManager.Layers = layers.ToArray()); } diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj index b020595..b0724ec 100644 --- a/UVtools.Core/UVtools.Core.csproj +++ b/UVtools.Core/UVtools.Core.csproj @@ -10,7 +10,7 @@ https://github.com/sn4k3/UVtools https://github.com/sn4k3/UVtools MSLA/DLP, file analysis, calibration, repair, conversion and manipulation - 2.28.0 + 2.28.1 Copyright © 2020 PTRTECH UVtools.png AnyCPU;x64 diff --git a/UVtools.WPF/Assets/Icons/terminal-16x16.png b/UVtools.WPF/Assets/Icons/terminal-16x16.png new file mode 100644 index 0000000..98f041d Binary files /dev/null and b/UVtools.WPF/Assets/Icons/terminal-16x16.png differ diff --git a/UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml.cs index 475edb0..69447da 100644 --- a/UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml.cs +++ b/UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml.cs @@ -62,7 +62,7 @@ namespace UVtools.WPF.Controls.Tools HorizontalAlignment = HorizontalAlignment.Stretch, Minimum = (double) modifier.Minimum, Maximum = (double) modifier.Maximum, - Increment = modifier.DecimalPlates == 0 ? 1 : 0.5, + Increment = modifier.Increment, Value = (double)modifier.NewValue, Tag = this, //Width = 100, @@ -70,7 +70,7 @@ namespace UVtools.WPF.Controls.Tools }; if (modifier.DecimalPlates > 0) { - NewValue.FormatString = "F02"; + NewValue.FormatString = $"F{modifier.DecimalPlates}"; } Unit = new TextBlock diff --git a/UVtools.WPF/Controls/Tools/ToolTimelapseControl.axaml b/UVtools.WPF/Controls/Tools/ToolTimelapseControl.axaml index edabb6f..57d9702 100644 --- a/UVtools.WPF/Controls/Tools/ToolTimelapseControl.axaml +++ b/UVtools.WPF/Controls/Tools/ToolTimelapseControl.axaml @@ -151,7 +151,6 @@ IsChecked="{Binding Operation.UseCustomLift}"> - @@ -162,7 +161,6 @@ ColumnDefinitions="Auto,10,210,5,Auto,5,210"> - @@ -172,6 +170,7 @@ VerticalAlignment="Center" ToolTip.Tip="The slow first lift sequence (TSMC). Use a low value or 0 to disable." + IsVisible="{Binding !Operation.IsVirtualLayerMode}" Text="Slow lift height:"/> + + + + + + + Text="(Not supported)"> + + + + + + + + + + + + + + Text="(Not supported)"> + + + + + + + MessageBoxGeneric(this Window window, string message, string title = null, - ButtonEnum buttons = ButtonEnum.Ok, Icon icon = Icon.None, bool topMost = false, WindowStartupLocation location = WindowStartupLocation.CenterOwner, Style style = Style.None) + ButtonEnum buttons = ButtonEnum.Ok, Icon icon = Icon.None, bool topMost = false, WindowStartupLocation location = WindowStartupLocation.CenterOwner) { var messageBoxStandardWindow = MessageBox.Avalonia.MessageBoxManager.GetMessageBoxStandardWindow( new MessageBoxStandardParams @@ -29,7 +29,6 @@ namespace UVtools.WPF.Extensions ContentTitle = title ?? window.Title, ContentMessage = message, Icon = icon, - Style = style, WindowIcon = new WindowIcon(App.GetAsset("/Assets/Icons/UVtools.ico")), WindowStartupLocation = location, CanResize = UserSettings.Instance.General.WindowsCanResize, @@ -42,17 +41,17 @@ namespace UVtools.WPF.Extensions return await messageBoxStandardWindow.ShowDialog(window); } - public static async Task MessageBoxInfo(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, bool topMost = false, Style style = Style.None) - => await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Information", buttons, Icon.Info, topMost, WindowStartupLocation.CenterOwner, style); + public static async Task MessageBoxInfo(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, bool topMost = false) + => await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Information", buttons, Icon.Info, topMost, WindowStartupLocation.CenterOwner); - public static async Task MessageBoxError(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, bool topMost = false, Style style = Style.None) - => await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Error", buttons, Icon.Error, topMost, WindowStartupLocation.CenterOwner, style); + public static async Task MessageBoxError(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, bool topMost = false) + => await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Error", buttons, Icon.Error, topMost, WindowStartupLocation.CenterOwner); - public static async Task MessageBoxQuestion(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.YesNo, bool topMost = false, Style style = Style.None) - => await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Question", buttons, Icon.Setting, topMost, WindowStartupLocation.CenterOwner, style); + public static async Task MessageBoxQuestion(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.YesNo, bool topMost = false) + => await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Question", buttons, Icon.Setting, topMost, WindowStartupLocation.CenterOwner); - public static async Task MessageBoxWaring(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, bool topMost = false, Style style = Style.None) - => await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Question", buttons, Icon.Warning, topMost, WindowStartupLocation.CenterOwner, style); + public static async Task MessageBoxWaring(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, bool topMost = false) + => await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Question", buttons, Icon.Warning, topMost, WindowStartupLocation.CenterOwner); public static void ShowDialogSync(this Window window, Window parent = null) diff --git a/UVtools.WPF/MainWindow.axaml b/UVtools.WPF/MainWindow.axaml index d141d39..9fff996 100644 --- a/UVtools.WPF/MainWindow.axaml +++ b/UVtools.WPF/MainWindow.axaml @@ -127,8 +127,19 @@ - - + + + + + + + { - ProcessFiles(e.Data.GetFileNames().ToArray()); + ProcessFiles(e.Data.GetFileNames()?.ToArray()); }); _menuFileSendTo = this.FindControl("MainMenu.File.SendTo"); @@ -1823,8 +1823,6 @@ namespace UVtools.WPF VisibleThumbnailIndex = 1; - RefreshProperties(); - UpdateTitle(); if (mat is not null) @@ -1904,7 +1902,7 @@ namespace UVtools.WPF $"Ratio: {xRatio}:{yRatio}\n", "Incorrect image ratio detected"); } - + RefreshProperties(); ResetDataContext(); ForceUpdateActualLayer(actualLayer.Clamp(actualLayer, SliderMaximumValue)); @@ -2234,6 +2232,11 @@ namespace UVtools.WPF } + public void OpenTerminal() + { + new TerminalWindow().Show(this); + } + #region Operations public async Task ShowRunOperation(Operation loadOperation) => diff --git a/UVtools.WPF/UVtools.WPF.csproj b/UVtools.WPF/UVtools.WPF.csproj index 013498f..052eca7 100644 --- a/UVtools.WPF/UVtools.WPF.csproj +++ b/UVtools.WPF/UVtools.WPF.csproj @@ -12,7 +12,7 @@ LICENSE https://github.com/sn4k3/UVtools Git - 2.28.0 + 2.28.1 AnyCPU;x64 UVtools.png README.md @@ -44,7 +44,7 @@ - + diff --git a/UVtools.WPF/Windows/TerminalWindow.axaml b/UVtools.WPF/Windows/TerminalWindow.axaml new file mode 100644 index 0000000..fe88998 --- /dev/null +++ b/UVtools.WPF/Windows/TerminalWindow.axaml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + +