Browse Source

Fixed cursor

Krzysztof Krysiński 1 year ago
parent
commit
d573e7b3e6

+ 18 - 0
src/PixiEditor.AvaloniaUI/Helpers/Converters/VectorPathToVisibleConverter.cs

@@ -0,0 +1,18 @@
+using System.Globalization;
+using Avalonia.Data.Converters;
+using PixiEditor.DrawingApi.Core.Surface.Vector;
+
+namespace PixiEditor.AvaloniaUI.Helpers.Converters;
+
+internal class VectorPathToVisibleConverter : SingleInstanceConverter<VectorPathToVisibleConverter>
+{
+    public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        if (value is VectorPath path)
+        {
+            return !path.IsEmpty;
+        }
+
+        return false;
+    }
+}

+ 4 - 0
src/PixiEditor.AvaloniaUI/ViewModels/Document/DocumentViewModel.cs

@@ -107,6 +107,8 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
         }
     }
 
+    public bool AnySymmetryAxisEnabledBindable => HorizontalSymmetryAxisEnabledBindable || VerticalSymmetryAxisEnabledBindable;
+
     private VecI size = new VecI(64, 64);
     public int Width => size.X;
     public int Height => size.Y;
@@ -511,12 +513,14 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
     {
         this.horizontalSymmetryAxisEnabled = horizontalSymmetryAxisEnabled;
         OnPropertyChanged(nameof(HorizontalSymmetryAxisEnabledBindable));
+        OnPropertyChanged(nameof(AnySymmetryAxisEnabledBindable));
     }
 
     public void SetVerticalSymmetryAxisEnabled(bool infoState)
     {
         verticalSymmetryAxisEnabled = infoState;
         OnPropertyChanged(nameof(VerticalSymmetryAxisEnabledBindable));
+        OnPropertyChanged(nameof(AnySymmetryAxisEnabledBindable));
     }
 
     public void SetVerticalSymmetryAxisX(double verticalSymmetryAxisX)

+ 2 - 2
src/PixiEditor.AvaloniaUI/Views/Main/ViewportControls/Viewport.axaml

@@ -125,7 +125,6 @@
             Surface="{Binding TargetBitmap, ElementName=vpUc}"
             Document="{Binding Document, ElementName=vpUc, Mode=OneWay}"
             UseTouchGestures="{Binding UseTouchGestures, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=viewportControls:Viewport}, Mode=OneWay}"
-            Scale="{Binding ZoomboxScale, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=viewportControls:Viewport}, Mode=OneWayToSource}"
             Center="{Binding Center, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=viewportControls:Viewport}, Mode=OneWayToSource}"
             AngleRadians="{Binding AngleRadians, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=viewportControls:Viewport}, Mode=OneWayToSource}"
             RealDimensions="{Binding RealDimensions, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=viewportControls:Viewport}, Mode=OneWayToSource}"
@@ -134,8 +133,9 @@
             ZoomOutOnClick="{Binding ZoomOutOnClick, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=viewportControls:Viewport}, Mode=TwoWay}"
             FlipX="{Binding FlipX, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=viewportControls:Viewport}, Mode=TwoWay}"
             FlipY="{Binding FlipY, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=viewportControls:Viewport}, Mode=TwoWay}"
-            ActiveOverlays="{Binding ElementName=vpUc, Path=ActiveOverlays}"
+            AllOverlays="{Binding ElementName=vpUc, Path=ActiveOverlays}"
             FadeOut="{Binding Source={viewModels:ToolVM ColorPickerToolViewModel}, Path=PickOnlyFromReferenceLayer, Mode=OneWay}"
+            DefaultCursor="{Binding Source={viewModels:MainVM}, Path=ToolsSubViewModel.ToolCursor, Mode=OneWay}"
             CheckerImagePath="/Images/CheckerTile.png"
             ui1:RenderOptionsBindable.BitmapInterpolationMode="{Binding Scale, Converter={converters:ScaleToBitmapScalingModeConverter}, RelativeSource={RelativeSource Self}}"/>
         <!--<zoombox:Zoombox

+ 3 - 1
src/PixiEditor.AvaloniaUI/Views/Main/ViewportControls/ViewportOverlays.cs

@@ -144,7 +144,7 @@ internal class ViewportOverlays
             Source = Viewport,
             Path = "Document.SelectionPathBindable",
             Mode = BindingMode.OneWay,
