Răsfoiți Sursa

Icons, bold and italic

Krzysztof Krysiński 7 luni în urmă
părinte
comite
208f99afce

+ 17 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/RenderNode.cs

@@ -5,6 +5,7 @@ using PixiEditor.ChangeableDocument.Rendering;
 using Drawie.Backend.Core.Surfaces;
 using Drawie.Backend.Core.Surfaces.ImageData;
 using Drawie.Numerics;
+using PixiEditor.ChangeableDocument.Changeables.Interfaces;
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 
@@ -67,6 +68,22 @@ public abstract class RenderNode : Node, IPreviewRenderable, IHighDpiRenderNode
         return textureCache.RequestTexture(id, size, processingCs, clear);
     }
 
+    public override void SerializeAdditionalData(Dictionary<string, object> additionalData)
+    {
+        base.SerializeAdditionalData(additionalData);
+        additionalData["AllowHighDpiRendering"] = AllowHighDpiRendering;
+    }
+
+    internal override OneOf<None, IChangeInfo, List<IChangeInfo>> DeserializeAdditionalData(IReadOnlyDocument target, IReadOnlyDictionary<string, object> data)
+    {
+        base.DeserializeAdditionalData(target, data);
+
+        if(data.TryGetValue("AllowHighDpiRendering", out var value))
+            AllowHighDpiRendering = (bool)value;
+
+        return new None();
+    }
+
     public override void Dispose()
     {
         base.Dispose();

+ 40 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/TextVectorData.cs

@@ -36,11 +36,31 @@ public class TextVectorData : ShapeVectorData, IReadOnlyTextData
         get => font;
         set
         {
+            if (value != null)
+            {
+                value.Changed -= FontChanged;
+            }
+
             font = value;
+            if (value != null)
+            {
+                value.Changed += FontChanged;
+            }
+
             lastBounds = richText.MeasureBounds(value);
         }
     }
 
+    private void FontChanged()
+    {
+        if (richText == null)
+        {
+            return;
+        }
+
+        lastBounds = richText.MeasureBounds(Font);
+    }
+
     public double? Spacing
     {
         get => spacing;
@@ -56,6 +76,11 @@ public class TextVectorData : ShapeVectorData, IReadOnlyTextData
 
     protected override void OnStrokeWidthChanged()
     {
+        if(richText == null)
+        {
+            return;
+        }
+
         richText.StrokeWidth = StrokeWidth;
         lastBounds = richText.MeasureBounds(Font);
     }
@@ -79,6 +104,17 @@ public class TextVectorData : ShapeVectorData, IReadOnlyTextData
     private RichText richText;
     private RectD lastBounds;
 
+    public TextVectorData()
+    {
+
+    }
+
+    public TextVectorData(string text)
+    {
+        Text = text;
+    }
+
+
     public override VectorPath ToPath()
     {
         var path = richText.ToPath(Font);
@@ -153,6 +189,10 @@ public class TextVectorData : ShapeVectorData, IReadOnlyTextData
             textData.Font.Size = Font.Size;
             textData.Font.Edging = Font.Edging;
             textData.Font.SubPixel = Font.SubPixel;
+            textData.Font.Bold = Font.Bold;
+            textData.Font.Italic = Font.Italic;
+
+            textData.lastBounds = lastBounds;
         }
     }
 

+ 0 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/TextNode.cs

@@ -77,6 +77,5 @@ public class TextNode : ShapeNode<TextVectorData>
     public override void Dispose()
     {
         base.Dispose();
-        cachedData?.Font.Dispose();
     }
 }

+ 6 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/VectorLayerNode.cs

@@ -173,6 +173,11 @@ public class VectorLayerNode : LayerNode, ITransformableObject, IReadOnlyVectorN
 
     public override Node CreateCopy()
     {
-        return new VectorLayerNode() { ShapeData = (ShapeVectorData?)ShapeData?.Clone(), ClipToPreviousMember = this.ClipToPreviousMember };
+        return new VectorLayerNode()
+        {
+            ShapeData = (ShapeVectorData?)ShapeData?.Clone(),
+            ClipToPreviousMember = this.ClipToPreviousMember,
+            AllowHighDpiRendering = this.AllowHighDpiRendering
+        };
     }
 }

+ 47 - 28
src/PixiEditor.UI.Common/Fonts/PixiPerfectIcons.axaml

@@ -1,10 +1,10 @@
 <Styles xmlns="https://github.com/avaloniaui"
