Browse Source

Enable/Disable preserve aspect ratio based on control and simplify aspect ratio logic

Equbuxu 3 years ago
parent
commit
28552acc39

+ 1 - 0
PixiEditor/Views/Dialogs/NewFilePopup.xaml

@@ -41,6 +41,7 @@
         <StackPanel HorizontalAlignment="Center" Margin="0,60,0,0" Background="{StaticResource MainColor}"
         <StackPanel HorizontalAlignment="Center" Margin="0,60,0,0" Background="{StaticResource MainColor}"
                         VerticalAlignment="Top" Grid.Row="1" Width="350" Height="150">
                         VerticalAlignment="Top" Grid.Row="1" Width="350" Height="150">
             <local:SizePicker Margin="0,20" HorizontalAlignment="Center" Height="110"
             <local:SizePicker Margin="0,20" HorizontalAlignment="Center" Height="110"
+                              PreserveAspectRatio="False"
                               ChosenHeight="{Binding FileHeight, Mode=TwoWay, ElementName=newFilePopup}"
                               ChosenHeight="{Binding FileHeight, Mode=TwoWay, ElementName=newFilePopup}"
                               ChosenWidth="{Binding FileWidth, Mode=TwoWay, ElementName=newFilePopup}" 
                               ChosenWidth="{Binding FileWidth, Mode=TwoWay, ElementName=newFilePopup}" 
                               x:Name="sizePicker"/>
                               x:Name="sizePicker"/>

+ 0 - 35
PixiEditor/Views/Dialogs/PopupTemplate.xaml

@@ -1,35 +0,0 @@
-<Window x:Class="PixiEditor.Views.PopupTemplate"
-        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
-        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
-        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
-        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
-        xmlns:local="clr-namespace:PixiEditor.Views"
-        mc:Ignorable="d" BorderBrush="Black" BorderThickness="1"
-        Title="ResizeDocumentPopup" WindowStartupLocation="CenterScreen" Height="200" Width="400" WindowStyle="None">
-
-    <WindowChrome.WindowChrome>
-        <WindowChrome CaptionHeight="32"  GlassFrameThickness="0.1"
-                      ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
-    </WindowChrome.WindowChrome>
-
-    <Window.CommandBindings>
-        <CommandBinding Command="{x:Static SystemCommands.CloseWindowCommand}" CanExecute="CommandBinding_CanExecute"
-                        Executed="CommandBinding_Executed_Close" />
-    </Window.CommandBindings>
-
-    <Grid Background="{StaticResource AccentColor}">
-        <Grid.RowDefinitions>
-            <RowDefinition Height="35" />
-            <RowDefinition />
-        </Grid.RowDefinitions>
-
-        <DockPanel Grid.Row="0" Background="{StaticResource MainColor}">
-            <Button DockPanel.Dock="Right" HorizontalAlignment="Right" Style="{StaticResource CloseButtonStyle}"
-                    WindowChrome.IsHitTestVisibleInChrome="True" ToolTip="Close"
-                    Command="{x:Static SystemCommands.CloseWindowCommand}" />
-        </DockPanel>
-        <Button Grid.Row="1" Height="30" Width="60" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="10"
-                Style="{StaticResource DarkRoundButton}" Content="OK" Command="{Binding OkCommand}" IsDefault="True"
-                CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" />
-    </Grid>
-</Window>

+ 0 - 26
PixiEditor/Views/Dialogs/PopupTemplate.xaml.cs

@@ -1,26 +0,0 @@
-using System.Windows;
-using System.Windows.Input;
-
-namespace PixiEditor.Views
-{
-    /// <summary>
-    ///     Interaction logic for PopupTemplate.xaml
-    /// </summary>
-    public partial class PopupTemplate : Window
-    {
-        public PopupTemplate()
-        {
-            InitializeComponent();
-        }
-
-        private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
-        {
-            e.CanExecute = true;
-        }
-
-        private void CommandBinding_Executed_Close(object sender, ExecutedRoutedEventArgs e)
-        {
-            SystemCommands.CloseWindow(this);
-        }
-    }
-}

+ 1 - 0
PixiEditor/Views/Dialogs/ResizeCanvasPopup.xaml

