Browse Source

Fix #341 and #340: Improve percentage calculation code

Equbuxu 3 years ago
parent
commit
6d07eb60f1

+ 1 - 1
PixiEditor/Helpers/Converters/ToolSizeToIntConverter.cs

@@ -31,4 +31,4 @@ namespace PixiEditor.Helpers.Converters
             return int.Parse(match.Groups[0].ValueSpan);
             return int.Parse(match.Groups[0].ValueSpan);
         }
         }
     }
     }
-}
+}

+ 10 - 7
PixiEditor/Helpers/SizeCalculator.cs

@@ -1,17 +1,20 @@
-namespace PixiEditor.Helpers
+using System;
+
+namespace PixiEditor.Helpers
 {
 {
     public static class SizeCalculator
     public static class SizeCalculator
     {
     {
-        public static System.Drawing.Size CalcAbsoluteFromPercentage(int percentage, System.Drawing.Size currentSize)
+        public static System.Drawing.Size CalcAbsoluteFromPercentage(float percentage, System.Drawing.Size currentSize)
         {
         {
-            var percFactor = ((float)percentage) / 100f;
-            var newWidth = currentSize.Width * percFactor;
-            var newHeight = currentSize.Height * percFactor;
-            return new System.Drawing.Size((int)newWidth, (int)newHeight);
+            float percFactor = percentage / 100f;
+            float newWidth = currentSize.Width * percFactor;
+            float newHeight = currentSize.Height * percFactor;
+            return new System.Drawing.Size((int)MathF.Round(newWidth), (int)MathF.Round(newHeight));
         }
         }
+
         public static int CalcPercentageFromAbsolute(int initAbsoluteSize, int currentAbsoluteSize)
         public static int CalcPercentageFromAbsolute(int initAbsoluteSize, int currentAbsoluteSize)
         {
         {
-            return (int)((float)currentAbsoluteSize*100) / initAbsoluteSize;
+            return (int)((float)currentAbsoluteSize * 100) / initAbsoluteSize;
         }
         }
     }
     }
 }
 }

+ 1 - 2
PixiEditor/Models/Constants.cs

@@ -6,8 +6,7 @@
         public const int MaxPreviewWidth = 2048;
         public const int MaxPreviewWidth = 2048;
         public const int MaxPreviewHeight = 2048;
         public const int MaxPreviewHeight = 2048;
 
 
-        public const int MaxCanvasWidth = 9999;
-        public const int MaxCanvasHeight = 9999;
+        public const int MaxCanvasSize = 9999;
 
 
         public const string NativeExtensionNoDot = "pixi";
         public const string NativeExtensionNoDot = "pixi";
         public const string NativeExtension = "." + NativeExtensionNoDot;
         public const string NativeExtension = "." + NativeExtensionNoDot;

+ 2 - 2
PixiEditor/Views/UserControls/SizeInput.xaml

@@ -42,7 +42,7 @@
                      x:Name="textBox"
                      x:Name="textBox"
                      Text="{Binding Size, ElementName=uc, Converter={converters:ToolSizeToIntConverter}}"
                      Text="{Binding Size, ElementName=uc, Converter={converters:ToolSizeToIntConverter}}"
                      d:Text="22"
                      d:Text="22"
-                     MaxLength = "4"
+                     MaxLength = "6"
                      >
                      >
                 <i:Interaction.Behaviors>
                 <i:Interaction.Behaviors>
                     <behaviors:GlobalShortcutFocusBehavior/>
                     <behaviors:GlobalShortcutFocusBehavior/>
@@ -54,7 +54,7 @@
             </TextBox>
             </TextBox>
             <Grid Grid.Column="1" Background="{Binding BorderBrush, ElementName=border}"
             <Grid Grid.Column="1" Background="{Binding BorderBrush, ElementName=border}"
                   d:Background="{StaticResource BrighterAccentColor}"/>
                   d:Background="{StaticResource BrighterAccentColor}"/>
