Browse Source

Added ToolPicker

Krzysztof Krysiński 1 year ago
parent
commit
99ad09d579

+ 20 - 0
src/PixiEditor.AvaloniaUI/Helpers/Converters/ImagePathToBitmapConverter.cs

@@ -0,0 +1,20 @@
+using System.Globalization;
+using System.Reflection;
+using Avalonia;
+using Avalonia.Media.Imaging;
+using Avalonia.Platform;
+
+namespace PixiEditor.AvaloniaUI.Helpers.Converters;
+
+internal class ImagePathToBitmapConverter : SingleInstanceConverter<ImagePathToBitmapConverter>
+{
+    public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        if (value is string path)
+        {
+            return new Bitmap(AssetLoader.Open(new Uri($"avares://{Assembly.GetExecutingAssembly().FullName}{path}")));
+        }
+
+        return null;
+    }
+}

+ 1 - 1
src/PixiEditor.AvaloniaUI/Models/Handlers/IToolsHandler.cs

@@ -12,7 +12,7 @@ internal interface IToolsHandler : IHandler
     public void SetTool(object parameter);
     public void SetTool(object parameter);
     public void RestorePreviousTool();
     public void RestorePreviousTool();
     public IToolHandler ActiveTool { get; }
     public IToolHandler ActiveTool { get; }
-    public List<IToolHandler> ToolSet { get; }
+    public ICollection<IToolHandler> ToolSet { get; }
     public RightClickMode RightClickMode { get; set; }
     public RightClickMode RightClickMode { get; set; }
     public bool EnableSharedToolbar { get; set; }
     public bool EnableSharedToolbar { get; set; }
     public event EventHandler<SelectedToolEventArgs> SelectedToolChanged;
     public event EventHandler<SelectedToolEventArgs> SelectedToolChanged;

+ 7 - 0
src/PixiEditor.AvaloniaUI/PixiEditor.AvaloniaUI.csproj

@@ -75,4 +75,11 @@
       <UpToDateCheckInput Remove="Fonts\feather.ttf" />
       <UpToDateCheckInput Remove="Fonts\feather.ttf" />
     </ItemGroup>
     </ItemGroup>
   
   
+    <ItemGroup>
+      <Compile Update="Views\Main\Tools\ToolsPicker.axaml.cs">
+        <DependentUpon>ToolsPicker.axaml</DependentUpon>
+        <SubType>Code</SubType>
+      </Compile>
+    </ItemGroup>
+  
 </Project>
 </Project>

+ 1 - 0
src/PixiEditor.AvaloniaUI/Styles/PixiEditor.Controls.axaml

@@ -10,4 +10,5 @@
     </Styles.Resources>
     </Styles.Resources>
 
 
     <StyleInclude Source="avares://PixiEditor.AvaloniaUI/Styles/PortingWipStyles.axaml"/>
     <StyleInclude Source="avares://PixiEditor.AvaloniaUI/Styles/PortingWipStyles.axaml"/>
+    <StyleInclude Source="avares://PixiEditor.AvaloniaUI/Styles/ToolPickerButton.Styles.axaml"/>
 </Styles>
 </Styles>

+ 53 - 2
src/PixiEditor.AvaloniaUI/Styles/PixiEditor.Handles.axaml

@@ -3,8 +3,59 @@
                     xmlns:system="clr-namespace:System;assembly=System.Runtime">
                     xmlns:system="clr-namespace:System;assembly=System.Runtime">
     <Styles.Resources>
     <Styles.Resources>
         <ResourceDictionary>
         <ResourceDictionary>