@@ -40,6 +40,7 @@
                     VerticalAlignment="Top" Grid.Row="1" Width="300" Height="250">
                     VerticalAlignment="Top" Grid.Row="1" Width="300" Height="250">
             <local:SizePicker Margin="0,10,0,0" Width="300" Height="110"
             <local:SizePicker Margin="0,10,0,0" Width="300" Height="110"
                               x:Name="sizePicker"
                               x:Name="sizePicker"
+                              PreserveAspectRatio="False"
                               ChosenHeight="{Binding NewHeight, Mode=TwoWay, ElementName=window}"
                               ChosenHeight="{Binding NewHeight, Mode=TwoWay, ElementName=window}"
                               ChosenWidth="{Binding NewWidth, Mode=TwoWay, ElementName=window}" />
                               ChosenWidth="{Binding NewWidth, Mode=TwoWay, ElementName=window}" />
             <Separator Margin="10,20,10,0" Background="{StaticResource AccentColor}" Height="1" />
             <Separator Margin="10,20,10,0" Background="{StaticResource AccentColor}" Height="1" />

+ 1 - 0
PixiEditor/Views/Dialogs/ResizeDocumentPopup.xaml

@@ -39,6 +39,7 @@
                     VerticalAlignment="Top" Grid.Row="1" Width="350" Height="150">
                     VerticalAlignment="Top" Grid.Row="1" Width="350" Height="150">
             <local:SizePicker Margin="0,20" 
             <local:SizePicker Margin="0,20" 
                               x:Name="sizePicker"
                               x:Name="sizePicker"
+                              PreserveAspectRatio="True"
                               ChosenHeight="{Binding Path=NewHeight, Mode=TwoWay, ElementName=window}"
                               ChosenHeight="{Binding Path=NewHeight, Mode=TwoWay, ElementName=window}"
                               ChosenWidth="{Binding Path=NewWidth, Mode=TwoWay, ElementName=window}" />
                               ChosenWidth="{Binding Path=NewWidth, Mode=TwoWay, ElementName=window}" />
         </StackPanel>
         </StackPanel>

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

@@ -8,7 +8,7 @@
              xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
              xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
              xmlns:validators="clr-namespace:PixiEditor.Helpers.Validators"
              xmlns:validators="clr-namespace:PixiEditor.Helpers.Validators"
              mc:Ignorable="d" Foreground="White" Focusable="True"
              mc:Ignorable="d" Foreground="White" Focusable="True"
-             d:DesignHeight="30" d:DesignWidth="160" Name="uc" LayoutUpdated="UserControlLayoutUpdated">
+             d:DesignHeight="30" d:DesignWidth="160" Name="uc">
 
 
     <Border BorderThickness="1" CornerRadius="3.5"
     <Border BorderThickness="1" CornerRadius="3.5"
             x:Name="border"
             x:Name="border"

+ 4 - 85
PixiEditor/Views/UserControls/SizeInput.xaml.cs

@@ -1,5 +1,4 @@
-using System;
-using System.Windows;
+using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Controls;
 using System.Windows.Input;
 using System.Windows.Input;
 
 
@@ -11,20 +10,11 @@ namespace PixiEditor.Views
     public partial class SizeInput : UserControl
     public partial class SizeInput : UserControl
     {
     {
         public static readonly DependencyProperty SizeProperty =
         public static readonly DependencyProperty SizeProperty =
-            DependencyProperty.Register(nameof(Size), typeof(int), typeof(SizeInput), new PropertyMetadata(1, InputSizeChanged));
+            DependencyProperty.Register(nameof(Size), typeof(int), typeof(SizeInput), new PropertyMetadata(1));
 
 
         public static readonly DependencyProperty MaxSizeProperty =
         public static readonly DependencyProperty MaxSizeProperty =
             DependencyProperty.Register(nameof(MaxSize), typeof(int), typeof(SizeInput), new PropertyMetadata(int.MaxValue));
             DependencyProperty.Register(nameof(MaxSize), typeof(int), typeof(SizeInput), new PropertyMetadata(int.MaxValue));
 
 
-        public static readonly DependencyProperty PreserveAspectRatioProperty =
-            DependencyProperty.Register(nameof(PreserveAspectRatio), typeof(bool), typeof(SizeInput));
-
-        public static readonly DependencyProperty AspectRatioValueProperty =
-            DependencyProperty.Register(nameof(AspectRatioValue), typeof(int), typeof(SizeInput), new PropertyMetadata(1));
-
-        public static readonly DependencyProperty AspectRatioControlProperty =
-            DependencyProperty.Register(nameof(AspectRatioControl), typeof(SizeInput), typeof(SizeInput), new PropertyMetadata(default));
-
         public static readonly DependencyProperty BehaveLikeSmallEmbeddedFieldProperty =
         public static readonly DependencyProperty BehaveLikeSmallEmbeddedFieldProperty =
             DependencyProperty.Register(nameof(BehaveLikeSmallEmbeddedField), typeof(bool), typeof(SizeInput), new PropertyMetadata(true));
             DependencyProperty.Register(nameof(BehaveLikeSmallEmbeddedField), typeof(bool), typeof(SizeInput), new PropertyMetadata(true));
 
 
@@ -40,35 +30,12 @@ namespace PixiEditor.Views
             set => SetValue(MaxSizeProperty, value);
             set => SetValue(MaxSizeProperty, value);
         }
         }
 
 