-                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
-                    xmlns:system="clr-namespace:System;assembly=System.Runtime">
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        xmlns:system="clr-namespace:System;assembly=System.Runtime">
     <Styles.Resources>
         <ResourceDictionary>
             <FontFamily x:Key="PixiPerfectIcons">avares://PixiEditor.UI.Common/Fonts/PixiPerfect.ttf#PixiPerfect</FontFamily>
-            
+
             <system:String x:Key="icon-add-reference">&#xE900;</system:String>
             <system:String x:Key="icon-add-to-mask">&#xE901;</system:String>
             <system:String x:Key="icon-alpha-lock">&#xE902;</system:String>
@@ -116,7 +116,7 @@
             <system:String x:Key="icon-copy-add">&#xe921;</system:String>
             <system:String x:Key="icon-check">&#xe96a;</system:String>
             <system:String x:Key="icon-dot">&#xe963;</system:String>
-            
+
             <system:String x:Key="icon-paste-reference-layer">&#xe977;</system:String>
             <system:String x:Key="icon-paste-as-new-layer">&#xe978;</system:String>
             <system:String x:Key="icon-star">&#xe97c;</system:String>
@@ -133,46 +133,65 @@
             <system:String x:Key="icon-swatches">&#xE982;</system:String>
             <system:String x:Key="icon-nodes">&#xe984;</system:String>
             <system:String x:Key="icon-onion">&#xe985;</system:String>
-            
+
             <system:String x:Key="icon-lowres-circle">&#xe986;</system:String>
             <system:String x:Key="icon-snapping">&#xe987;</system:String>
             <system:String x:Key="icon-lowres-square">&#xe988;</system:String>
             <system:String x:Key="icon-lowres-line">&#xe989;</system:String>
+
+            <system:String x:Key="icon-align-center">&#xE98C;</system:String>
+            <system:String x:Key="icon-bold">&#xE98D;</system:String>
+            <system:String x:Key="icon-text-antialiased">&#xE98E;</system:String>
+            <system:String x:Key="icon-italic">&#xE98F;</system:String>
+            <system:String x:Key="icon-align-stretch">&#xE990;</system:String>
+            <system:String x:Key="icon-align-left">&#xE991;</system:String>
+            <system:String x:Key="icon-letter-spacing">&#xE992;</system:String>
+            <system:String x:Key="icon-line-height">&#xE993;</system:String>
+            <system:String x:Key="icon-text-pixel">&#xE994;</system:String>
+            <system:String x:Key="icon-align-right">&#xE995;</system:String>
+            <system:String x:Key="icon-strikethrough">&#xE996;</system:String>
+            <system:String x:Key="icon-linked-pipette">&#xE997;</system:String>
+            <system:String x:Key="icon-text-underline">&#xE998;</system:String>
+            <system:String x:Key="icon-text-round">&#xE999;</system:String>
         </ResourceDictionary>
     </Styles.Resources>
-    
+
     <Style Selector="TextBlock.pixi-icon">
-        <Setter Property="FontFamily" Value="{DynamicResource PixiPerfectIcons}"/>
+        <Setter Property="FontFamily" Value="{DynamicResource PixiPerfectIcons}" />
     </Style>
-    
+
+    <Style Selector="Label.pixi-icon">
+        <Setter Property="FontFamily" Value="{DynamicResource PixiPerfectIcons}" />
+    </Style>
+
     <Style Selector="Run.pixi-icon">
-        <Setter Property="FontFamily" Value="{DynamicResource PixiPerfectIcons}"/>
+        <Setter Property="FontFamily" Value="{DynamicResource PixiPerfectIcons}" />
     </Style>
-    
+
     <Style Selector="Button.pixi-icon">
-        <Setter Property="FontFamily" Value="{DynamicResource PixiPerfectIcons}"/>
-        <Setter Property="Background" Value="Transparent"/>
-        <Setter Property="FontSize" Value="24"/>
-        <Setter Property="Padding" Value="0"/>
-        <Setter Property="HorizontalContentAlignment" Value="Center"/>
-        <Setter Property="VerticalContentAlignment" Value="Center"/>
+        <Setter Property="FontFamily" Value="{DynamicResource PixiPerfectIcons}" />
+        <Setter Property="Background" Value="Transparent" />
+        <Setter Property="FontSize" Value="24" />
+        <Setter Property="Padding" Value="0" />
+        <Setter Property="HorizontalContentAlignment" Value="Center" />
+        <Setter Property="VerticalContentAlignment" Value="Center" />
     </Style>