-                      <TextBlock Text="{Binding Unit, ElementName=uc, Converter={converters:EnumToStringConverter}}" TextAlignment="Right"
+            <TextBlock Text="{Binding Unit, ElementName=uc, Converter={converters:EnumToStringConverter}}" TextAlignment="Right"
                        Grid.Column="2" Margin="5,0" VerticalAlignment="Center" d:Text="px"
                        Grid.Column="2" Margin="5,0" VerticalAlignment="Center" d:Text="px"
                        
                        
                        />
                        />

+ 2 - 1
PixiEditor/Views/UserControls/SizePicker.xaml

@@ -57,10 +57,11 @@
                                      Size="{Binding Path=ChosenPercentageSize, ElementName=uc, Mode=TwoWay}"
                                      Size="{Binding Path=ChosenPercentageSize, ElementName=uc, Mode=TwoWay}"
                                      Unit="Percentage"
                                      Unit="Percentage"
                                      Margin="-10,0,0,0"
                                      Margin="-10,0,0,0"
+                                     MaxSize="999900"
                                      Width="80">
                                      Width="80">
                     <i:Interaction.Triggers>
                     <i:Interaction.Triggers>
                         <i:EventTrigger EventName="LostFocus">
                         <i:EventTrigger EventName="LostFocus">
-                            <i:InvokeCommandAction Command="{Binding ElementName=uc, Path=WidthLostFocusCommand}"/>
+                            <i:InvokeCommandAction Command="{Binding ElementName=uc, Path=PercentageLostFocusCommand}"/>
                         </i:EventTrigger>
                         </i:EventTrigger>
                     </i:Interaction.Triggers>
                     </i:Interaction.Triggers>
                 </local:SizeInput>
                 </local:SizeInput>

+ 45 - 21
PixiEditor/Views/UserControls/SizePicker.xaml.cs

@@ -22,7 +22,7 @@ namespace PixiEditor.Views
             DependencyProperty.Register(nameof(ChosenHeight), typeof(int), typeof(SizePicker), new PropertyMetadata(1));
             DependencyProperty.Register(nameof(ChosenHeight), typeof(int), typeof(SizePicker), new PropertyMetadata(1));
 
 
         public static readonly DependencyProperty ChosenPercentageSizeProperty =
         public static readonly DependencyProperty ChosenPercentageSizeProperty =
-            DependencyProperty.Register(nameof(ChosenPercentageSize), typeof(int), typeof(SizePicker), new PropertyMetadata(1, InputSizeChanged));
+            DependencyProperty.Register(nameof(ChosenPercentageSize), typeof(float), typeof(SizePicker), new PropertyMetadata(100f));
 
 
         public static readonly DependencyProperty SelectedUnitProperty =
         public static readonly DependencyProperty SelectedUnitProperty =
             DependencyProperty.Register(nameof(SelectedUnit), typeof(SizeUnit), typeof(SizePicker), new PropertyMetadata(SizeUnit.Pixel));
             DependencyProperty.Register(nameof(SelectedUnit), typeof(SizeUnit), typeof(SizePicker), new PropertyMetadata(SizeUnit.Pixel));
@@ -32,24 +32,6 @@ namespace PixiEditor.Views
 
 
         System.Drawing.Size? initSize = null;
         System.Drawing.Size? initSize = null;
 
 
-        private static void InputSizeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
-        {
-            var sizePicker = d as SizePicker;
-            if (!sizePicker.initSize.HasValue)
-                return;
-
-            var newValue = (int)e.NewValue;
-            var newSize = SizeCalculator.CalcAbsoluteFromPercentage(newValue, sizePicker.initSize.Value);
-            if (newSize.Width > Constants.MaxCanvasWidth || newSize.Height > Constants.MaxCanvasHeight)
-            {
-                newSize = new System.Drawing.Size(Constants.MaxCanvasWidth, Constants.MaxCanvasHeight);
-                d.SetValue(ChosenPercentageSizeProperty, SizeCalculator.CalcPercentageFromAbsolute(sizePicker.initSize.Value.Width, newSize.Width));
-            }
-
-            d.SetValue(ChosenWidthProperty, newSize.Width);
-            d.SetValue(ChosenHeightProperty, newSize.Height);
-        }
-
         public bool EditingEnabled
         public bool EditingEnabled
         {
         {
             get => (bool)GetValue(EditingEnabledProperty);
             get => (bool)GetValue(EditingEnabledProperty);
@@ -68,9 +50,9 @@ namespace PixiEditor.Views
             set => SetValue(ChosenHeightProperty, value);
             set => SetValue(ChosenHeightProperty, value);
         }
         }
 
 