-        public bool PreserveAspectRatio
-        {
-            get => (bool)GetValue(PreserveAspectRatioProperty);
-            set => SetValue(PreserveAspectRatioProperty, value);
-        }
-
-        public int AspectRatioValue
-        {
-            get => (int)GetValue(AspectRatioValueProperty);
-            set => SetValue(AspectRatioValueProperty, value);
-        }
-
-        public SizeInput AspectRatioControl
-        {
-            get { return (SizeInput)GetValue(AspectRatioControlProperty); }
-            set { SetValue(AspectRatioControlProperty, value); }
-        }
-
         public bool BehaveLikeSmallEmbeddedField
         public bool BehaveLikeSmallEmbeddedField
         {
         {
             get => (bool)GetValue(BehaveLikeSmallEmbeddedFieldProperty);
             get => (bool)GetValue(BehaveLikeSmallEmbeddedFieldProperty);
             set => SetValue(BehaveLikeSmallEmbeddedFieldProperty, value);
             set => SetValue(BehaveLikeSmallEmbeddedFieldProperty, value);
         }
         }
 
 
-        private int loadedAspectRatioSize = -1;
-
-        private int loadedSize = -1;
-        private bool blockUpdate = false;
-
         public SizeInput()
         public SizeInput()
         {
         {
             InitializeComponent();
             InitializeComponent();
@@ -80,55 +47,7 @@ namespace PixiEditor.Views
             textBox.SelectAll();
             textBox.SelectAll();
         }
         }
 
 
-        private static void InputSizeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
-        {
-            int newValue = (int)e.NewValue;
-            int maxSize = (int)d.GetValue(MaxSizeProperty);
-
-            if (newValue > maxSize)
-            {
-                d.SetValue(SizeProperty, maxSize);
-
-                return;
-            }
-            else if (newValue <= 0)
-            {
-                d.SetValue(SizeProperty, 1);
-
-                return;
-            }
-
-            SizeInput input = ((SizeInput)d).AspectRatioControl;
-            if (input == null)
-            {
-                return;
-            }
-
-            int newVal = (int)e.NewValue;
-            if (input.PreserveAspectRatio && !input.IsFocused && !input.blockUpdate)
-            {
-                float ratio = newVal / Math.Clamp(input.loadedAspectRatioSize, 1f, float.MaxValue);
-                int newSize = (int)(input.loadedSize * ratio);
-                input.AspectRatioControl.blockUpdate = true; // Block update is used to prevent infinite feedback loop.
-                input.Size = newSize;
-            }
-
-            if (input.blockUpdate)
-            {
-                input.blockUpdate = false;
-            }
-        }
-
-        private void UserControlLayoutUpdated(object sender, EventArgs e)
-        {
-            if (loadedSize == -1)
-            {
-                loadedSize = Size;
-                loadedAspectRatioSize = AspectRatioValue;
-            }
-        }
-
-        private void Border_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
+        private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
         {
         {
             if (!textBox.IsFocused)
             if (!textBox.IsFocused)
                 textBox.Focus();
                 textBox.Focus();
@@ -143,7 +62,7 @@ namespace PixiEditor.Views
             e.Handled = true;
             e.Handled = true;
         }
         }
 
 