-    
+
     <Style Selector="Button.pixi-icon:pointerover">
-        <Setter Property="Background" Value="Transparent"/>
+        <Setter Property="Background" Value="Transparent" />
     </Style>
-    
+
     <Style Selector="ToggleButton.pixi-icon">
-        <Setter Property="FontFamily" Value="{DynamicResource PixiPerfectIcons}"/>
-        <Setter Property="BorderThickness" Value="0"/>
-        <Setter Property="Background" Value="Transparent"/>
-        <Setter Property="FontSize" Value="24"/>
-        <Setter Property="Padding" Value="0"/>
-        <Setter Property="HorizontalContentAlignment" Value="Center"/>
-        <Setter Property="VerticalContentAlignment" Value="Center"/>
+        <Setter Property="FontFamily" Value="{DynamicResource PixiPerfectIcons}" />
+        <Setter Property="BorderThickness" Value="0" />
+        <Setter Property="Background" Value="Transparent" />
+        <Setter Property="FontSize" Value="24" />
+        <Setter Property="Padding" Value="0" />
+        <Setter Property="HorizontalContentAlignment" Value="Center" />
+        <Setter Property="VerticalContentAlignment" Value="Center" />
     </Style>
-    
+
     <Style Selector="ToggleButton.pixi-icon:checked">
-        <Setter Property="Background" Value="{DynamicResource ThemeControlHighBrush}"/>
+        <Setter Property="Background" Value="{DynamicResource ThemeControlHighBrush}" />
     </Style>
 </Styles>

+ 16 - 1
src/PixiEditor.UI.Common/Fonts/PixiPerfectIcons.axaml.cs

@@ -128,7 +128,7 @@ public static class PixiPerfectIcons
     public const string Nodes = "\uE984";
     public const string Onion = "\uE965";
         
-    public const string Reset = "R"; // TODO: Create a reset icon
+    public const string Reset = "\uE98A";
     public const string ToggleLayerVisible = "\u25a1;"; // TODO: Create a toggle layer visible icon
     public const string ToggleMask = "\u25a1;"; // TODO: Create a toggle mask icon
     public const string Pen = "\uE971";
@@ -137,6 +137,21 @@ public static class PixiPerfectIcons
     public const string LowResSquare = "\uE988";
     public const string LowResLine = "\uE989";
 
+    public const string AlignCenter = "\uE98C";
+    public const string Bold = "\uE98D";
+    public const string TextAntialiased = "\uE98E";
+    public const string Italic = "\uE98F";
+    public const string AlignStretch = "\uE990";
+    public const string AlignLeft = "\uE991";
+    public const string LetterSpacing = "\uE992";
+    public const string LineHeight = "\uE993";
+    public const string TextPixel = "\uE994";
+    public const string AlignRight = "\uE995";
+    public const string Strikethrough = "\uE996";
+    public const string LinkedPipette = "\uE997";
+    public const string TextUnderline = "\uE998";
+    public const string TextRound = "\uE999";
+
     public static Stream GetFontStream()
     {
         return AssetLoader.Open(new Uri("avares://PixiEditor.UI.Common/Fonts/PixiPerfect.ttf"));

+ 4 - 2
src/PixiEditor/Data/Configs/ToolSetsConfig.json

@@ -24,7 +24,8 @@
         "Settings": {
           "AntiAliasing": false,
           "ForceLowDpiRendering": true
-        }
+        },
+        "Icon": "\ue994"
       },
       {
         "ToolName": "Eraser",
@@ -92,7 +93,8 @@
         "Settings": {
           "AntiAliasing": true,
           "ForceLowDpiRendering": true
-        }
+        },
+        "Icon": "\ue98E"
       },
       {
         "ToolName": "Eraser",

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

@@ -845,5 +845,7 @@
   "TEXT_TOOL": "Text",
   "MISSING_FONT": "Missing font",
   "TEXT_LAYER_NAME": "Text",
-  "TEXT_TOOL_TOOLTIP": "Create text ({0})."
+  "TEXT_TOOL_TOOLTIP": "Create text ({0}).",
+  "BOLD_TOOLTIP": "Bold",
+  "ITALIC_TOOLTIP": "Italic"
 }

+ 5 - 1
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/VectorTextToolExecutor.cs

