From 3015a1d53fd7b68feea1529ad72effff91ced632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20Concei=C3=A7=C3=A3o?= Date: Mon, 28 Sep 2020 03:43:51 +0100 Subject: [PATCH] WPF progress --- CHANGELOG.md | 4 + README.md | 15 +- .../Operations/OperationEditParameters.cs | 31 ++- .../Operations/OperationLayerReHeight.cs | 8 +- .../Controls/Tools/CtrlToolLayerReHeight.cs | 13 +- UVtools.WPF/App.axaml.cs | 3 + .../ToolChangeResolutionControl.axaml.cs | 7 +- .../Tools/ToolEditParametersControl.axaml | 51 +++++ .../Tools/ToolEditParametersControl.axaml.cs | 183 ++++++++++++++++++ .../Tools/ToolLayerReHeightControl.axaml | 20 ++ .../Tools/ToolLayerReHeightControl.axaml.cs | 41 ++++ UVtools.WPF/Extensions/WindowExtensions.cs | 7 +- UVtools.WPF/MainWindow.axaml.cs | 18 +- UVtools.WPF/UVtools.WPF.csproj | 5 +- UVtools.WPF/Windows/ToolWindow.axaml | 20 +- UVtools.WPF/Windows/ToolWindow.axaml.cs | 19 ++ 16 files changed, 424 insertions(+), 21 deletions(-) create mode 100644 UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml create mode 100644 UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml.cs create mode 100644 UVtools.WPF/Controls/Tools/ToolLayerReHeightControl.axaml create mode 100644 UVtools.WPF/Controls/Tools/ToolLayerReHeightControl.axaml.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index ac1490d..19572f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,13 +6,17 @@ * (Add) Themes support * (Add) Fullscreen support (F11) * (Change) GUI was rewritten from Windows Forms to WPF Avalonia, C# +* (Improvement) Edit print parameters: Dedicated reset button hides when value is unchanged +* (Improvement) Edit print parameters: Show changes on confirm dialog * (Improvement) More detailed descriptions on error messages * (Improvement) GUI is now scalable +* (Fix) Some islands wont remove from list select select many and click remove * (Fix) Many bug found and fixed during convertion ## ??/09/2020 - v0.8.2.5 * (Fix) Extract: Use trail zeros to layer filenames +* (Improvement) Edit print parameters: Show changes on confirm dialog ## 22/09/2020 - v0.8.2.4 diff --git a/README.md b/README.md index 5bdc404..9d1ffe5 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,7 @@ But also, i need victims for test subject. Proceed at your own risk! * Phrozen Shuffle 4K * Phrozen Sonic * Phrozen Sonic Mini +* Phrozen Sonic Mini 4K * Phrozen Transform * Kelant S400 * Wanhao D7 @@ -146,10 +147,20 @@ After some tests without failure you can increase your confidence and ignore thi 1. 2 GB RAM or higher -### Mac and Linux +### Linux -(Not supported yet) +**Ubuntu** + +```bash +wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb +sudo dpkg -i packages-microsoft-prod.deb +rm packages-microsoft-prod.deb +sudo apt-get update +sudo apt-get install -y apt-transport-https +sudo apt-get update +sudo apt-get install -y libjpeg-dev libpng-dev libgeotiff-dev libdc1394-22 libavcodec-dev libavformat-dev libswscale-dev libopenexr24 libtbb-dev dotnet-runtime-3.1 +``` ## How to use diff --git a/UVtools.Core/Operations/OperationEditParameters.cs b/UVtools.Core/Operations/OperationEditParameters.cs index 77e08c0..968c552 100644 --- a/UVtools.Core/Operations/OperationEditParameters.cs +++ b/UVtools.Core/Operations/OperationEditParameters.cs @@ -6,7 +6,10 @@ * of this license document, but changing it is not allowed. */ +using System.Linq; +using System.Text; using UVtools.Core.FileFormats; +using UVtools.Core.Objects; namespace UVtools.Core.Operations { @@ -21,12 +24,38 @@ namespace UVtools.Core.Operations public override string Description => "Edits the available print parameters."; - public override string ConfirmationText => "commit print parameter changes?"; + public override string ConfirmationText + { + get + { + var sb = new StringBuilder(); + foreach (var modifier in Modifiers) + { + if(!modifier.HasChanged) continue; + sb.AppendLine($"{modifier.Name}: {modifier.OldValue} » {modifier.NewValue}"); + } + return $"commit print parameter changes?\n{sb}"; + } + } public override string ProgressTitle => null; public override string ProgressAction => null; + public override StringTag Validate(params object[] parameters) + { + var sb = new StringBuilder(); + var changed = Modifiers.Any(modifier => modifier.HasChanged); + + if (!changed) + { + sb.AppendLine("Nothing changed\nDo some changes or cancel the operation."); + } + + + return new StringTag(sb.ToString()); + } + public FileFormat.PrintParameterModifier[] Modifiers { get; set; } public OperationEditParameters() diff --git a/UVtools.Core/Operations/OperationLayerReHeight.cs b/UVtools.Core/Operations/OperationLayerReHeight.cs index a7f4f8b..f5550c1 100644 --- a/UVtools.Core/Operations/OperationLayerReHeight.cs +++ b/UVtools.Core/Operations/OperationLayerReHeight.cs @@ -16,6 +16,8 @@ namespace UVtools.Core.Operations { public sealed class OperationLayerReHeight : Operation { + private OperationLayerReHeightItem _item; + #region Overrides public override Enumerations.LayerRangeSelection LayerRangeSelection => Enumerations.LayerRangeSelection.None; @@ -51,7 +53,11 @@ namespace UVtools.Core.Operations #endregion - public OperationLayerReHeightItem Item { get; set; } + public OperationLayerReHeightItem Item + { + get => _item; + set => RaiseAndSetIfChanged(ref _item, value); + } public static OperationLayerReHeightItem[] GetItems(uint layerCount, decimal layerHeight) diff --git a/UVtools.GUI/Controls/Tools/CtrlToolLayerReHeight.cs b/UVtools.GUI/Controls/Tools/CtrlToolLayerReHeight.cs index 4cb552d..656e87a 100644 --- a/UVtools.GUI/Controls/Tools/CtrlToolLayerReHeight.cs +++ b/UVtools.GUI/Controls/Tools/CtrlToolLayerReHeight.cs @@ -17,6 +17,10 @@ namespace UVtools.GUI.Controls.Tools { public OperationLayerReHeight Operation { get; } + public OperationLayerReHeight.OperationLayerReHeightItem[] Presets { get; } = OperationLayerReHeight.GetItems( + Program.SlicerFile.LayerCount, + (decimal) Program.SlicerFile.LayerHeight); + public CtrlToolLayerReHeight() { @@ -25,13 +29,10 @@ namespace UVtools.GUI.Controls.Tools SetOperation(Operation); lbCurrent.Text = $"Current layers: {Program.SlicerFile.LayerCount} at {Program.SlicerFile.LayerHeight}mm"; - - var items = OperationLayerReHeight.GetItems(Program.SlicerFile.LayerCount, - (decimal) Program.SlicerFile.LayerHeight); - - if (items.Length > 0) + + if (Presets.Length > 0) { - cbMultiplier.Items.AddRange(items); + cbMultiplier.Items.AddRange(Presets); cbMultiplier.SelectedIndex = 0; } else diff --git a/UVtools.WPF/App.axaml.cs b/UVtools.WPF/App.axaml.cs index 7faf6d8..0e99fdb 100644 --- a/UVtools.WPF/App.axaml.cs +++ b/UVtools.WPF/App.axaml.cs @@ -16,6 +16,7 @@ using System.Threading; using Avalonia; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Markup.Xaml; +using Avalonia.Media.Imaging; using Avalonia.Platform; using Avalonia.ThemeManager; using Emgu.CV; @@ -159,6 +160,8 @@ namespace UVtools.WPF return res; } + public static Bitmap GetBitmapFromAsset(string url) => new Bitmap(GetAsset(url)); + #endregion } } diff --git a/UVtools.WPF/Controls/Tools/ToolChangeResolutionControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolChangeResolutionControl.axaml.cs index 6254a2b..5ddac9a 100644 --- a/UVtools.WPF/Controls/Tools/ToolChangeResolutionControl.axaml.cs +++ b/UVtools.WPF/Controls/Tools/ToolChangeResolutionControl.axaml.cs @@ -1,4 +1,5 @@ -using System.Timers; +using System.Diagnostics; +using System.Timers; using Avalonia.Markup.Xaml; using UVtools.Core.Operations; @@ -18,7 +19,9 @@ namespace UVtools.WPF.Controls.Tools if (_selectedPresetItem is null || _selectedPresetItem.IsEmpty) return; Operation.NewResolutionX = _selectedPresetItem.ResolutionX; Operation.NewResolutionY = _selectedPresetItem.ResolutionY; - Timer timer = new Timer(50); + + //SelectedPresetItem = null; + Timer timer = new Timer(1); timer.Elapsed += (sender, args) => { SelectedPresetItem = null; diff --git a/UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml b/UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml new file mode 100644 index 0000000..35f4e0c --- /dev/null +++ b/UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml @@ -0,0 +1,51 @@ + + + + + + + + + + + + diff --git a/UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml.cs new file mode 100644 index 0000000..5d2dcde --- /dev/null +++ b/UVtools.WPF/Controls/Tools/ToolEditParametersControl.axaml.cs @@ -0,0 +1,183 @@ +using System; +using System.Globalization; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Interactivity; +using Avalonia.Layout; +using Avalonia.Markup.Xaml; +using Avalonia.Media.Imaging; +using UVtools.Core.Extensions; +using UVtools.Core.FileFormats; +using UVtools.Core.Operations; +using UVtools.WPF.Windows; + +namespace UVtools.WPF.Controls.Tools +{ + public class ToolEditParametersControl : ToolControl + { + public OperationEditParameters Operation { get; } + + public RowControl[] RowControls; + + public sealed class RowControl + { + public FileFormat.PrintParameterModifier Modifier { get; } + + public TextBlock Name { get; } + public TextBlock OldValue { get; } + public NumericUpDown NewValue { get; } + public TextBlock Unit { get; } + public Button ResetButton { get; } + + public RowControl(FileFormat.PrintParameterModifier modifier) + { + Modifier = modifier; + + modifier.NewValue = modifier.OldValue.Clamp(modifier.Minimum, modifier.Maximum); + + Name = new TextBlock + { + Text = $"{modifier.Name}:", + VerticalAlignment = VerticalAlignment.Center, + Padding = new Thickness(15, 0), + Tag = this, + }; + + OldValue = new TextBlock + { + Text = modifier.OldValue.ToString(CultureInfo.InvariantCulture), + VerticalAlignment = VerticalAlignment.Center, + HorizontalAlignment = HorizontalAlignment.Center, + //Padding = new Thickness(15, 0), + Tag = this + }; + + NewValue = new NumericUpDown + { + //DecimalPlaces = modifier.DecimalPlates, + VerticalAlignment = VerticalAlignment.Center, + Minimum = (double) modifier.Minimum, + Maximum = (double) modifier.Maximum, + Increment = modifier.DecimalPlates == 0 ? 1 : 0.01, + Value = (double)modifier.NewValue, + Tag = this, + Width = 100, + }; + if (modifier.DecimalPlates > 0) + { + NewValue.FormatString = "{0:#,0.00}"; + } + + Unit = new TextBlock + { + Text = modifier.ValueUnit, + VerticalAlignment = VerticalAlignment.Center, + Padding = new Thickness(10, 0, 15, 0), + Tag = this + }; + + ResetButton = new Button + { + IsVisible = false, + IsEnabled = false, + VerticalAlignment = VerticalAlignment.Center, + Tag = this, + Padding = new Thickness(5), + Content = new Image {Source = App.GetBitmapFromAsset("/Assets/Icons/undo-16x16.png")} + }; + ResetButton.Click += ResetButtonOnClick; + NewValue.ValueChanged += NewValueOnValueChanged; + } + + private void NewValueOnValueChanged(object? sender, NumericUpDownValueChangedEventArgs e) + { + Modifier.NewValue = (decimal) NewValue.Value; + ResetButton.IsVisible = ResetButton.IsEnabled = Modifier.HasChanged; + } + + private void ResetButtonOnClick(object? sender, RoutedEventArgs e) + { + NewValue.Value = (double) Modifier.OldValue; + NewValue.Focus(); + } + } + + public ToolEditParametersControl() + { + InitializeComponent(); + + App.SlicerFile.RefreshPrintParametersModifiersValues(); + BaseOperation = Operation = new OperationEditParameters(App.SlicerFile.PrintParameterModifiers); + + if (Operation.Modifiers is null || Operation.Modifiers.Length == 0) + { + CanRun = false; + return; + } + + Grid grid = this.FindControl("grid"); + + int rowIndex = 1; + RowControls = new RowControl[Operation.Modifiers.Length]; + //table.RowCount = Operation.Modifiers.Length+1; + foreach (var modifier in Operation.Modifiers) + { + grid.RowDefinitions.Add(new RowDefinition()); + byte column = 0; + + var rowControl = new RowControl(modifier); + grid.Children.Add(rowControl.Name); + grid.Children.Add(rowControl.OldValue); + grid.Children.Add(rowControl.NewValue); + grid.Children.Add(rowControl.Unit); + grid.Children.Add(rowControl.ResetButton); + Grid.SetRow(rowControl.Name, rowIndex); + Grid.SetColumn(rowControl.Name, column++); + + Grid.SetRow(rowControl.OldValue, rowIndex); + Grid.SetColumn(rowControl.OldValue, column++); + + Grid.SetRow(rowControl.NewValue, rowIndex); + Grid.SetColumn(rowControl.NewValue, column++); + + Grid.SetRow(rowControl.Unit, rowIndex); + Grid.SetColumn(rowControl.Unit, column++); + + Grid.SetRow(rowControl.ResetButton, rowIndex); + Grid.SetColumn(rowControl.ResetButton, column++); + /*table.Controls.Add(rowControl.Name, column++, rowIndex); + table.Controls.Add(rowControl.OldValue, column++, rowIndex); + table.Controls.Add(rowControl.NewValue, column++, rowIndex); + table.Controls.Add(rowControl.Unit, column++, rowIndex); + table.Controls.Add(rowControl.ResetButton, column++, rowIndex); + */ + RowControls[rowIndex - 1] = rowControl; + + rowIndex++; + } + + DataContext = this; + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + + public override void Callback(ToolWindow.Callbacks callback) + { + switch (callback) + { + case ToolWindow.Callbacks.Init: + ParentWindow.IsButton1Visible = true; + break; + case ToolWindow.Callbacks.Button1: + foreach (var rowControl in RowControls) + { + rowControl.NewValue.Value = (double) rowControl.Modifier.OldValue; + } + break; + } + } + } +} diff --git a/UVtools.WPF/Controls/Tools/ToolLayerReHeightControl.axaml b/UVtools.WPF/Controls/Tools/ToolLayerReHeightControl.axaml new file mode 100644 index 0000000..21c0e98 --- /dev/null +++ b/UVtools.WPF/Controls/Tools/ToolLayerReHeightControl.axaml @@ -0,0 +1,20 @@ + + + + + + + + + + + diff --git a/UVtools.WPF/Controls/Tools/ToolLayerReHeightControl.axaml.cs b/UVtools.WPF/Controls/Tools/ToolLayerReHeightControl.axaml.cs new file mode 100644 index 0000000..aa96ac7 --- /dev/null +++ b/UVtools.WPF/Controls/Tools/ToolLayerReHeightControl.axaml.cs @@ -0,0 +1,41 @@ +using Avalonia.Markup.Xaml; +using UVtools.Core.Operations; +using UVtools.WPF.Extensions; + +namespace UVtools.WPF.Controls.Tools +{ + public class ToolLayerReHeightControl : ToolControl + { + public OperationLayerReHeight Operation { get; } + + public OperationLayerReHeight.OperationLayerReHeightItem[] Presets { get; } = OperationLayerReHeight.GetItems( + App.SlicerFile.LayerCount, + (decimal)App.SlicerFile.LayerHeight); + + public string CurrentLayers => $"Current layers: {App.SlicerFile.LayerCount} at {App.SlicerFile.LayerHeight}mm"; + + public ToolLayerReHeightControl() + { + InitializeComponent(); + BaseOperation = Operation = new OperationLayerReHeight(); + + if (Presets.Length == 0) + { + App.MainWindow.MessageBoxInfo("No valid configuration to be able to re-height, closing this tool now.", "Not possible to re-height"); + CanRun = false; + } + else + { + Operation.Item = Presets[0]; + } + + + DataContext = this; + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + } +} diff --git a/UVtools.WPF/Extensions/WindowExtensions.cs b/UVtools.WPF/Extensions/WindowExtensions.cs index 1e1f157..3a8ddd9 100644 --- a/UVtools.WPF/Extensions/WindowExtensions.cs +++ b/UVtools.WPF/Extensions/WindowExtensions.cs @@ -26,6 +26,7 @@ namespace UVtools.WPF.Extensions ContentMessage = message, Icon = icon, Style = style, + WindowIcon = new WindowIcon(App.GetAsset("/Assets/Icons/UVtools.ico")), WindowStartupLocation = location, CanResize = false }); @@ -34,13 +35,13 @@ namespace UVtools.WPF.Extensions } public static async Task MessageBoxInfo(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, Style style = Style.None) - => await window.MessageBoxGeneric(message, title ?? $"{window.Title} Information", buttons, Icon.Info, WindowStartupLocation.CenterOwner, style); + => await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Information", buttons, Icon.Info, WindowStartupLocation.CenterOwner, style); public static async Task MessageBoxError(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.Ok, Style style = Style.None) - => await window.MessageBoxGeneric(message, title ?? $"{window.Title} Error", buttons, Icon.Error, WindowStartupLocation.CenterOwner, style); + => await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Error", buttons, Icon.Error, WindowStartupLocation.CenterOwner, style); public static async Task MessageBoxQuestion(this Window window, string message, string title = null, ButtonEnum buttons = ButtonEnum.YesNo, Style style = Style.None) - => await window.MessageBoxGeneric(message, title ?? $"{window.Title} Question", buttons, Icon.Setting, WindowStartupLocation.CenterOwner, style); + => await window.MessageBoxGeneric(message, title ?? $"{window.Title} - Question", buttons, Icon.Setting, WindowStartupLocation.CenterOwner, style); public static void ResetDataContext(this Window window) diff --git a/UVtools.WPF/MainWindow.axaml.cs b/UVtools.WPF/MainWindow.axaml.cs index 493c684..c18a6af 100644 --- a/UVtools.WPF/MainWindow.axaml.cs +++ b/UVtools.WPF/MainWindow.axaml.cs @@ -44,6 +44,7 @@ using Bitmap = Avalonia.Media.Imaging.Bitmap; using Color = UVtools.WPF.Structures.Color; using Helpers = UVtools.WPF.Controls.Helpers; using Point = Avalonia.Point; +using Timer = System.Timers.Timer; namespace UVtools.WPF { @@ -237,6 +238,7 @@ namespace UVtools.WPF #region Members public Stopwatch LastStopWatch; + private Timer _layerNavigationTooltipTimer = new Timer(1){AutoReset = false}; private uint _actualLayer; private bool _isGUIEnabled = true; private uint _savesCount; @@ -1137,9 +1139,10 @@ namespace UVtools.WPF RaisePropertyChanged(nameof(CanGoDown)); RaisePropertyChanged(nameof(CanGoUp)); RaisePropertyChanged(nameof(ActualLayerTooltip)); - RaisePropertyChanged(nameof(LayerNavigationTooltipMargin)); + //RaisePropertyChanged(nameof(LayerNavigationTooltipMargin)); RaisePropertyChanged(nameof(LayerPixelCountStr)); RaisePropertyChanged(nameof(LayerBoundsStr)); + _layerNavigationTooltipTimer.Start(); } public Thickness LayerNavigationTooltipMargin @@ -1219,7 +1222,13 @@ namespace UVtools.WPF { ProcessFiles(e.Data.GetFileNames().ToArray()); }); - + + _layerNavigationTooltipTimer.Elapsed += (sender, args) => + { + Dispatcher.UIThread.InvokeAsync(() => RaisePropertyChanged(nameof(LayerNavigationTooltipMargin))); + }; + + UpdateTitle(); if (Settings.General.StartMaximized) @@ -1231,6 +1240,10 @@ namespace UVtools.WPF ProcessFiles(Program.Args); } + private void _layerSliderTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) + { + throw new NotImplementedException(); + } private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) { @@ -2407,6 +2420,7 @@ namespace UVtools.WPF }*/ SlicerFile.SetValuesFromPrintParametersModifiers(); RefreshProperties(); + ResetDataContext(); CanSave = true; diff --git a/UVtools.WPF/UVtools.WPF.csproj b/UVtools.WPF/UVtools.WPF.csproj index aec357e..9128a3a 100644 --- a/UVtools.WPF/UVtools.WPF.csproj +++ b/UVtools.WPF/UVtools.WPF.csproj @@ -29,7 +29,7 @@ - + @@ -201,10 +201,13 @@ PreserveNewest + + True + diff --git a/UVtools.WPF/Windows/ToolWindow.axaml b/UVtools.WPF/Windows/ToolWindow.axaml index dd213ae..bd23100 100644 --- a/UVtools.WPF/Windows/ToolWindow.axaml +++ b/UVtools.WPF/Windows/ToolWindow.axaml @@ -206,11 +206,25 @@ - - + + - +