-            Converter = new NotNullToVisibilityConverter()
+            Converter = new VectorPathToVisibleConverter()
         };
 
         selectionOverlay.Bind(SelectionOverlay.ShowFillProperty, showFillBinding);
@@ -154,6 +154,7 @@ internal class ViewportOverlays
 
     private void BindSymmetryOverlay()
     {
+        Binding isVisibleBinding = new() {Source = Viewport, Path = "Document.AnySymmetryAxisEnabledBindable", Mode = BindingMode.OneWay };
         Binding sizeBinding = new() { Source = Viewport, Path = "Document.SizeBindable", Mode = BindingMode.OneWay };
         Binding isHitTestVisibleBinding = new() {Source = Viewport, Path = "ZoomMode", Converter = new ZoomModeToHitTestVisibleConverter(), Mode = BindingMode.OneWay };
         Binding horizontalAxisVisibleBinding = new() {Source = Viewport, Path = "Document.HorizontalSymmetryAxisEnabledBindable", Mode = BindingMode.OneWay };
@@ -161,6 +162,7 @@ internal class ViewportOverlays
         Binding horizontalAxisYBinding = new() {Source = Viewport, Path = "Document.HorizontalSymmetryAxisYBindable", Mode = BindingMode.OneWay };
         Binding verticalAxisXBinding = new() {Source = Viewport, Path = "Document.VerticalSymmetryAxisXBindable", Mode = BindingMode.OneWay };
 
+        symmetryOverlay.Bind(Visual.IsVisibleProperty, isVisibleBinding);
         symmetryOverlay.Bind(SymmetryOverlay.SizeProperty, sizeBinding);
         symmetryOverlay.Bind(InputElement.IsHitTestVisibleProperty, isHitTestVisibleBinding);
         symmetryOverlay.Bind(SymmetryOverlay.HorizontalAxisVisibleProperty, horizontalAxisVisibleBinding);

+ 5 - 0
src/PixiEditor.AvaloniaUI/Views/Overlays/Overlay.cs

@@ -47,6 +47,11 @@ public abstract class Overlay : Decorator, IOverlay // TODO: Maybe make it not a
         ZoomScaleProperty.Changed.Subscribe(OnZoomScaleChanged);
     }
 
+    ~Overlay()
+    {
+        transitionTimer?.Stop();
+    }
+
     public abstract void RenderOverlay(DrawingContext context, RectD canvasBounds);
 
     public void Refresh()

+ 33 - 18
src/PixiEditor.AvaloniaUI/Views/Rendering/Scene.cs

@@ -39,23 +39,32 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
     public static readonly StyledProperty<bool> FadeOutProperty = AvaloniaProperty.Register<Scene, bool>(
         nameof(FadeOut), false);
 
-    public static readonly StyledProperty<ObservableCollection<Overlay>> ActiveOverlaysProperty =
+    public static readonly StyledProperty<ObservableCollection<Overlay>> AllOverlaysProperty =
         AvaloniaProperty.Register<Scene, ObservableCollection<Overlay>>(
-            nameof(ActiveOverlays));
+            nameof(AllOverlays));
 
     public static readonly StyledProperty<string> CheckerImagePathProperty = AvaloniaProperty.Register<Scene, string>(
         nameof(CheckerImagePath));
 
+    public static readonly StyledProperty<Cursor> DefaultCursorProperty = AvaloniaProperty.Register<Scene, Cursor>(
+        nameof(DefaultCursor));
+
+    public Cursor DefaultCursor
+    {
+        get => GetValue(DefaultCursorProperty);
+        set => SetValue(DefaultCursorProperty, value);
+    }
+
     public string CheckerImagePath
     {
         get => GetValue(CheckerImagePathProperty);
         set => SetValue(CheckerImagePathProperty, value);
     }
 
-    public ObservableCollection<Overlay> ActiveOverlays
+    public ObservableCollection<Overlay> AllOverlays
     {
-        get => GetValue(ActiveOverlaysProperty);
-        set => SetValue(ActiveOverlaysProperty, value);
+        get => GetValue(AllOverlaysProperty);
+        set => SetValue(AllOverlaysProperty, value);
     }
 
     public bool FadeOut