@@ -64,6 +64,8 @@ internal class VectorTextToolExecutor : UpdateableChangeExecutor, ITextOverlayEv
             toolbar.FontFamily = textData.Font.Family;
             toolbar.FontSize = textData.Font.Size;
             toolbar.Spacing = textData.Spacing ?? textData.Font.Size;
+            toolbar.Bold = textData.Font.Bold;
+            toolbar.Italic = textData.Font.Italic;
 
             lastText = textData.Text;
             position = textData.Position;
@@ -120,7 +122,7 @@ internal class VectorTextToolExecutor : UpdateableChangeExecutor, ITextOverlayEv
             cachedFont = toolbar.ConstructFont();
             document.TextOverlayHandler.Font = cachedFont;
         }
-        else if (name is nameof(ITextToolbar.FontSize))
+        else
         {
             if (cachedFont == null)
             {
@@ -129,6 +131,8 @@ internal class VectorTextToolExecutor : UpdateableChangeExecutor, ITextOverlayEv
 
             document.TextOverlayHandler.Font.Size = toolbar.FontSize;
             cachedFont.Size = toolbar.FontSize;
+            cachedFont.Bold = toolbar.Bold;
+            cachedFont.Italic = toolbar.Italic;
         }
 
         var constructedText = ConstructTextData(lastText);

+ 2 - 0
src/PixiEditor/Models/Handlers/Toolbars/ITextToolbar.cs

@@ -8,6 +8,8 @@ internal interface ITextToolbar : IFillableShapeToolbar
     public FontFamilyName FontFamily { get; set; }
     public double Spacing { get; set; }
     public bool ForceLowDpiRendering { get; set; }
+    public bool Bold { get; set; }
+    public bool Italic { get; set; }
 
     public Font ConstructFont();
 }

+ 13 - 3
src/PixiEditor/Models/Serialization/Factories/TextSerializationFactory.cs

@@ -26,6 +26,9 @@ internal class TextSerializationFactory : VectorShapeSerializationFactory<TextVe
         }
 
         builder.AddDouble(original.Font.Size);
+        builder.AddBool(original.Font.Bold);
+        builder.AddBool(original.Font.Italic);
+
         builder.AddDouble(original.MaxWidth);
         builder.AddDouble(original.Spacing ?? original.Font.Size);
         builder.AddBool(original.Path != null);
@@ -52,6 +55,9 @@ internal class TextSerializationFactory : VectorShapeSerializationFactory<TextVe
         }
 
         double fontSize = extractor.GetDouble();
+        bool bold = extractor.GetBool();
+        bool italic = extractor.GetBool();
+
         double maxWidth = extractor.GetDouble();
         double spacing = extractor.GetDouble();
         bool hasPath = extractor.GetBool();
@@ -65,7 +71,7 @@ internal class TextSerializationFactory : VectorShapeSerializationFactory<TextVe
             new FontFamilyName(fontFamily) { FontUri = isFontFromFile ? new Uri(fontPath, UriKind.Absolute) : null };
         Font font = Font.FromFontFamily(family);
         FontFamilyName? missingFamily = null;
-        
+
         if (font == null)
         {
             font = Font.CreateDefault();
@@ -76,16 +82,20 @@ internal class TextSerializationFactory : VectorShapeSerializationFactory<TextVe
             FontLibrary.TryAddCustomFont(family);
         }
 
+
+        font.Bold = bold;
+        font.Italic = italic;
+        font.Edging = antiAlias ? FontEdging.AntiAlias : FontEdging.Alias;
+        font.SubPixel = antiAlias;
         font.Size = fontSize;
 