-        public int ChosenPercentageSize
+        public float ChosenPercentageSize
         {
         {
-            get => (int)GetValue(ChosenPercentageSizeProperty);
+            get => (float)GetValue(ChosenPercentageSizeProperty);
             set => SetValue(ChosenPercentageSizeProperty, value);
             set => SetValue(ChosenPercentageSizeProperty, value);
         }
         }
 
 
@@ -95,12 +77,14 @@ namespace PixiEditor.Views
         public RelayCommand LoadedCommand { get; private set; }
         public RelayCommand LoadedCommand { get; private set; }
         public RelayCommand WidthLostFocusCommand { get; private set; }
         public RelayCommand WidthLostFocusCommand { get; private set; }
         public RelayCommand HeightLostFocusCommand { get; private set; }
         public RelayCommand HeightLostFocusCommand { get; private set; }
+        public RelayCommand PercentageLostFocusCommand { get; private set; }
 
 
         public SizePicker()
         public SizePicker()
         {
         {
             LoadedCommand = new(AfterLoaded);
             LoadedCommand = new(AfterLoaded);
             WidthLostFocusCommand = new(WidthLostFocus);
             WidthLostFocusCommand = new(WidthLostFocus);
             HeightLostFocusCommand = new(HeightLostFocus);
             HeightLostFocusCommand = new(HeightLostFocus);
+            PercentageLostFocusCommand = new(PercentageLostFocus);
             InitializeComponent();
             InitializeComponent();
         }
         }
 
 
@@ -118,6 +102,46 @@ namespace PixiEditor.Views
         private void WidthLostFocus(object param) => OnSizeUpdate(true);
         private void WidthLostFocus(object param) => OnSizeUpdate(true);
         private void HeightLostFocus(object param) => OnSizeUpdate(false);
         private void HeightLostFocus(object param) => OnSizeUpdate(false);
 
 
+        private void PercentageLostFocus(object param)
+        {
+            if (!initSize.HasValue)
+                return;
+
+            float targetPercentage = GetTargetPercentage(initSize.Value, ChosenPercentageSize);
+            var newSize = SizeCalculator.CalcAbsoluteFromPercentage(targetPercentage, initSize.Value);
+
+            //this shouldn't ever be necessary but just in case
+            newSize.Width = Math.Clamp(newSize.Width, 1, Constants.MaxCanvasSize);
+            newSize.Height = Math.Clamp(newSize.Height, 1, Constants.MaxCanvasSize);
+
+            ChosenPercentageSize = targetPercentage;
+            ChosenWidth = newSize.Width;
+            ChosenHeight = newSize.Height;
+        }
+
+        private static float GetTargetPercentage(System.Drawing.Size initSize, float desiredPercentage)
+        {
+            var potentialSize = SizeCalculator.CalcAbsoluteFromPercentage(desiredPercentage, initSize);
+            // all good
+            if (potentialSize.Width > 0 && potentialSize.Height > 0 && potentialSize.Width <= Constants.MaxCanvasSize && potentialSize.Height <= Constants.MaxCanvasSize)
+                return desiredPercentage;
+
+            // canvas too small
+            if (potentialSize.Width <= 0 || potentialSize.Height <= 0)
+            {
+                if (potentialSize.Width < potentialSize.Height)
+                    return 100f / initSize.Width;
+                else
+                    return 100f / initSize.Height;
+            }
+
+            // canvas too big
+            if (potentialSize.Width > potentialSize.Height)
+                return Constants.MaxCanvasSize * 100f / initSize.Width;
+            else
+                return Constants.MaxCanvasSize * 100f / initSize.Height;
+        }
+
         private void OnSizeUpdate(bool widthUpdated)
         private void OnSizeUpdate(bool widthUpdated)
         {
         {
             if (!initSize.HasValue || !PreserveAspectRatio)
             if (!initSize.HasValue || !PreserveAspectRatio)