@@ -87,12 +96,12 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
     static Scene()
     {
         AffectsRender<Scene>(BoundsProperty, WidthProperty, HeightProperty, ScaleProperty, AngleRadiansProperty, FlipXProperty,
-            FlipYProperty, DocumentProperty, SurfaceProperty, ActiveOverlaysProperty);
+            FlipYProperty, DocumentProperty, SurfaceProperty, AllOverlaysProperty);
 
         FadeOutProperty.Changed.AddClassHandler<Scene>(FadeOutChanged);
         SurfaceProperty.Changed.AddClassHandler<Scene>(SurfaceChanged);
         CheckerImagePathProperty.Changed.AddClassHandler<Scene>(CheckerImagePathChanged);
-        ActiveOverlaysProperty.Changed.AddClassHandler<Scene>(ActiveOverlaysChanged);
+        AllOverlaysProperty.Changed.AddClassHandler<Scene>(ActiveOverlaysChanged);
     }
 
     public Scene()
@@ -137,6 +146,9 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
         DrawCheckerboard(context, dirtyRect, operation.SurfaceRectToRender);
 
         resolutionTransformation.Dispose();
+
+        Cursor = DefaultCursor;
+
         DrawOverlays(context, dirtyBounds, OverlayRenderSorting.Background);
 
         resolutionTransformation = context.PushTransform(Matrix.CreateScale(resolutionScale, resolutionScale));
@@ -148,9 +160,9 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
 
     private void DrawOverlays(DrawingContext context, RectD dirtyBounds, OverlayRenderSorting sorting)
     {
-        if (ActiveOverlays != null)
+        if (AllOverlays != null)
         {
-            foreach (Overlay overlay in ActiveOverlays)
+            foreach (Overlay overlay in AllOverlays)
             {
                 if (!overlay.IsVisible || overlay.OverlayRenderSorting != sorting) continue;
                 overlay.ZoomScale = Scale;
@@ -174,10 +186,10 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
     protected override void OnPointerEntered(PointerEventArgs e)
     {
         base.OnPointerEntered(e);
-        if (ActiveOverlays != null)
+        if (AllOverlays != null)
         {
             OverlayPointerArgs args = ConstructPointerArgs(e);
-            foreach (Overlay overlay in ActiveOverlays)
+            foreach (Overlay overlay in AllOverlays)
             {
                 if (!overlay.IsVisible || mouseOverOverlays.Contains(overlay) || !overlay.TestHit(args.Point)) continue;
                 overlay.EnterPointer(args);
@@ -191,7 +203,7 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
     protected override void OnPointerMoved(PointerEventArgs e)
     {
         base.OnPointerMoved(e);
-        if (ActiveOverlays != null)
+        if (AllOverlays != null)
         {
             OverlayPointerArgs args = ConstructPointerArgs(e);
 
@@ -201,7 +213,7 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
             }
             else
             {
-                foreach (Overlay overlay in ActiveOverlays)
+                foreach (Overlay overlay in AllOverlays)
                 {
                     if (!overlay.IsVisible) continue;
 
@@ -219,6 +231,9 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
                         {
                             overlay.ExitPointer(args);
                             mouseOverOverlays.Remove(overlay);
+
+                            e.Handled = args.Handled;
+                            return;
                         }
                     }
 
@@ -233,7 +248,7 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
     protected override void OnPointerPressed(PointerPressedEventArgs e)
     {
         base.OnPointerPressed(e);
-        if (ActiveOverlays != null)
+        if (AllOverlays != null)
         {
             OverlayPointerArgs args = ConstructPointerArgs(e);
             if (capturedOverlay != null)
@@ -258,7 +273,7 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
     protected override void OnPointerExited(PointerEventArgs e)
     {
         base.OnPointerExited(e);
-        if (ActiveOverlays != null)
+        if (AllOverlays != null)
         {
             OverlayPointerArgs args = ConstructPointerArgs(e);
             for (var i = 0; i < mouseOverOverlays.Count; i++)
@@ -279,7 +294,7 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
     protected override void OnPointerReleased(PointerReleasedEventArgs e)
     {
         base.OnPointerExited(e);
-        if (ActiveOverlays != null)
+        if (AllOverlays != null)
         {
             OverlayPointerArgs args = ConstructPointerArgs(e);
 
@@ -340,7 +355,7 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
 
     private void CaptureOverlay(Overlay? overlay, IPointer pointer)
     {
-        if(ActiveOverlays == null) return;
+        if(AllOverlays == null) return;
         if (overlay == null)
         {
             pointer.Capture(null);
@@ -349,7 +364,7 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
             return;
         }
 
-        if(!ActiveOverlays.Contains(overlay)) return;
+        if(!AllOverlays.Contains(overlay)) return;
 
         pointer.Capture(this);
         capturedOverlay = overlay;