Bladeren bron

Improved rectangle guide and added hover highlighting

CPKreuz 2 jaren geleden
bovenliggende
commit
d2d30cc38e

+ 4 - 1
src/PixiEditor/Data/Localization/Languages/en.json

@@ -579,10 +579,13 @@
   "LINE_GUIDE": "Line guide",
   "VERTICAL_GUIDE": "Vertical guide",
   "HORIZONTAL_GUIDE": "Horizontal guide",
+  "RECTANGLE_GUIDE": "Rectangle Guide",
   "ADD_LINE_GUIDE": "Add line guide",
   "ADD_LINE_GUIDE_DESCRIPTIVE": "Add line guide",
   "ADD_VERTICAL_GUIDE": "Add vertical guide",
   "ADD_VERTICAL_GUIDE_DESCRIPTIVE": "Add vertical guide",
   "ADD_HORIZONTAL_GUIDE": "Add horizontal guide",
-  "ADD_HORIZONTAL_GUIDE_DESCRIPTIVE": "Add horizontal guide"
+  "ADD_HORIZONTAL_GUIDE_DESCRIPTIVE": "Add horizontal guide",
+  "ADD_RECTANGLE_GUIDE": "Add rectangle guide",
+  "ADD_RECTANGLE_GUIDE_DESCRIPTIVE": "Add rectangle guide"
 }

+ 2 - 1
src/PixiEditor/Models/DataHolders/Guides/DirectionalGuide.cs