-            <Path x:Key="MoveHandle"
-                  Data="M 0.50025839 0 0.4248062 0.12971572 0.34987079 0.25994821 h 0.1002584 V 0.45012906 H 0.25994831 V 0.34987066 L 0.12971577 0.42480604 0 0.5002582 0.12971577 0.57519373 0.25994831 0.65012926 V 0.5498709 H 0.45012919 V 0.74005175 H 0.34987079 L 0.42480619 0.87028439 0.50025839 1 0.57519399 0.87028439 0.65012959 0.74005175 H 0.54987119 V 0.5498709 H 0.74005211 V 0.65012926 L 0.87028423 0.57519358 1 0.5002582 0.87028423 0.42480604 0.74005169 0.34987066 v 0.1002584 H 0.54987077 V 0.25994821 h 0.1002584 L 0.5751938 0.12971572 Z"/>
+             <DrawingGroup x:Key="MoveHandle">
+        <DrawingGroup.ClipGeometry>
+            <RectangleGeometry Rect="0.0,0.0,24.0,24.0"/>
+        </DrawingGroup.ClipGeometry>
+        <GeometryDrawing>
+            <GeometryDrawing.Pen>
+                <Pen Brush="{DynamicResource HandleBrush}" LineJoin="Round" Thickness="2.0" LineCap="Round"/>
+            </GeometryDrawing.Pen>
+            <GeometryDrawing.Geometry>
+                <PathGeometry Figures="M 5 9 L 2 12 L 5 15"/>
+            </GeometryDrawing.Geometry>
+        </GeometryDrawing>
+        <GeometryDrawing>
+            <GeometryDrawing.Pen>
+                <Pen Brush="{DynamicResource HandleBrush}" LineJoin="Round" Thickness="2.0" LineCap="Round"/>
+            </GeometryDrawing.Pen>
+            <GeometryDrawing.Geometry>
+                <PathGeometry Figures="M 9 5 L 12 2 L 15 5"/>
+            </GeometryDrawing.Geometry>
+        </GeometryDrawing>
+        <GeometryDrawing>
+            <GeometryDrawing.Pen>
+                <Pen Brush="{DynamicResource HandleBrush}" LineJoin="Round" Thickness="2.0" LineCap="Round"/>
+            </GeometryDrawing.Pen>
+            <GeometryDrawing.Geometry>
+                <PathGeometry Figures="M 15 19 L 12 22 L 9 19"/>
+            </GeometryDrawing.Geometry>
+        </GeometryDrawing>
+        <GeometryDrawing>
+            <GeometryDrawing.Pen>
+                <Pen Brush="{DynamicResource HandleBrush}" LineJoin="Round" Thickness="2.0" LineCap="Round"/>
+            </GeometryDrawing.Pen>
+            <GeometryDrawing.Geometry>
+                <PathGeometry Figures="M 19 9 L 22 12 L 19 15"/>
+            </GeometryDrawing.Geometry>
+        </GeometryDrawing>
+        <GeometryDrawing>
+            <GeometryDrawing.Pen>
+                <Pen Brush="{DynamicResource HandleBrush}" LineJoin="Round" Thickness="2.0" LineCap="Round"/>
+            </GeometryDrawing.Pen>
+            <GeometryDrawing.Geometry>
+                <LineGeometry StartPoint="2.0,12.0" EndPoint="22.0,12.0"/>
+            </GeometryDrawing.Geometry>
+        </GeometryDrawing>
+        <GeometryDrawing>
+            <GeometryDrawing.Pen>
+                <Pen Brush="{DynamicResource HandleBrush}" LineJoin="Round" Thickness="2.0" LineCap="Round"/>
+            </GeometryDrawing.Pen>
+            <GeometryDrawing.Geometry>
+                <LineGeometry StartPoint="12.0,2.0" EndPoint="12.0,22.0"/>
+            </GeometryDrawing.Geometry>
+        </GeometryDrawing>
+    </DrawingGroup>
 
 
             <Path x:Key="MarkerHandle" Data="M -1.1146 -0.6603 c -0.1215 -0.1215 -0.3187 -0.1215 -0.4401 0 l -0.4401 0.4401 c -0.1215 0.1215 -0.1215 0.3187 0 0.4401 l 0.4401 0.4401 c 0.1215 0.1215 0.3187 0.1215 0.4401 0 l 0.4401 -0.4401 c 0.1215 -0.1215 0.1215 -0.3187 0 -0.4401 l -0.4401 -0.4401 Z M -0.5834 0.0012 l 0.5833 -0.0013"/>
             <Path x:Key="MarkerHandle" Data="M -1.1146 -0.6603 c -0.1215 -0.1215 -0.3187 -0.1215 -0.4401 0 l -0.4401 0.4401 c -0.1215 0.1215 -0.1215 0.3187 0 0.4401 l 0.4401 0.4401 c 0.1215 0.1215 0.3187 0.1215 0.4401 0 l 0.4401 -0.4401 c 0.1215 -0.1215 0.1215 -0.3187 0 -0.4401 l -0.4401 -0.4401 Z M -0.5834 0.0012 l 0.5833 -0.0013"/>
 
 