-        original = new TextVectorData()
+        original = new TextVectorData(text)
         {
             TransformationMatrix = matrix,
             StrokeColor = strokeColor,
             Fill = fill,
             FillColor = fillColor,
             StrokeWidth = strokeWidth,
-            Text = text,
             Position = position,
             Font = font,
             MaxWidth = maxWidth,

+ 5 - 0
src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/Setting.cs

@@ -94,7 +94,12 @@ internal abstract class Setting : ObservableObject
 
     public LocalizedString Label { get; set; }
 
+    public string Icon { get; set; }
+
+    public string Tooltip { get; set; }
+
     public bool HasLabel => !string.IsNullOrEmpty(Label);
+    public bool HasIcon => !string.IsNullOrEmpty(Icon);
 
     public object UserValue
     {

+ 4 - 1
src/PixiEditor/ViewModels/Tools/ToolSettings/Toolbars/ShapeToolbar.cs

@@ -1,5 +1,6 @@
 using Avalonia.Media;
 using PixiEditor.Models.Handlers.Toolbars;
+using PixiEditor.UI.Common.Fonts;
 using PixiEditor.ViewModels.Tools.ToolSettings.Settings;
 
 namespace PixiEditor.ViewModels.Tools.ToolSettings.Toolbars;
@@ -59,7 +60,9 @@ internal class ShapeToolbar : Toolbar, IShapeToolbar
             IsExposed = false, Value = false
         });
         AddSetting(
-            new BoolSettingViewModel(nameof(SyncWithPrimaryColor), "SYNC_WITH_PRIMARY_COLOR_LABEL") { Value = true });
+            new BoolSettingViewModel(nameof(SyncWithPrimaryColor))
+                { Value = true, Icon = PixiPerfectIcons.LinkedPipette,
+                    Tooltip = "SYNC_WITH_PRIMARY_COLOR_LABEL"});
         AddSetting(new ColorSettingViewModel(nameof(StrokeColor), "STROKE_COLOR_LABEL"));
     }
 }

+ 44 - 3
src/PixiEditor/ViewModels/Tools/ToolSettings/Toolbars/TextToolbar.cs

@@ -2,6 +2,7 @@
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Handlers.Toolbars;
+using PixiEditor.UI.Common.Fonts;
 using PixiEditor.ViewModels.Tools.ToolSettings.Settings;
 
 namespace PixiEditor.ViewModels.Tools.ToolSettings.Toolbars;
@@ -62,9 +63,33 @@ internal class TextToolbar : FillableShapeToolbar, ITextToolbar
         }
     }
 
+    public bool Bold
+    {
+        get
+        {
+            return GetSetting<BoolSettingViewModel>(nameof(Bold)).Value;
+        }
+        set
+        {
+            GetSetting<BoolSettingViewModel>(nameof(Bold)).Value = value;
+        }
+    }
+
+    public bool Italic
+    {
+        get
+        {
+            return GetSetting<BoolSettingViewModel>(nameof(Italic)).Value;
+        }
+        set
+        {
+            GetSetting<BoolSettingViewModel>(nameof(Italic)).Value = value;
+        }
+    }
+
     public TextToolbar()
     {
-        AddSetting(new FontFamilySettingViewModel(nameof(FontFamily), "FONT_LABEL"));
+        AddSetting(new FontFamilySettingViewModel(nameof(FontFamily), ""));
         FontFamily = FontLibrary.DefaultFontFamily;
         
         var sizeSetting =
@@ -74,7 +99,11 @@ internal class TextToolbar : FillableShapeToolbar, ITextToolbar
             };
         AddSetting(sizeSetting);
         var spacingSetting =
-            new SizeSettingViewModel(nameof(Spacing), "SPACING_LABEL", unit: new LocalizedString("UNIT_PT"));
+            new SizeSettingViewModel(nameof(Spacing), unit: new LocalizedString("UNIT_PT"))
+            {
+                Tooltip = "SPACING_LABEL",
+                Icon = PixiPerfectIcons.LineHeight
+            };
         spacingSetting.Value = 12;
 
         sizeSetting.ValueChanged += (sender, args) =>
@@ -84,7 +113,17 @@ internal class TextToolbar : FillableShapeToolbar, ITextToolbar
         };
 
         AddSetting(spacingSetting);