-        private void Border_MouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
+        private void Border_MouseWheel(object sender, MouseWheelEventArgs e)
         {
         {
             int step = e.Delta / 100;
             int step = e.Delta / 100;
 
 

+ 26 - 9
PixiEditor/Views/UserControls/SizePicker.xaml

@@ -3,9 +3,15 @@
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
              xmlns:local="clr-namespace:PixiEditor.Views"
              xmlns:local="clr-namespace:PixiEditor.Views"
              mc:Ignorable="d"
              mc:Ignorable="d"
              d:DesignHeight="110" d:DesignWidth="215" Name="uc">
              d:DesignHeight="110" d:DesignWidth="215" Name="uc">
+    <i:Interaction.Triggers>
+        <i:EventTrigger EventName="Loaded">
+            <i:InvokeCommandAction Command="{Binding ElementName=uc, Path=LoadedCommand}"/>
+        </i:EventTrigger>
+    </i:Interaction.Triggers>
     <UserControl.Resources>
     <UserControl.Resources>
         <Style TargetType="local:SizeInput">
         <Style TargetType="local:SizeInput">
             <Setter Property="HorizontalAlignment" Value="Left"/>
             <Setter Property="HorizontalAlignment" Value="Left"/>
@@ -23,10 +29,13 @@
                        HorizontalAlignment="Center" VerticalAlignment="Center" />
                        HorizontalAlignment="Center" VerticalAlignment="Center" />
             <local:SizeInput x:Name="WidthPicker"
             <local:SizeInput x:Name="WidthPicker"
                              IsEnabled="{Binding EditingEnabled, ElementName=uc}"
                              IsEnabled="{Binding EditingEnabled, ElementName=uc}"
-                             PreserveAspectRatio="{Binding Path=IsChecked, ElementName=aspectRatio}"
-                             AspectRatioValue="{Binding Path=ChosenHeight, ElementName=uc}"
-                             AspectRatioControl="{Binding ElementName=HeightPicker}"
-                             Size="{Binding Path=ChosenWidth, ElementName=uc, Mode=TwoWay}" />
+                             Size="{Binding Path=ChosenWidth, ElementName=uc, Mode=TwoWay}">
+                <i:Interaction.Triggers>
+                    <i:EventTrigger EventName="LostFocus">
+                        <i:InvokeCommandAction Command="{Binding ElementName=uc, Path=WidthLostFocusCommand}"/>
+                    </i:EventTrigger>
+                </i:Interaction.Triggers>
+            </local:SizeInput>
         </DockPanel>
         </DockPanel>
         <DockPanel Margin="5,10,0,0" HorizontalAlignment="Center" VerticalAlignment="Center">
         <DockPanel Margin="5,10,0,0" HorizontalAlignment="Center" VerticalAlignment="Center">
             <TextBlock Foreground="Snow" Text="Height:" TextAlignment="Center" FontSize="16"
             <TextBlock Foreground="Snow" Text="Height:" TextAlignment="Center" FontSize="16"
@@ -34,11 +43,19 @@
             <local:SizeInput x:Name="HeightPicker" 
             <local:SizeInput x:Name="HeightPicker" 
                              IsEnabled="{Binding EditingEnabled, ElementName=uc}"
                              IsEnabled="{Binding EditingEnabled, ElementName=uc}"
                              Margin="5,0,0,0"
                              Margin="5,0,0,0"
-                             PreserveAspectRatio="{Binding Path=IsChecked, ElementName=aspectRatio}"
-                             AspectRatioValue="{Binding Path=ChosenWidth, ElementName=uc}"
-                             AspectRatioControl="{Binding ElementName=WidthPicker}"
-                             Size="{Binding ChosenHeight, ElementName=uc, Mode=TwoWay}" />
+                             Size="{Binding ChosenHeight, ElementName=uc, Mode=TwoWay}">
+                <i:Interaction.Triggers>
+                    <i:EventTrigger EventName="LostFocus">
+                        <i:InvokeCommandAction Command="{Binding ElementName=uc, Path=HeightLostFocusCommand}"/>
+                    </i:EventTrigger>
+                </i:Interaction.Triggers>
+            </local:SizeInput>
         </DockPanel>
         </DockPanel>
-        <CheckBox Name="aspectRatio" Content="Preserve aspect ratio" Foreground="White" HorizontalAlignment="Left" Margin="50,10,0,0" />
+        <CheckBox Name="aspectRatio" 
+                  IsChecked="{Binding ElementName=uc, Path=PreserveAspectRatio}" 
+                  Content="Preserve aspect ratio" 
+                  Foreground="White" 
+                  HorizontalAlignment="Left" 
+                  Margin="50,10,0,0" />
     </StackPanel>
     </StackPanel>
 </UserControl>
 </UserControl>

+ 52 - 9
PixiEditor/Views/UserControls/SizePicker.xaml.cs

@@ -1,27 +1,24 @@
-using System.Windows;
+using PixiEditor.Helpers;
+using System;
+using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Controls;
 
 
 namespace PixiEditor.Views
 namespace PixiEditor.Views
 {
 {
-    /// <summary>
-    ///     Interaction logic for SizePicker.xaml.
-    /// </summary>
     public partial class SizePicker : UserControl
     public partial class SizePicker : UserControl
     {
     {
         public static readonly DependencyProperty EditingEnabledProperty =
         public static readonly DependencyProperty EditingEnabledProperty =
             DependencyProperty.Register(nameof(EditingEnabled), typeof(bool), typeof(SizePicker), new PropertyMetadata(true));
             DependencyProperty.Register(nameof(EditingEnabled), typeof(bool), typeof(SizePicker), new PropertyMetadata(true));
 
 
+        public static readonly DependencyProperty PreserveAspectRatioProperty =
+            DependencyProperty.Register(nameof(PreserveAspectRatio), typeof(bool), typeof(SizePicker), new PropertyMetadata(true));
+
         public static readonly DependencyProperty ChosenWidthProperty =
         public static readonly DependencyProperty ChosenWidthProperty =
             DependencyProperty.Register(nameof(ChosenWidth), typeof(int), typeof(SizePicker), new PropertyMetadata(1));
             DependencyProperty.Register(nameof(ChosenWidth), typeof(int), typeof(SizePicker), new PropertyMetadata(1));
 
 
         public static readonly DependencyProperty ChosenHeightProperty =
         public static readonly DependencyProperty ChosenHeightProperty =
             DependencyProperty.Register(nameof(ChosenHeight), typeof(int), typeof(SizePicker), new PropertyMetadata(1));
             DependencyProperty.Register(nameof(ChosenHeight), typeof(int), typeof(SizePicker), new PropertyMetadata(1));
 
 
-        public SizePicker()
-        {
-            InitializeComponent();
-        }
-
         public bool EditingEnabled
         public bool EditingEnabled
         {
         {
             get => (bool)GetValue(EditingEnabledProperty);
             get => (bool)GetValue(EditingEnabledProperty);
@@ -40,9 +37,55 @@ namespace PixiEditor.Views
             set => SetValue(ChosenHeightProperty, value);
             set => SetValue(ChosenHeightProperty, value);
         }
         }
 
 
+        public bool PreserveAspectRatio
+        {
+            get => (bool)GetValue(PreserveAspectRatioProperty);
+            set => SetValue(PreserveAspectRatioProperty, value);
+        }
+
+        public RelayCommand LoadedCommand { get; private set; }
+        public RelayCommand WidthLostFocusCommand { get; private set; }
+        public RelayCommand HeightLostFocusCommand { get; private set; }
+
+        private bool initialValuesLoaded = false;
+        private int initW;
+        private int initH;
+        public SizePicker()
+        {
+            LoadedCommand = new(AfterLoaded);
+            WidthLostFocusCommand = new(WidthLostFocus);
+            HeightLostFocusCommand = new(HeightLostFocus);
+            InitializeComponent();
+        }
+
         public void FocusWidthPicker()
         public void FocusWidthPicker()
         {
         {
             WidthPicker.FocusAndSelect();
             WidthPicker.FocusAndSelect();
         }
         }
+
+        private void AfterLoaded(object parameter)
+        {
+            initW = ChosenWidth;
+            initH = ChosenHeight;
+            initialValuesLoaded = true;
+        }
+
+        private void WidthLostFocus(object param) => OnSizeUpdate(true);
+        private void HeightLostFocus(object param) => OnSizeUpdate(false);
+
+        private void OnSizeUpdate(bool widthUpdated)
+        {
+            if (!initialValuesLoaded || !PreserveAspectRatio)
+                return;
+
+            if (widthUpdated)
+            {
+                ChosenHeight = Math.Clamp(ChosenWidth * initH / initW, 1, HeightPicker.MaxSize);
+            }
+            else
+            {
+                ChosenWidth = Math.Clamp(ChosenHeight * initW / initH, 1, WidthPicker.MaxSize);
+            }
+        }
     }
     }
 }
 }