@@ -69,7 +69,8 @@ internal class DirectionalGuide : Guide
 
     public override void Draw(DrawingContext context, GuideRenderer renderer)
     {
-        var pen = new Pen(new SolidColorBrush(Color), renderer.ScreenUnit * (IsEditing ? 3 : 1.5d));
+        var mod = IsEditing ? 4.5 : (ShowExtended ? 3 : 1.5);
+        var pen = new Pen(new SolidColorBrush(Color), renderer.ScreenUnit * mod);
 
         var pointA = IsVertical ? new Point(Offset, 0) : new Point(0, Offset);
         var pointB = IsVertical ? new Point(Offset, Document.SizeBindable.Y) : new Point(Document.SizeBindable.X, Offset);

+ 3 - 3
src/PixiEditor/Models/DataHolders/Guides/Guide.cs

@@ -18,7 +18,7 @@ namespace PixiEditor.Models.DataHolders.Guides
         private string name;
         private bool alwaysShowName;
         private bool showExtended;
-        private bool showEditable;
+        private bool isEditing;
         private List<GuideRenderer> renderers = new();
 
         public string Name
@@ -60,10 +60,10 @@ namespace PixiEditor.Models.DataHolders.Guides
 
         public bool IsEditing
         {
-            get => showEditable;
+            get => isEditing;
             set
             {
-                if (SetProperty(ref showEditable, value))
+                if (SetProperty(ref isEditing, value))
                 {
                     InvalidateVisual();
                 }

+ 2 - 2
src/PixiEditor/Models/DataHolders/Guides/LineGuide.cs

@@ -101,10 +101,10 @@ namespace PixiEditor.Models.DataHolders.Guides
 
             if (ShowExtended || IsEditing)
             {
-                var scale = IsEditing ? 2 : 1;
+                var scale = IsEditing ? 3 : 1.5;
                 var pen = new Pen(brush, penThickness * 2 * scale);
                 context.DrawLine(pen, points.Item1, points.Item2);
-                context.DrawEllipse(Brushes.Aqua, null, new Point(X, Y), penThickness * 3 * scale, penThickness * 3 * scale);
+                context.DrawEllipse(Brushes.Aqua, null, new Point(X, Y), penThickness * 2 * scale, penThickness * 2 * scale);
             }
             else
             {

+ 100 - 18
src/PixiEditor/Models/DataHolders/Guides/RectangleGuide.cs

@@ -7,6 +7,7 @@ using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Input;
 using System.Windows.Media;
+using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.ViewModels.SubViewModels.Document;
 using PixiEditor.Views.UserControls.Guides;
 
@@ -96,7 +97,7 @@ internal class RectangleGuide : Guide
     {
         bool skipDraw = false;
 
-        var mod = IsEditing ? 3 : 1;
+        var mod = IsEditing ? 3 : (ShowExtended ? 2 : 1);
 
         var pen = new Pen(new SolidColorBrush(color), renderer.ScreenUnit * 1.5d * mod);
         context.DrawRectangle(null, pen, new(Left, Top, Width, Height));
@@ -120,12 +121,13 @@ internal class RectangleGuide : Guide
         }
 
         var renderer = (GuideRenderer)sender;
-        var closestPoint = GetPoint(e.GetPosition(renderer));
+        var closestPoint = GetPoint(e.GetPosition(renderer), renderer.ScreenUnit);
 
         renderer.Cursor = closestPoint switch
         {
             GrabbedPoint.TopLeft or GrabbedPoint.BottomRight => Cursors.SizeNWSE,
-            GrabbedPoint.TopRight or GrabbedPoint.BottomLeft => Cursors.SizeNESW
+            GrabbedPoint.TopRight or GrabbedPoint.BottomLeft => Cursors.SizeNESW,
+            _ => null
         };
     }
 
@@ -145,7 +147,7 @@ internal class RectangleGuide : Guide
         e.Handled = true;
         var renderer = (GuideRenderer)sender;
         Mouse.Capture(renderer);
-        grabbedPoint = GetPoint(e.GetPosition(renderer));
+        grabbedPoint = GetPoint(e.GetPosition(renderer), renderer.ScreenUnit);
     }
 
     private void Renderer_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
@@ -161,39 +163,114 @@ internal class RectangleGuide : Guide
 
         if (grabbedPoint == null)
         {
-            var closestPoint = GetPoint(mousePos);
+            var closestPoint = GetPoint(mousePos, renderer.ScreenUnit);
 
             renderer.Cursor = closestPoint switch
             {
                 GrabbedPoint.TopLeft or GrabbedPoint.BottomRight => Cursors.SizeNWSE,
-                GrabbedPoint.TopRight or GrabbedPoint.BottomLeft => Cursors.SizeNESW
+                GrabbedPoint.TopRight or GrabbedPoint.BottomLeft => Cursors.SizeNESW,
+                _ => null
             };
             return;
         }
 
         var size = Document.SizeBindable;
 
+        var newLeft = Left;
+        var newTop = Top;
+        var newWidth = Width;
+        var newHeight = Height;
+
+        GetNewDimensions(mousePos, ref newLeft, ref newTop, ref newWidth, ref newHeight);
+        if (EnsureSafeDimensions(ref newLeft, ref newTop, ref newWidth, ref newHeight))
+        {
+            return;
+        }
+
+        Left = newLeft;
+        Top = newTop;
+        Width = newWidth;
+        Height = newHeight;
+    }
+
+    private void GetNewDimensions(Point mousePos, ref double newLeft, ref double newTop, ref double newWidth, ref double newHeight)
+    {
         switch (grabbedPoint)
         {
             case GrabbedPoint.TopLeft:
-                Left = RoundMod(mousePos.X);
-                Top = RoundMod(mousePos.Y);
+                newWidth = RoundMod(Width + Left - mousePos.X);
+                newHeight = RoundMod(Height + Top - mousePos.Y);
+                newLeft = RoundMod(mousePos.X);
+                newTop = RoundMod(mousePos.Y);
                 break;
             case GrabbedPoint.TopRight:
-                Width = RoundMod(size.X - mousePos.X - Left);
-                Top = RoundMod(mousePos.Y);
+                newWidth = RoundMod(mousePos.X - Left);
+                newHeight = RoundMod(Height + Top - mousePos.Y);
+                newTop = RoundMod(mousePos.Y);
                 break;
             case GrabbedPoint.BottomRight:
-                Width = RoundMod(size.X - mousePos.X - Left);
-                Height = RoundMod(size.Y - mousePos.Y - Top);
+                newWidth = RoundMod(mousePos.X - Left);
+                newHeight = RoundMod(mousePos.Y - Top);
                 break;
             case GrabbedPoint.BottomLeft:
-                Left = RoundMod(mousePos.X);
-                Height = RoundMod(size.Y - mousePos.Y - Top);
+                newWidth = RoundMod(Width + Left - mousePos.X);
+                newLeft = RoundMod(mousePos.X);
+                newHeight = RoundMod(mousePos.Y - Top);
                 break;
         }
     }
 
+    private bool EnsureSafeDimensions(ref double newLeft, ref double newTop, ref double newWidth, ref double newHeight)
+    {
+        if (newWidth < 0 && newHeight < 0)
+        {
+            newWidth = 0;
+            newHeight = 0;
+
+            grabbedPoint = grabbedPoint switch
+            {
+                GrabbedPoint.TopLeft => GrabbedPoint.BottomRight,
+                GrabbedPoint.BottomRight => GrabbedPoint.TopLeft,
+                GrabbedPoint.TopRight => GrabbedPoint.BottomLeft,
+                GrabbedPoint.BottomLeft => GrabbedPoint.TopRight
+            };
+
+            return true;
+        }
+
+        if (newWidth < 0)
+        {
+            newWidth = 0;
+
+            grabbedPoint = grabbedPoint switch
+            {
+                GrabbedPoint.TopLeft => GrabbedPoint.TopRight,
+                GrabbedPoint.BottomLeft => GrabbedPoint.BottomRight,
+                GrabbedPoint.TopRight => GrabbedPoint.TopLeft,
+                GrabbedPoint.BottomRight => GrabbedPoint.BottomLeft
+            };
+
+            return true;
+        }
+
+        if (newHeight < 0)
+        {
+            newHeight = 0;
+
+            grabbedPoint = grabbedPoint switch
+            {
+                GrabbedPoint.TopLeft => GrabbedPoint.BottomLeft,
+                GrabbedPoint.TopRight => GrabbedPoint.BottomRight,
+                GrabbedPoint.BottomLeft => GrabbedPoint.TopLeft,
+                GrabbedPoint.BottomRight => GrabbedPoint.TopRight
+            };
+
+            return true;
+        }
+
+        return false;
+    }
+
     private void Renderer_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
     {
         if (!IsEditing || grabbedPoint == null)
@@ -207,14 +284,14 @@ internal class RectangleGuide : Guide
         Mouse.Capture(null);
     }
 
-    private GrabbedPoint GetPoint(Point mouse)
+    private GrabbedPoint? GetPoint(Point mouse, double screenUnit)
     {
         var size = Document.SizeBindable;
 
         var topLeft = new Point(Left, Top);
-        var topRight = new Point(size.X - left, Top);
-        var bottomRight = new Point(size.X - left, size.Y - top);
-        var bottomLeft = new Point(Left, size.Y - top);
+        var topRight = new Point(Left + Width, Top);
+        var bottomRight = new Point(Left + Width, Top + Height);
+        var bottomLeft = new Point(Left, Top + Height);
 
         double value = double.PositiveInfinity;
         int index = -1;
@@ -230,6 +307,11 @@ internal class RectangleGuide : Guide
             }
         }
 