-        
+
+        AddSetting(new BoolSettingViewModel(nameof(Bold))
+        {
+            Icon = PixiPerfectIcons.Bold, Tooltip = "BOLD_TOOLTIP"
+        });
+
+        AddSetting(new BoolSettingViewModel(nameof(Italic))
+        {
+            Icon = PixiPerfectIcons.Italic, Tooltip = "ITALIC_TOOLTIP"
+        });
+
         AddSetting(new BoolSettingViewModel(nameof(ForceLowDpiRendering), "__force_low_dpi_rendering")
         {
             IsExposed = false, Value = false
@@ -106,6 +145,8 @@ internal class TextToolbar : FillableShapeToolbar, ITextToolbar
 
         font.Size = (float)FontSize;
         font.Edging = AntiAliasing ? FontEdging.AntiAlias : FontEdging.Alias;
+        font.Bold = Bold;
+        font.Italic = Italic;
 
         return font;
     }

+ 3 - 0
src/PixiEditor/ViewModels/Tools/Tools/TextToolViewModel.cs

@@ -5,6 +5,7 @@ using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Models.Commands.Attributes.Commands;
 using PixiEditor.Models.Handlers;
 using PixiEditor.Models.Handlers.Tools;
+using PixiEditor.UI.Common.Fonts;
 using PixiEditor.ViewModels.Tools.ToolSettings.Toolbars;
 
 namespace PixiEditor.ViewModels.Tools.Tools;
@@ -17,6 +18,8 @@ internal class TextToolViewModel : ToolViewModel, ITextToolHandler
     public override Type LayerTypeToCreateOnEmptyUse => typeof(VectorLayerNode);
     public override LocalizedString Tooltip => new LocalizedString("TEXT_TOOL_TOOLTIP", Shortcut);
 
+    public override string DefaultIcon => PixiPerfectIcons.TextRound;
+
     public override bool IsErasable => false;
     public override bool StopsLinkedToolOnUse => false;
 

+ 11 - 1
src/PixiEditor/Views/Main/Tools/Toolbar.axaml

@@ -55,7 +55,8 @@
                        ui:Translator.Key="{Binding ToolsSubViewModel.ActiveTool.DisplayName.Key}"
                        ui:Translator.TooltipLocalizedString="{Binding ToolsSubViewModel.ActiveTool.ActionDisplay}" />
             </StackPanel>
-            <ItemsControl VerticalAlignment="Center" Grid.Column="1" IsVisible="{Binding ElementName=CollapseButton, Path=!IsChecked}"
+            <ItemsControl VerticalAlignment="Center" Grid.Column="1"
+                          IsVisible="{Binding ElementName=CollapseButton, Path=!IsChecked}"
                           ItemsSource="{Binding ToolsSubViewModel.ActiveTool.Toolbar.Settings}">
                 <ItemsControl.ItemsPanel>
                     <ItemsPanelTemplate>
@@ -69,7 +70,16 @@
                             <Label
                                 IsVisible="{Binding HasLabel}" VerticalAlignment="Center"
                                 Foreground="{DynamicResource ThemeForegroundBrush}"
+                                ui:Translator.TooltipKey="{Binding Tooltip}"
                                 ui:Translator.Key="{Binding Label.Key}" />
+                            <TextBlock
+                                IsVisible="{Binding HasIcon}" VerticalAlignment="Center"
+                                Foreground="{DynamicResource ThemeForegroundBrush}"
+                                ui:Translator.TooltipKey="{Binding Tooltip}"
+                                Classes="pixi-icon"
+                                FontSize="18"
+                                Padding="5 0"
+                                Text="{Binding Icon}" />
                             <ContentControl VerticalAlignment="Center" Content="{Binding }" />
                         </StackPanel>
                     </DataTemplate>

+ 13 - 16
src/PixiEditor/Views/Overlays/TextOverlay/TextOverlay.cs

@@ -519,24 +519,21 @@ internal class TextOverlay : Overlay
 
     private void DeleteChar(int direction)
     {
-        if (Text.Length > 0 && CursorPosition + direction >= 0 && CursorPosition + direction < Text.Length)
+        if (SelectionEnd != CursorPosition)
         {
-            if (SelectionEnd == CursorPosition)
-            {
-                Text = Text.Remove(CursorPosition + direction, 1);
-                CursorPosition += direction;
-                SelectionEnd = CursorPosition;
-            }
-            else
-            {
-                Text = Text.Remove(Math.Min(CursorPosition, SelectionEnd),
-                    Math.Abs(CursorPosition - SelectionEnd));
-                CursorPosition = Math.Min(CursorPosition, SelectionEnd);
-                SelectionEnd = CursorPosition;
-            }
-
-            lastXMovementCursorIndex = CursorPosition;
+            Text = Text.Remove(Math.Min(CursorPosition, SelectionEnd),
+                Math.Abs(CursorPosition - SelectionEnd));
+            CursorPosition = Math.Min(CursorPosition, SelectionEnd);
+            SelectionEnd = CursorPosition;
+        }
+        else if (Text.Length > 0 && CursorPosition + direction >= 0 && CursorPosition + direction < Text.Length)
+        {
+            Text = Text.Remove(CursorPosition + direction, 1);
+            CursorPosition += direction;
+            SelectionEnd = CursorPosition;
         }
+
+        lastXMovementCursorIndex = CursorPosition;
     }
 
     private void MoveCursorBy(VecI direction, bool updateSelection = true, MoveMode mode = MoveMode.Characters)