+ 19 - 0
src/PixiEditor.AvaloniaUI/Styles/ToolPickerButton.Styles.axaml

@@ -0,0 +1,19 @@
+<Styles xmlns="https://github.com/avaloniaui"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        xmlns:tools="clr-namespace:PixiEditor.AvaloniaUI.Views.Main.Tools"
+        xmlns:system="clr-namespace:System;assembly=System.Runtime">
+
+    <Styles.Resources>
+        <CornerRadius x:Key="SelectedToolCornerRadius">50</CornerRadius>
+    </Styles.Resources>
+
+    <Style Selector="tools|ToolPickerButton Border">
+        <Setter Property="BorderBrush" Value="Transparent" />
+        <Setter Property="BorderThickness" Value="1" />
+        <Setter Property="CornerRadius" Value="{DynamicResource SelectedToolCornerRadius}" />
+    </Style>
+
+    <Style Selector="tools|ToolPickerButton:selected Border">
+        <Setter Property="BorderBrush" Value="{DynamicResource SelectedToolBorderBrush}" />
+    </Style>
+</Styles>

+ 2 - 1
src/PixiEditor.AvaloniaUI/ViewLocator.cs

@@ -5,6 +5,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
 using Dock.Model.Core;
 using Dock.Model.Core;
 using PixiEditor.AvaloniaUI.ViewModels.Dock;
 using PixiEditor.AvaloniaUI.ViewModels.Dock;
 using PixiEditor.AvaloniaUI.Views.Dock;
 using PixiEditor.AvaloniaUI.Views.Dock;
+using PixiEditor.AvaloniaUI.Views.Main;
 
 
 namespace PixiEditor.AvaloniaUI;
 namespace PixiEditor.AvaloniaUI;
 
 