+        if (value > screenUnit * 20)
+        {
+            return null;
+        }
+
         return (GrabbedPoint)index;
     }
 

+ 2 - 0
src/PixiEditor/Views/Dialogs/Guides/GuidesManager.xaml

@@ -58,6 +58,8 @@
                                 <Setter Property="BorderBrush" Value="Transparent" />
                                 <Setter Property="Background" Value="Transparent"/>
                                 <Setter Property="Foreground" Value="White"/>
+                                <EventSetter Event="MouseEnter" Handler="ListViewItem_MouseEnter"/>
+                                <EventSetter Event="MouseLeave" Handler="ListViewItem_MouseLeave"/>
                                 <Setter Property="Template">
                                     <Setter.Value>
                                         <ControlTemplate TargetType="ListViewItem">

+ 16 - 0
src/PixiEditor/Views/Dialogs/Guides/GuidesManager.xaml.cs

@@ -114,4 +114,20 @@ public partial class GuidesManager : Window
     }
 
     private bool IsSupportedKey(Key key) => key == Key.Delete || key == Key.Up || key == Key.Down;
+
+    private void ListViewItem_MouseEnter(object sender, MouseEventArgs e)
+    {
+        var listItem = (ListViewItem)sender;
+        var guide = (Guide)listItem.DataContext;
+
+        guide.ShowExtended = true;
+    }
+
+    private void ListViewItem_MouseLeave(object sender, MouseEventArgs e)
+    {
+        var listItem = (ListViewItem)sender;
+        var guide = (Guide)listItem.DataContext;
+
+        guide.ShowExtended = false;
+    }
 }

+ 4 - 4
src/PixiEditor/Views/UserControls/Guides/RectangleGuideSettings.xaml

@@ -66,11 +66,11 @@
                 <ColumnDefinition Width="Auto" SharedSizeGroup="position"/>
                 <ColumnDefinition Width="Auto"/>
             </Grid.ColumnDefinitions>
-            <TextBlock views:Translator.Key="RIGHT" Margin="0,0,10,0" TextAlignment="Right"/>
-            <uc:NumberInput Margin="0,0,10,0" Grid.Column="1" Value="{Binding Right, Mode=TwoWay}" Width="50" HorizontalAlignment="Left"/>
+            <TextBlock views:Translator.Key="Width" Margin="0,0,10,0" TextAlignment="Right"/>
+            <uc:NumberInput Margin="0,0,10,0" Grid.Column="1" Value="{Binding Width, Mode=TwoWay}" Width="50" HorizontalAlignment="Left"/>
 
-            <TextBlock Grid.Column="2" views:Translator.Key="BOTTOM" Margin="0,0,10,0"/>
-            <uc:NumberInput Grid.Column="3" Value="{Binding Bottom, Mode=TwoWay}" Width="50" HorizontalAlignment="Left"/>
+            <TextBlock Grid.Column="2" views:Translator.Key="Height" Margin="0,0,10,0"/>
+            <uc:NumberInput Grid.Column="3" Value="{Binding Height, Mode=TwoWay}" Width="50" HorizontalAlignment="Left"/>
         </Grid>
     </StackPanel>
 </UserControl>