@@ -12,7 +13,7 @@ public class ViewLocator : IDataTemplate
 {
 {
     public static Dictionary<Type, Type> ViewBindingsMap = new Dictionary<Type, Type>()
     public static Dictionary<Type, Type> ViewBindingsMap = new Dictionary<Type, Type>()
     {
     {
-        [typeof(DockDocumentViewModel)] = typeof(DocumentTemplate)
+        [typeof(DockDocumentViewModel)] = typeof(DocumentTemplate),
     };
     };
 
 
     public Control Build(object? data)
     public Control Build(object? data)

+ 1 - 15
src/PixiEditor.AvaloniaUI/ViewModels/Dock/DockFactory.cs

@@ -56,7 +56,6 @@ internal class DockFactory : Factory
     private IList<IDockable>? BuildDockables()
     private IList<IDockable>? BuildDockables()
     {
     {
         List<IDockable> dockables = new List<IDockable>();
         List<IDockable> dockables = new List<IDockable>();
-        dockables.Add(BuildToolDock());
 
 
         IDockable documentDock = BuildDocumentDock();
         IDockable documentDock = BuildDocumentDock();
 
 
@@ -102,22 +101,9 @@ internal class DockFactory : Factory
         return new ProportionalDock() { Proportion = 0.15 };
         return new ProportionalDock() { Proportion = 0.15 };
     }
     }
 
 
-    private IDockable BuildToolDock()
-    {
-        toolDock = new ToolDock()
-        {
-            Dock = DockMode.Left,
-            CanFloat = false,
-            GripMode = GripMode.Hidden,
-            Id = "ToolsPane",
-            Title = "ToolsPane",
-        };
-
-        return toolDock;
-    }
-
     public override void InitLayout(IDockable layout)
     public override void InitLayout(IDockable layout)
     {
     {
+        // Uhh, don't ask me what to put here, I just copied from the example
         DockableLocator = new Dictionary<string, Func<IDockable?>>()
         DockableLocator = new Dictionary<string, Func<IDockable?>>()
         {
         {
             { "MainLayout", () => mainLayout },
             { "MainLayout", () => mainLayout },

+ 4 - 2
src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/ToolsViewModel.cs

@@ -1,4 +1,5 @@
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.Collections.ObjectModel;
 using System.Linq;
 using System.Linq;
 using Avalonia.Input;
 using Avalonia.Input;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.DependencyInjection;
@@ -75,7 +76,8 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
         }
         }
     }
     }
 
 
-    public List<IToolHandler>? ToolSet { get; private set; }
+    ICollection<IToolHandler> IToolsHandler.ToolSet => ToolSet;
+    public ObservableCollection<IToolHandler> ToolSet { get; private set; }
 
 
     public event EventHandler<SelectedToolEventArgs>? SelectedToolChanged;
     public event EventHandler<SelectedToolEventArgs>? SelectedToolChanged;
 
 
@@ -94,7 +96,7 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
 
 
     public void SetupTools(IServiceProvider services)
     public void SetupTools(IServiceProvider services)
     {
     {
-        ToolSet = services.GetServices<IToolHandler>().ToList();
+        ToolSet = new ObservableCollection<IToolHandler>(services.GetServices<IToolHandler>());
     }
     }
 
 
     public void SetupToolsTooltipShortcuts(IServiceProvider services)
     public void SetupToolsTooltipShortcuts(IServiceProvider services)

+ 27 - 0
src/PixiEditor.AvaloniaUI/Views/Main/Tools/ToolPickerButton.axaml

@@ -0,0 +1,27 @@
+<UserControl xmlns="https://github.com/avaloniaui"
+             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:handlers="clr-namespace:PixiEditor.AvaloniaUI.Models.Handlers"
+             xmlns:xaml="clr-namespace:PixiEditor.AvaloniaUI.Models.Commands.XAML"
+             xmlns:ui="clr-namespace:PixiEditor.Extensions.UI;assembly=PixiEditor.Extensions"
+             xmlns:converters="clr-namespace:PixiEditor.AvaloniaUI.Helpers.Converters"
+             mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+             x:Class="PixiEditor.AvaloniaUI.Views.Main.Tools.ToolPickerButton">
+    <Button Command="{xaml:Command PixiEditor.Tools.SelectTool, UseProvided=true}"
+            CommandParameter="{Binding}"
+            Width="50" Height="40"
+            ui:Translator.TooltipKey="{Binding DisplayName}"
+            Background="{DynamicResource ThemeBackgroundBrush1}">
+        <Button.Template>
+            <ControlTemplate>
+                <Border Height="40" Width="40" Background="{DynamicResource ThemeBackgroundBrush1}">
+                    <ContentPresenter Content="{TemplateBinding Content}"/>
+                </Border>
+            </ControlTemplate>
+        </Button.Template>
+        <Button.Content>
+            <Image Source="{Binding ImagePath, Converter={converters:ImagePathToBitmapConverter}}" Width="30" Height="30"/>
+        </Button.Content>
+    </Button>
+</UserControl>

+ 26 - 0
src/PixiEditor.AvaloniaUI/Views/Main/Tools/ToolPickerButton.axaml.cs

@@ -0,0 +1,26 @@
+using System.Reactive.Linq;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Controls.Metadata;
+
+namespace PixiEditor.AvaloniaUI.Views.Main.Tools;
+
+[PseudoClasses(":selected")]
+public partial class ToolPickerButton : UserControl
+{
+    public static readonly StyledProperty<bool> IsSelectedProperty = AvaloniaProperty.Register<ToolPickerButton, bool>(
+        nameof(IsSelected));
+
+    public bool IsSelected
+    {
+        get => GetValue(IsSelectedProperty);
+        set => SetValue(IsSelectedProperty, value);
+    }
+    public ToolPickerButton()
+    {
+        IObservable<bool> isSelectedObservable = this.GetObservable(IsSelectedProperty);
+        PseudoClasses.Set(":selected", isSelectedObservable);
+        InitializeComponent();
+    }
+}
+

+ 29 - 0
src/PixiEditor.AvaloniaUI/Views/Main/Tools/ToolsPicker.axaml

@@ -0,0 +1,29 @@
+<UserControl xmlns="https://github.com/avaloniaui"
+             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:tools="clr-namespace:PixiEditor.AvaloniaUI.ViewModels.Tools"
+             xmlns:ui="clr-namespace:PixiEditor.Extensions.UI;assembly=PixiEditor.Extensions"
+             xmlns:handlers="clr-namespace:PixiEditor.AvaloniaUI.Models.Handlers"
+             xmlns:converters="clr-namespace:PixiEditor.AvaloniaUI.Helpers.Converters"
+             xmlns:xaml="clr-namespace:PixiEditor.AvaloniaUI.Models.Commands.XAML"
+             xmlns:tools1="clr-namespace:PixiEditor.AvaloniaUI.Views.Main.Tools"
+             mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+             x:Class="PixiEditor.AvaloniaUI.Views.Main.ToolsPicker" Name="picker">
+    <Border CornerRadius="100" Background="{DynamicResource ThemeBackgroundBrush1}">
+        <ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
+        <ItemsControl ItemsSource="{Binding ElementName=picker, Path=Tools}" Padding="0 10">
+            <ItemsControl.ItemTemplate>
+                <DataTemplate DataType="tools:ToolViewModel">
+                    <tools1:ToolPickerButton DataContext="{Binding}" IsSelected="{Binding IsActive}"/>
+                </DataTemplate>
+            </ItemsControl.ItemTemplate>
+            <ItemsControl.ItemsPanel>
+                <ItemsPanelTemplate>
+                    <StackPanel Orientation="Vertical"/>
+                </ItemsPanelTemplate>
+            </ItemsControl.ItemsPanel>
+        </ItemsControl>
+        </ScrollViewer>
+    </Border>
+</UserControl>

+ 27 - 0
src/PixiEditor.AvaloniaUI/Views/Main/Tools/ToolsPicker.axaml.cs

@@ -0,0 +1,27 @@
+using System.Collections.ObjectModel;
+using System.Windows.Input;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using PixiEditor.AvaloniaUI.Models.Handlers;
+using PixiEditor.AvaloniaUI.ViewModels.Tools;
+
+namespace PixiEditor.AvaloniaUI.Views.Main;
+
+internal partial class ToolsPicker : UserControl
+{
+    public static readonly StyledProperty<ObservableCollection<IToolHandler>> ToolsProperty =
+        AvaloniaProperty.Register<ToolsPicker, ObservableCollection<IToolHandler>>(nameof(Tools));
+
+    public ObservableCollection<IToolHandler> Tools
+    {
+        get => GetValue(ToolsProperty);
+        set => SetValue(ToolsProperty, value);
+    }
+
+    public ToolsPicker()
+    {
+        InitializeComponent();
+    }
+}
+

+ 7 - 0
src/PixiEditor.AvaloniaUI/Views/Main/Viewport.axaml

@@ -21,6 +21,8 @@
     xmlns:overlays="clr-namespace:PixiEditor.Views.UserControls.Overlays"
     xmlns:overlays="clr-namespace:PixiEditor.Views.UserControls.Overlays"
     xmlns:lineToolOverlay="clr-namespace:PixiEditor.AvaloniaUI.Views.Overlays.LineToolOverlay"
     xmlns:lineToolOverlay="clr-namespace:PixiEditor.AvaloniaUI.Views.Overlays.LineToolOverlay"
     xmlns:transformOverlay="clr-namespace:PixiEditor.AvaloniaUI.Views.Overlays.TransformOverlay"
     xmlns:transformOverlay="clr-namespace:PixiEditor.AvaloniaUI.Views.Overlays.TransformOverlay"
+    xmlns:main="clr-namespace:PixiEditor.AvaloniaUI.Views.Main"
+    xmlns:viewModels1="clr-namespace:PixiEditor.ViewModels"
     mc:Ignorable="d"
     mc:Ignorable="d"
     x:Name="vpUc"
     x:Name="vpUc"
     d:DesignHeight="450"
     d:DesignHeight="450"
@@ -116,6 +118,11 @@
         </Border>
         </Border>
             </views:TogglableFlyout.Child>
             </views:TogglableFlyout.Child>
         </views:TogglableFlyout>
         </views:TogglableFlyout>
+        <main:ToolsPicker ZIndex="2"
+                          Margin="10 0 0 0"
+                          HorizontalAlignment="Left"
+                          VerticalAlignment="Center"
+                          Tools="{Binding Source={viewModels:MainVM}, Path=ToolsSubViewModel.ToolSet}"/>
         <zoombox:Zoombox
         <zoombox:Zoombox
             Tag="{Binding ElementName=vpUc}"
             Tag="{Binding ElementName=vpUc}"
             x:Name="zoombox"
             x:Name="zoombox"

+ 1 - 0
src/PixiEditor.AvaloniaUI/Views/Main/Viewport.axaml.cs

@@ -22,6 +22,7 @@ namespace PixiEditor.Views.UserControls;
 #nullable enable
 #nullable enable
 internal partial class Viewport : UserControl, INotifyPropertyChanged
 internal partial class Viewport : UserControl, INotifyPropertyChanged
 {
 {
+    //TODO: IDK where to write this, but on close zoom level, when I drag line handle, it doesn't update the canvas
     public event PropertyChangedEventHandler? PropertyChanged;
     public event PropertyChangedEventHandler? PropertyChanged;
 
 
     public static readonly StyledProperty<bool> FlipXProperty =
     public static readonly StyledProperty<bool> FlipXProperty =

+ 0 - 76
src/PixiEditor.AvaloniaUI/Views/MainView.axaml

@@ -27,81 +27,5 @@
         </Grid.RowDefinitions>
         </Grid.RowDefinitions>
         <main1:MainTitleBar/>
         <main1:MainTitleBar/>
         <DockControl Grid.Row="1" Layout="{Binding LayoutDockSubViewModel.Layout}"/>
         <DockControl Grid.Row="1" Layout="{Binding LayoutDockSubViewModel.Layout}"/>
-      <!--<DockControl x:Name="Dock" Grid.Row="1" InitializeLayout="True" InitializeFactory="True">
-      <DockControl.Factory>
-        <Factory />
-      </DockControl.Factory>
-
-      <RootDock x:Name="Root" Id="Root" IsCollapsable="False" DefaultDockable="{Binding #MainLayout}">
-          <DockDock x:Name="MainLayout" Id="MainLayout" >
-              ~1~ Left Pane @1@
-              <ToolDock Dock="Left" CanFloat="False" GripMode="Hidden">
-                    <Tool CanClose="False" CanPin="False" CanFloat="False">
-                        <StackPanel Orientation="Vertical" Spacing="5" Width="40">
-                            <Border Width="40" Height="40" Background="White"/>
-                            <Border Width="40" Height="40" Background="White"/>
-                            <Border Width="40" Height="40" Background="White"/>
-                            <Border Width="40" Height="40" Background="White"/>
-                        </StackPanel>
-                    </Tool>
-              </ToolDock>
-
-
-
-              ~1~ Top Pane @1@
-
-          <ProportionalDock x:Name="TopPane" Id="TopPane" Orientation="Vertical">
-
-            ~1~ Right Pane @1@
-
-            <ProportionalDock x:Name="RightPane" Id="RightPane" Orientation="Horizontal">
-
-              ~1~ Documents Pane @1@
-
-              <DocumentDock x:Name="DocumentsPane" Id="DocumentsPane" CanCreateDocument="True">
-                  <DocumentDock.DocumentTemplate>
-                  <DocumentTemplate>
-
-                  </DocumentTemplate>
-                </DocumentDock.DocumentTemplate>
-              </DocumentDock>
-
-              <ProportionalDockSplitter x:Name="RightSplitter" Id="RightSplitter" />
-
-              <ProportionalDock Orientation="Vertical"  x:Name="RightVerticalPane" Id="RightVerticalPane" Proportion="0.15">
-
-                  ~1~ Properties Pane @1@
-              <ToolDock x:Name="ColorsPane" Id="ColorsPane" Alignment="Right">
-                <Tool x:Name="ColorPicker" Id="ColorPicker" CanClose="False" CanPin="False" Title="Color Picker" x:DataType="Tool">
-                  <TextBlock Text="{Binding Title}"/>
-                </Tool>
-                  <Tool x:Name="ColorSliders" Id="ColorSliders" CanClose="False" CanPin="False" Title="Color Sliders" x:DataType="Tool">
-                      <TextBlock Text="{Binding Title}"/>
-                  </Tool>
-                  <Tool x:Name="Palette" Id="Palette" Title="Palette" CanClose="False" CanPin="False" x:DataType="Tool">
-                      <TextBlock Text="{Binding Title}"/>
-                  </Tool>
-                  <Tool x:Name="Swatches" Id="Swatches" Title="Swatches" CanClose="False" CanPin="False" x:DataType="Tool">
-                      <TextBlock Text="{Binding Title}"/>
-                  </Tool>
-              </ToolDock>
-              <ToolDock x:Name="LayersPane" Id="LayersPane" Alignment="Right">
-                  <Tool CanClose="False" CanPin="False" x:Name="Layers" Id="Layers" Title="Layers" x:DataType="Tool">
-                      <TextBlock Text="{Binding Title}"/>
-                  </Tool>
-              </ToolDock>
-                  <ToolDock x:Name="NavigationPane" Id="NavigationPane" Alignment="Right">
-                      <Tool CanClose="False" CanPin="False" x:Name="Navigation" Id="Navigation" Title="Navigation" x:DataType="Tool">
-                          <TextBlock Text="{Binding Title}"/>
-                      </Tool>
-                  </ToolDock>
-              </ProportionalDock>
-            </ProportionalDock>
-          </ProportionalDock>
-
-        </DockDock>
-      </RootDock>
-
-    </DockControl>-->
     </Grid>
     </Grid>
 </UserControl>
 </UserControl>

+ 12 - 1
src/PixiEditor.AvaloniaUI/Views/Overlays/Handles/Handle.cs

@@ -51,7 +51,7 @@ public abstract class Handle : IHandle
         return TransformHelper.IsWithinHandle(handlePos, pos, zoomboxScale, Size);
         return TransformHelper.IsWithinHandle(handlePos, pos, zoomboxScale, Size);
     }
     }
 
 
-    public static T GetResource<T>(string key)
+    public static T? GetResource<T>(string key)
     {
     {
         if (Application.Current.Styles.TryGetResource(key, null, out object resource))
         if (Application.Current.Styles.TryGetResource(key, null, out object resource))
         {
         {
@@ -71,6 +71,17 @@ public abstract class Handle : IHandle
         return Geometry.Parse("M 0 0 L 1 0 M 0 0 L 0 1");
         return Geometry.Parse("M 0 0 L 1 0 M 0 0 L 0 1");
     }
     }
 
 
+    public static HandleGlyph? GetHandleGlyph(string key)
+    {
+        DrawingGroup? glyph = GetResource<DrawingGroup>(key);
+        if (glyph != null)
+        {
+            return new HandleGlyph(glyph);
+        }
+
+        return null;
+    }
+
     protected static IBrush GetBrush(string key)
     protected static IBrush GetBrush(string key)
     {
     {
         if (Application.Current.Styles.TryGetResource(key, null, out object brush))
         if (Application.Current.Styles.TryGetResource(key, null, out object brush))

+ 47 - 0
src/PixiEditor.AvaloniaUI/Views/Overlays/Handles/HandleGlyph.cs

@@ -0,0 +1,47 @@
+using Avalonia;
+using Avalonia.Media;
+using PixiEditor.DrawingApi.Core.Numerics;
+
+namespace PixiEditor.AvaloniaUI.Views.Overlays.Handles;
+
+public class HandleGlyph
+{
+    public DrawingGroup Glyph { get; set; }
+
+    public VecD Size { get; set; }
+
+    private Rect originalBounds;
+
+    public HandleGlyph(DrawingGroup glyph)
+    {
+        Glyph = glyph;
+        originalBounds = glyph.GetBounds();
+    }
+
+    public void Draw(DrawingContext context, double zoomboxScale, VecD position)
+    {
+        VecD scale = NormalizeGlyph(zoomboxScale);
+        VecD offset = CalculateOffset(zoomboxScale, position);
+
+        Glyph.Transform = new MatrixTransform(
+            new Matrix(
+                scale.X, 0,
+                0, scale.Y,
+                offset.X, offset.Y)
+        );
+        Glyph.Draw(context);
+    }
+
+    private VecD CalculateOffset(double zoomboxScale, VecD position)
+    {
+        return new VecD(position.X - Size.X / (zoomboxScale * 2) - originalBounds.Position.X / (zoomboxScale * 2), position.Y - Size.Y / (zoomboxScale * 2) - originalBounds.Position.Y / (zoomboxScale * 2));
+    }
+
+    private VecD NormalizeGlyph(double scale)
+    {
+        double scaleX = Size.X / originalBounds.Width / scale;
+        double scaleY = Size.Y / originalBounds.Height / scale;
+
+        return new VecD(scaleX, scaleY);
+    }
+}

+ 5 - 10
src/PixiEditor.AvaloniaUI/Views/Overlays/Handles/TransformHandle.cs

@@ -12,10 +12,13 @@ public class TransformHandle : Handle
     public double AnchorRadius { get; set; } = GetResource<double>("AnchorRadius");
     public double AnchorRadius { get; set; } = GetResource<double>("AnchorRadius");
     public IBrush GlyphBrush { get; set; } = GetBrush("HandleGlyphBrush");
     public IBrush GlyphBrush { get; set; } = GetBrush("HandleGlyphBrush");
 
 
-    private Geometry handleGeometry = GetHandleGeometry("MoveHandle");
+    private HandleGlyph handleGeometry;
 
 
     public TransformHandle(Control owner) : base(owner)
     public TransformHandle(Control owner) : base(owner)
     {
     {
+        handleGeometry = GetHandleGlyph("MoveHandle");
+        handleGeometry.Size = Size - new VecD(1, 1);
+
         Cursor = new Cursor(StandardCursorType.SizeAll);
         Cursor = new Cursor(StandardCursorType.SizeAll);
     }
     }
 
 
@@ -25,14 +28,6 @@ public class TransformHandle : Handle
         double radius = AnchorRadius * scaleMultiplier;
         double radius = AnchorRadius * scaleMultiplier;
 
 
         context.DrawRectangle(HandleBrush, HandlePen, TransformHelper.ToHandleRect(Position, Size, ZoomboxScale), radius, radius);
         context.DrawRectangle(HandleBrush, HandlePen, TransformHelper.ToHandleRect(Position, Size, ZoomboxScale), radius, radius);
-        double crossSize = HandleRect.Size.X - 1;
-
-        handleGeometry.Transform = new MatrixTransform(
-            new Matrix(
-                0, crossSize / ZoomboxScale,
-                crossSize / ZoomboxScale, 0,
-                Position.X - crossSize / (ZoomboxScale * 2), Position.Y - crossSize / (ZoomboxScale * 2))
-        );
-        context.DrawGeometry(GlyphBrush, null, handleGeometry);
+        handleGeometry.Draw(context, ZoomboxScale, Position);
     }
     }
 }
 }

+ 4 - 0
src/PixiEditor.UI.Common/Accents/Base.axaml

@@ -32,6 +32,8 @@
 
 
             <Color x:Key="NotificationCardBackgroundColor">#303030</Color>
             <Color x:Key="NotificationCardBackgroundColor">#303030</Color>
 
 
+            <Color x:Key="SelectedToolBorderColor">#fff</Color>
+
             <system:Double x:Key="ThemeDisabledOpacity">0.4</system:Double>
             <system:Double x:Key="ThemeDisabledOpacity">0.4</system:Double>
 
 
             <SolidColorBrush x:Key="ThemeBackgroundBrush" Color="{StaticResource ThemeBackgroundColor}" />
             <SolidColorBrush x:Key="ThemeBackgroundBrush" Color="{StaticResource ThemeBackgroundColor}" />
@@ -59,6 +61,8 @@
             <SolidColorBrush x:Key="ErrorBrush" Color="{StaticResource ErrorColor}" />
             <SolidColorBrush x:Key="ErrorBrush" Color="{StaticResource ErrorColor}" />
             <SolidColorBrush x:Key="GlyphBrush" Color="{StaticResource GlyphColor}"/>
             <SolidColorBrush x:Key="GlyphBrush" Color="{StaticResource GlyphColor}"/>
 
 
+            <SolidColorBrush x:Key="SelectedToolBorderBrush" Color="{StaticResource SelectedToolBorderColor}"/>
+
             <CornerRadius x:Key="ControlCornerRadius">5</CornerRadius>
             <CornerRadius x:Key="ControlCornerRadius">5</CornerRadius>
             <system:Double x:Key="ControlCornerRadiusValue">5</system:Double>
             <system:Double x:Key="ControlCornerRadiusValue">5</system:Double>
             <Thickness x:Key="ThemeBorderThickness">1</Thickness>
             <Thickness x:Key="ThemeBorderThickness">1</Thickness>

+ 1 - 3
src/PixiEditor.UI.Common/Controls/Dock/Controls/DockControl.axaml

@@ -27,9 +27,7 @@
             <DataTemplate DataType="dmc:IDocumentDock">
             <DataTemplate DataType="dmc:IDocumentDock">
               <DocumentDockControl />
               <DocumentDockControl />
             </DataTemplate>
             </DataTemplate>
-            <DataTemplate DataType="dmc:IToolDock">
-              <ToolDockControl />
-            </DataTemplate>
+
             <DataTemplate DataType="dmc:IProportionalDock">
             <DataTemplate DataType="dmc:IProportionalDock">
               <ProportionalDockControl />
               <ProportionalDockControl />
             </DataTemplate>
             </DataTemplate>