Browse Source

Text tool click and drag

Krzysztof Krysiński 2 months ago
parent
commit
d5f84de87b

BIN
src/PixiEditor.UI.Common/Fonts/PixiPerfect.ttf


+ 3 - 0
src/PixiEditor.UI.Common/Fonts/PixiPerfectIcons.axaml

@@ -35,6 +35,7 @@
             <system:String x:Key="icon-circle">&#xE930;</system:String>
             <system:String x:Key="icon-circle">&#xE930;</system:String>
             <system:String x:Key="icon-clock">&#xE931;</system:String>
             <system:String x:Key="icon-clock">&#xE931;</system:String>
             <system:String x:Key="icon-closed-grid">&#xE913;</system:String>
             <system:String x:Key="icon-closed-grid">&#xE913;</system:String>
+            <system:String x:Key="icon-coins">&#xE9C5;</system:String>
             <system:String x:Key="icon-color-palette">&#xE932;</system:String>
             <system:String x:Key="icon-color-palette">&#xE932;</system:String>
             <system:String x:Key="icon-color-picker">&#xE933;</system:String>
             <system:String x:Key="icon-color-picker">&#xE933;</system:String>
             <system:String x:Key="icon-color-sliders">&#xE934;</system:String>
             <system:String x:Key="icon-color-sliders">&#xE934;</system:String>
@@ -48,6 +49,7 @@
             <system:String x:Key="icon-create-mask">&#xE93A;</system:String>
             <system:String x:Key="icon-create-mask">&#xE93A;</system:String>
             <system:String x:Key="icon-crop">&#xE93C;</system:String>
             <system:String x:Key="icon-crop">&#xE93C;</system:String>
             <system:String x:Key="icon-crop-to-selection">&#xE93B;</system:String>
             <system:String x:Key="icon-crop-to-selection">&#xE93B;</system:String>
+            <system:String x:Key="icon-crosshair">&#xE9C6;</system:String>
             <system:String x:Key="icon-crossroad">&#xE91D;</system:String>
             <system:String x:Key="icon-crossroad">&#xE91D;</system:String>
             <system:String x:Key="icon-database">&#xE93D;</system:String>
             <system:String x:Key="icon-database">&#xE93D;</system:String>
             <system:String x:Key="icon-deselect">&#xE93E;</system:String>
             <system:String x:Key="icon-deselect">&#xE93E;</system:String>
@@ -113,6 +115,7 @@
             <system:String x:Key="icon-lowres-square">&#xE9A8;</system:String>
             <system:String x:Key="icon-lowres-square">&#xE9A8;</system:String>
             <system:String x:Key="icon-magic">&#xE90D;</system:String>
             <system:String x:Key="icon-magic">&#xE90D;</system:String>
             <system:String x:Key="icon-magic-wand">&#xE95D;</system:String>
             <system:String x:Key="icon-magic-wand">&#xE95D;</system:String>
+            <system:String x:Key="icon-map">&#xE9C4;</system:String>
             <system:String x:Key="icon-mask-ghost">&#xE99E;</system:String>
             <system:String x:Key="icon-mask-ghost">&#xE99E;</system:String>
             <system:String x:Key="icon-merge">&#xE95F;</system:String>
             <system:String x:Key="icon-merge">&#xE95F;</system:String>
             <system:String x:Key="icon-message">&#xE98F;</system:String>
             <system:String x:Key="icon-message">&#xE98F;</system:String>

+ 3 - 0
src/PixiEditor.UI.Common/Fonts/PixiPerfectIcons.axaml.cs

@@ -31,6 +31,7 @@ public static partial class PixiPerfectIcons
     public const string Circle = "\uE930";
     public const string Circle = "\uE930";
     public const string Clock = "\uE931";
     public const string Clock = "\uE931";
     public const string ClosedGrid = "\uE913";
     public const string ClosedGrid = "\uE913";
+    public const string Coins = "\uE9C5";
     public const string ColorPalette = "\uE932";
     public const string ColorPalette = "\uE932";
     public const string ColorPicker = "\uE933";
     public const string ColorPicker = "\uE933";
     public const string ColorSliders = "\uE934";
     public const string ColorSliders = "\uE934";
@@ -44,6 +45,7 @@ public static partial class PixiPerfectIcons
     public const string CreateMask = "\uE93A";
     public const string CreateMask = "\uE93A";
     public const string Crop = "\uE93C";
     public const string Crop = "\uE93C";
     public const string CropToSelection = "\uE93B";
     public const string CropToSelection = "\uE93B";
+    public const string Crosshair = "\uE9C6";
     public const string Crossroad = "\uE91D";
     public const string Crossroad = "\uE91D";
     public const string Database = "\uE93D";
     public const string Database = "\uE93D";
     public const string Deselect = "\uE93E";
     public const string Deselect = "\uE93E";
@@ -109,6 +111,7 @@ public static partial class PixiPerfectIcons
     public const string LowresSquare = "\uE9A8";
     public const string LowresSquare = "\uE9A8";
     public const string Magic = "\uE90D";
     public const string Magic = "\uE90D";
     public const string MagicWand = "\uE95D";
     public const string MagicWand = "\uE95D";
+    public const string Map = "\uE9C4";
     public const string MaskGhost = "\uE99E";
     public const string MaskGhost = "\uE99E";
     public const string Merge = "\uE95F";
     public const string Merge = "\uE95F";
     public const string Message = "\uE98F";
     public const string Message = "\uE98F";

+ 3 - 0
src/PixiEditor.UI.Common/Fonts/defs.svg

@@ -219,4 +219,7 @@
 <glyph unicode="&#xe9c1;" glyph-name="step-forward" data-tags="step-forward" d="M213.333 789.333c0 23.552 19.115 42.667 42.667 42.667s42.667-19.115 42.667-42.667v-682.667c0-23.552-19.115-42.667-42.667-42.667s-42.667 19.115-42.667 42.667v682.667zM453.333 822.656l426.667-341.333c10.112-8.107 16-20.352 16-33.323s-5.888-25.216-16-33.323l-426.667-341.333c-12.8-10.24-30.379-12.245-45.141-5.12-14.805 7.083-24.192 22.059-24.192 38.443v682.667c0 16.384 9.387 31.36 24.192 38.443 14.763 7.125 32.341 5.12 45.141-5.12zM469.333 700.544v-505.088l315.691 252.544-315.691 252.544z" />
 <glyph unicode="&#xe9c1;" glyph-name="step-forward" data-tags="step-forward" d="M213.333 789.333c0 23.552 19.115 42.667 42.667 42.667s42.667-19.115 42.667-42.667v-682.667c0-23.552-19.115-42.667-42.667-42.667s-42.667 19.115-42.667 42.667v682.667zM453.333 822.656l426.667-341.333c10.112-8.107 16-20.352 16-33.323s-5.888-25.216-16-33.323l-426.667-341.333c-12.8-10.24-30.379-12.245-45.141-5.12-14.805 7.083-24.192 22.059-24.192 38.443v682.667c0 16.384 9.387 31.36 24.192 38.443 14.763 7.125 32.341 5.12 45.141-5.12zM469.333 700.544v-505.088l315.691 252.544-315.691 252.544z" />
 <glyph unicode="&#xe9c2;" glyph-name="step-end" data-tags="step-end" d="M261.333 822.656l426.667-341.333c10.112-8.107 16-20.352 16-33.323s-5.888-25.216-16-33.323l-426.667-341.333c-12.8-10.24-30.379-12.245-45.141-5.12-14.805 7.083-24.192 22.059-24.192 38.443v682.667c0 16.384 9.387 31.36 24.192 38.443 14.763 7.125 32.341 5.12 45.141-5.12zM277.333 700.544v-505.088l315.691 252.544-315.691 252.544zM746.667 789.333c0 23.552 19.115 42.667 42.667 42.667s42.667-19.115 42.667-42.667v-682.667c0-23.552-19.115-42.667-42.667-42.667s-42.667 19.115-42.667 42.667v682.667z" />
 <glyph unicode="&#xe9c2;" glyph-name="step-end" data-tags="step-end" d="M261.333 822.656l426.667-341.333c10.112-8.107 16-20.352 16-33.323s-5.888-25.216-16-33.323l-426.667-341.333c-12.8-10.24-30.379-12.245-45.141-5.12-14.805 7.083-24.192 22.059-24.192 38.443v682.667c0 16.384 9.387 31.36 24.192 38.443 14.763 7.125 32.341 5.12 45.141-5.12zM277.333 700.544v-505.088l315.691 252.544-315.691 252.544zM746.667 789.333c0 23.552 19.115 42.667 42.667 42.667s42.667-19.115 42.667-42.667v-682.667c0-23.552-19.115-42.667-42.667-42.667s-42.667 19.115-42.667 42.667v682.667z" />
 <glyph unicode="&#xe9c3;" glyph-name="train" data-tags="train-front" d="M298.667 827.733c0 23.552 19.115 42.667 42.667 42.667s42.667-19.115 42.667-42.667v-166.4c0-70.229 57.771-128 128-128s128 57.771 128 128v166.4c0 23.552 19.115 42.667 42.667 42.667s42.667-19.115 42.667-42.667v-166.4c0-117.035-96.299-213.333-213.333-213.333s-213.333 96.299-213.333 213.333v166.4zM414.165 350.165c16.64-16.64 16.64-43.691 0-60.331s-43.691-16.64-60.331 0l-42.667 42.667c-16.64 16.64-16.64 43.691 0 60.331s43.691 16.64 60.331 0l42.667-42.667zM670.165 289.835c-16.64-16.64-43.691-16.64-60.331 0s-16.64 43.691 0 60.331l42.667 42.667c16.64 16.64 43.691 16.64 60.331 0s16.64-43.691 0-60.331l-42.667-42.667zM384 106.667c-143.36 0-256 112.64-256 256v170.667c0 210.645 173.355 384 384 384s384-173.355 384-384v-170.667c0-143.36-112.64-256-256-256h-256zM384 192h256c95.573 0 170.667 75.093 170.667 170.667v170.667c0 163.84-134.827 298.667-298.667 298.667s-298.667-134.827-298.667-298.667v-170.667c0-95.573 75.093-170.667 170.667-170.667zM305.835 173.013c13.056 19.584 39.552 24.875 59.179 11.819 19.584-13.056 24.875-39.552 11.819-59.179l-85.333-128c-13.056-19.584-39.552-24.875-59.179-11.819-19.584 13.056-24.875 39.552-11.819 59.179l85.333 128zM647.168 125.653c-13.056 19.627-7.765 46.123 11.819 59.179 19.627 13.056 46.123 7.765 59.179-11.819l85.333-128c13.056-19.627 7.765-46.123-11.819-59.179-19.627-13.056-46.123-7.765-59.179 11.819l-85.333 128z" />
 <glyph unicode="&#xe9c3;" glyph-name="train" data-tags="train-front" d="M298.667 827.733c0 23.552 19.115 42.667 42.667 42.667s42.667-19.115 42.667-42.667v-166.4c0-70.229 57.771-128 128-128s128 57.771 128 128v166.4c0 23.552 19.115 42.667 42.667 42.667s42.667-19.115 42.667-42.667v-166.4c0-117.035-96.299-213.333-213.333-213.333s-213.333 96.299-213.333 213.333v166.4zM414.165 350.165c16.64-16.64 16.64-43.691 0-60.331s-43.691-16.64-60.331 0l-42.667 42.667c-16.64 16.64-16.64 43.691 0 60.331s43.691 16.64 60.331 0l42.667-42.667zM670.165 289.835c-16.64-16.64-43.691-16.64-60.331 0s-16.64 43.691 0 60.331l42.667 42.667c16.64 16.64 43.691 16.64 60.331 0s16.64-43.691 0-60.331l-42.667-42.667zM384 106.667c-143.36 0-256 112.64-256 256v170.667c0 210.645 173.355 384 384 384s384-173.355 384-384v-170.667c0-143.36-112.64-256-256-256h-256zM384 192h256c95.573 0 170.667 75.093 170.667 170.667v170.667c0 163.84-134.827 298.667-298.667 298.667s-298.667-134.827-298.667-298.667v-170.667c0-95.573 75.093-170.667 170.667-170.667zM305.835 173.013c13.056 19.584 39.552 24.875 59.179 11.819 19.584-13.056 24.875-39.552 11.819-59.179l-85.333-128c-13.056-19.584-39.552-24.875-59.179-11.819-19.584 13.056-24.875 39.552-11.819 59.179l85.333 128zM647.168 125.653c-13.056 19.627-7.765 46.123 11.819 59.179 19.627 13.056 46.123 7.765 59.179-11.819l85.333-128c13.056-19.627 7.765-46.123-11.819-59.179-19.627-13.056-46.123-7.765-59.179 11.819l-85.333 128z" />
+<glyph unicode="&#xe9c4;" glyph-name="map" data-tags="map" d="M620.928 761.259c11.989-6.016 26.155-6.016 38.144 0l156.117 78.080 18.56 6.699 19.584 2.261c46.805 0 85.333-38.528 85.333-85.333v-544.683l-3.328-23.509c-2.176-7.552-5.333-14.72-9.429-21.291-4.096-6.613-9.088-12.672-14.848-17.963l-19.584-13.483-194.261-97.195c-36.011-17.963-78.421-17.963-114.432 0l-179.712 89.856c-11.989 6.016-26.155 6.016-38.144 0l-156.117-78.080c-11.861-5.888-24.917-8.96-38.144-8.96-46.805 0-85.333 38.485-85.333 85.333v544.683c0 32.256 18.347 61.867 47.189 76.245l194.261 97.195c36.011 17.963 78.421 17.963 114.432 0l179.712-89.856zM170.667 132.949l156.117 78.080c35.968 18.005 78.464 18.005 114.432 0l179.712-89.813c11.989-6.016 26.155-6.016 38.144 0l194.261 97.152c-14.421-7.211 0 16.128 0 0v543.445c-1.493-0.299-2.816-0.256 0 1.152l-156.117-78.037c-35.968-18.005-78.464-18.005-114.432 0l-179.712 89.813c-11.989 6.016-26.155 6.016-38.144 0l-194.261-97.109v-544.683zM597.333 714.069c0 23.552 19.115 42.667 42.667 42.667s42.667-19.115 42.667-42.667v-640c0-23.552-19.115-42.667-42.667-42.667s-42.667 19.115-42.667 42.667v640zM341.333 821.931c0 23.552 19.115 42.667 42.667 42.667s42.667-19.115 42.667-42.667v-640c0-23.552-19.115-42.667-42.667-42.667s-42.667 19.115-42.667 42.667v640z" />
+<glyph unicode="&#xe9c5;" glyph-name="coins" data-tags="coins" d="M341.333 917.333c164.821 0 298.667-133.845 298.667-298.667s-133.845-298.667-298.667-298.667c-164.821 0-298.667 133.845-298.667 298.667s133.845 298.667 298.667 298.667zM341.333 832c-117.76 0-213.333-95.573-213.333-213.333s95.573-213.333 213.333-213.333c117.76 0 213.333 95.573 213.333 213.333s-95.573 213.333-213.333 213.333zM756.949 477.568c-22.059 8.235-33.323 32.811-25.088 54.869s32.811 33.323 54.869 25.088c116.608-43.477 194.347-155.435 194.347-279.851 0-163.84-134.827-298.667-298.667-298.667-126.123 0-239.232 79.872-281.429 198.699-7.893 22.187 3.712 46.635 25.899 54.485 22.187 7.893 46.635-3.712 54.485-25.899 30.165-84.907 110.976-141.952 201.045-141.952 117.035 0 213.333 96.299 213.333 213.333 0 88.875-55.552 168.832-138.795 199.893zM298.667 661.333c-23.552 0-42.667 19.115-42.667 42.667s19.115 42.667 42.667 42.667h42.667c23.552 0 42.667-19.115 42.667-42.667v-170.667c0-23.552-19.115-42.667-42.667-42.667s-42.667 19.115-42.667 42.667v128zM682.581 337.835c-16.555 16.768-16.341 43.819 0.427 60.331 16.768 16.555 43.819 16.341 60.331-0.427l29.867-30.293c16.469-16.683 16.384-43.563-0.213-60.117l-120.32-120.32c-16.64-16.64-43.691-16.64-60.331 0s-16.64 43.691 0 60.331l90.368 90.368-0.128 0.128z" />
+<glyph unicode="&#xe9c6;" glyph-name="crosshair" data-tags="crosshair" d="M512 917.333c259.029 0 469.333-210.304 469.333-469.333s-210.304-469.333-469.333-469.333c-259.029 0-469.333 210.304-469.333 469.333s210.304 469.333 469.333 469.333zM512 832c-211.925 0-384-172.075-384-384s172.075-384 384-384c211.925 0 384 172.075 384 384s-172.075 384-384 384zM938.667 490.667c23.552 0 42.667-19.115 42.667-42.667s-19.115-42.667-42.667-42.667h-170.667c-23.552 0-42.667 19.115-42.667 42.667s19.115 42.667 42.667 42.667h170.667zM256 490.667c23.552 0 42.667-19.115 42.667-42.667s-19.115-42.667-42.667-42.667h-170.667c-23.552 0-42.667 19.115-42.667 42.667s19.115 42.667 42.667 42.667h170.667zM554.667 704c0-23.552-19.115-42.667-42.667-42.667s-42.667 19.115-42.667 42.667v170.667c0 23.552 19.115 42.667 42.667 42.667s42.667-19.115 42.667-42.667v-170.667zM554.667 21.333c0-23.552-19.115-42.667-42.667-42.667s-42.667 19.115-42.667 42.667v170.667c0 23.552 19.115 42.667 42.667 42.667s42.667-19.115 42.667-42.667v-170.667z" />
 </font></defs></svg>
 </font></defs></svg>

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

@@ -1074,5 +1074,6 @@
   "OLD_MAX": "Old Max",
   "OLD_MAX": "Old Max",
   "NEW_MIN": "New Min",
   "NEW_MIN": "New Min",
   "NEW_MAX": "New Max",
   "NEW_MAX": "New Max",
-  "REMAP_NODE": "Remap"
+  "REMAP_NODE": "Remap",
+  "TEXT_TOOL_ACTION_DISPLAY": "Click on the canvas to add a new text (drag while clicking to set the size). Click on existing text to edit it."
 }
 }

+ 28 - 0
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/VectorTextToolExecutor.cs

@@ -34,6 +34,9 @@ internal class VectorTextToolExecutor : UpdateableChangeExecutor, ITextOverlayEv
     private bool isListeningForValidLayer;
     private bool isListeningForValidLayer;
     private VectorPath? onPath;
     private VectorPath? onPath;
 
 
+    private VecD clickPos;
+    private bool wasDrawingSize;
+
     private List<Font> fontsToDispose = new();
     private List<Font> fontsToDispose = new();
 
 
     public override bool BlocksOtherActions => false;
     public override bool BlocksOtherActions => false;
@@ -98,6 +101,7 @@ internal class VectorTextToolExecutor : UpdateableChangeExecutor, ITextOverlayEv
                 Matrix3X3.Identity, toolbar.Spacing);
                 Matrix3X3.Identity, toolbar.Spacing);
             lastText = "";
             lastText = "";
             position = controller.LastPrecisePosition;
             position = controller.LastPrecisePosition;
+            clickPos = controller.LastPrecisePosition;
             // TODO: Implement proper putting on path editing
             // TODO: Implement proper putting on path editing
             /*if (controller.LeftMousePressed)
             /*if (controller.LeftMousePressed)
             {
             {
@@ -116,6 +120,7 @@ internal class VectorTextToolExecutor : UpdateableChangeExecutor, ITextOverlayEv
     {
     {
         var topMostWithinClick = QueryLayers<IVectorLayerHandler>(args.PositionOnCanvas);
         var topMostWithinClick = QueryLayers<IVectorLayerHandler>(args.PositionOnCanvas);
 
 
+        clickPos = args.PositionOnCanvas;
         var firstLayer = topMostWithinClick.FirstOrDefault();
         var firstLayer = topMostWithinClick.FirstOrDefault();
         args.Handled = firstLayer != null;
         args.Handled = firstLayer != null;
         if (firstLayer is not IVectorLayerHandler layerHandler)
         if (firstLayer is not IVectorLayerHandler layerHandler)
@@ -143,6 +148,29 @@ internal class VectorTextToolExecutor : UpdateableChangeExecutor, ITextOverlayEv
             }, false);
             }, false);
     }
     }
 
 
+    public override void OnPrecisePositionChange(VecD pos)
+    {
+        if (document.TextOverlayHandler.IsActive && internals.ChangeController.LeftMousePressed && string.IsNullOrEmpty(lastText))
+        {
+            wasDrawingSize = true;
+            double distance = Math.Abs(clickPos.Y - pos.Y);
+            position = new VecD(position.X, pos.Y);
+            document.TextOverlayHandler.Position = position;
+            document.TextOverlayHandler.PreviewSize = true;
+            var textData = ConstructTextData(lastText);
+            toolbar.FontSize = distance * RichText.PtToPx;
+            internals.ActionAccumulator.AddActions(new SetShapeGeometry_Action(selectedMember.Id, textData, VectorShapeChangeType.GeometryData));
+        }
+    }
+
+    public override void OnLeftMouseButtonUp(VecD pos)
+    {
+        if (wasDrawingSize)
+        {
+            document.TextOverlayHandler.PreviewSize = false;
+        }
+    }
+
     public void OnQuickToolSwitch()
     public void OnQuickToolSwitch()
     {
     {
         document.TextOverlayHandler.SetCursorPosition(internals.ChangeController.LastPrecisePosition);
         document.TextOverlayHandler.SetCursorPosition(internals.ChangeController.LastPrecisePosition);

+ 1 - 0
src/PixiEditor/Models/Handlers/ITextOverlayHandler.cs

@@ -12,5 +12,6 @@ public interface ITextOverlayHandler : IHandler
     public VecD Position { get; set; }
     public VecD Position { get; set; }
     public double? Spacing { get; set; }
     public double? Spacing { get; set; }
     public bool IsActive { get; }
     public bool IsActive { get; }
+    public bool PreviewSize { get; set; }
     public void SetCursorPosition(VecD closestToPosition);
     public void SetCursorPosition(VecD closestToPosition);
 }
 }

+ 1 - 1
src/PixiEditor/ViewModels/Document/Nodes/Calculations/RemapNodeViewModel.cs

@@ -2,7 +2,7 @@
 
 
 namespace PixiEditor.ViewModels.Document.Nodes.Calculations;
 namespace PixiEditor.ViewModels.Document.Nodes.Calculations;
 
 
-[NodeViewModel("REMAP_NODE", "NUMBERS", "")]
+[NodeViewModel("REMAP_NODE", "NUMBERS", PixiPerfectIcons.Map)]
 internal class RemapNodeViewModel : NodeViewModel<PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Calculations.RemapNode>
 internal class RemapNodeViewModel : NodeViewModel<PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Calculations.RemapNode>
 {
 {
 
 

+ 8 - 0
src/PixiEditor/ViewModels/Document/TransformOverlays/TextOverlayViewModel.cs

@@ -13,6 +13,7 @@ internal class TextOverlayViewModel : ObservableObject, ITextOverlayHandler
     private string text;
     private string text;
     private VecD position;
     private VecD position;
     private Font font;
     private Font font;
+    private bool previewSize = false;
     private ExecutionTrigger<string> requestEditTextTrigger;
     private ExecutionTrigger<string> requestEditTextTrigger;
     private Matrix3X3 matrix = Matrix3X3.Identity;
     private Matrix3X3 matrix = Matrix3X3.Identity;
     private double? spacing;
     private double? spacing;
@@ -76,6 +77,12 @@ internal class TextOverlayViewModel : ObservableObject, ITextOverlayHandler
         set => SetProperty(ref cursorPosition, value);
         set => SetProperty(ref cursorPosition, value);
     }
     }
 
 
+    public bool PreviewSize
+    {
+        get => previewSize;
+        set => SetProperty(ref previewSize, value);
+    }
+
     public int SelectionEnd
     public int SelectionEnd
     {
     {
         get => selectionEnd;
         get => selectionEnd;
@@ -119,6 +126,7 @@ internal class TextOverlayViewModel : ObservableObject, ITextOverlayHandler
         Matrix = matrix;
         Matrix = matrix;
         Spacing = spacing;
         Spacing = spacing;
         IsActive = true;
         IsActive = true;
+        PreviewSize = false;
         RequestEditTextTrigger.Execute(this, text);
         RequestEditTextTrigger.Execute(this, text);
     }
     }
 
 

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

@@ -47,6 +47,7 @@ internal class TextToolViewModel : ToolViewModel, ITextToolHandler
         if (!restoring)
         if (!restoring)
         {
         {
             ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Tools.UseTextTool();
             ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Tools.UseTextTool();
+            ActionDisplay = new LocalizedString("TEXT_TOOL_ACTION_DISPLAY");
         }
         }
     }
     }
 
 

+ 6 - 0
src/PixiEditor/Views/Main/ViewportControls/ViewportOverlays.cs

@@ -521,6 +521,11 @@ internal class ViewportOverlays
             Source = Viewport, Path = "Document.TextOverlayViewModel.SelectionEnd", Mode = BindingMode.TwoWay
             Source = Viewport, Path = "Document.TextOverlayViewModel.SelectionEnd", Mode = BindingMode.TwoWay
         };
         };
 
 
+        Binding previewSizeBinding = new()
+        {
+            Source = Viewport, Path = "Document.TextOverlayViewModel.PreviewSize", Mode = BindingMode.OneWay
+        };
+
         textOverlay.Bind(Visual.IsVisibleProperty, isVisibleBinding);
         textOverlay.Bind(Visual.IsVisibleProperty, isVisibleBinding);
         textOverlay.Bind(TextOverlay.TextProperty, textBinding);
         textOverlay.Bind(TextOverlay.TextProperty, textBinding);
         textOverlay.Bind(TextOverlay.PositionProperty, positionBinding);
         textOverlay.Bind(TextOverlay.PositionProperty, positionBinding);
@@ -530,5 +535,6 @@ internal class ViewportOverlays
         textOverlay.Bind(TextOverlay.SpacingProperty, spacingBinding);
         textOverlay.Bind(TextOverlay.SpacingProperty, spacingBinding);
         textOverlay.Bind(TextOverlay.CursorPositionProperty, cursorPositionBinding);
         textOverlay.Bind(TextOverlay.CursorPositionProperty, cursorPositionBinding);
         textOverlay.Bind(TextOverlay.SelectionEndProperty, selectionEndBinding);
         textOverlay.Bind(TextOverlay.SelectionEndProperty, selectionEndBinding);
+        textOverlay.Bind(TextOverlay.PreviewSizeProperty, previewSizeBinding);
     }
     }
 }
 }

+ 28 - 1
src/PixiEditor/Views/Overlays/TextOverlay/TextOverlay.cs

@@ -103,6 +103,15 @@ internal class TextOverlay : Overlay
         set => SetValue(SpacingProperty, value);
         set => SetValue(SpacingProperty, value);
     }
     }
 
 
+    public static readonly StyledProperty<bool> PreviewSizeProperty = AvaloniaProperty.Register<TextOverlay, bool>(
+        nameof(PreviewSize));
+
+    public bool PreviewSize
+    {
+        get => GetValue(PreviewSizeProperty);
+        set => SetValue(PreviewSizeProperty, value);
+    }
+
     private Dictionary<KeyCombination, Action> shortcuts;
     private Dictionary<KeyCombination, Action> shortcuts;
 
 
     private Caret caret = new Caret();
     private Caret caret = new Caret();
@@ -116,6 +125,7 @@ internal class TextOverlay : Overlay
 
 
     private Paint selectionPaint;
     private Paint selectionPaint;
     private Paint opacityPaint;
     private Paint opacityPaint;
+    private Paint sampleTextPaint;
 
 
     private int lastXMovementCursorIndex;
     private int lastXMovementCursorIndex;
 
 
@@ -199,6 +209,10 @@ internal class TextOverlay : Overlay
         };
         };
 
 
         opacityPaint = new Paint() { Color = Colors.White.WithAlpha(ThemeResources.SelectionFillColor.A) };
         opacityPaint = new Paint() { Color = Colors.White.WithAlpha(ThemeResources.SelectionFillColor.A) };
+        sampleTextPaint = new Paint()
+        {
+            Color = Colors.Black, Style = PaintStyle.Fill, IsAntiAliased = true
+        };
     }
     }
 
 
 
 
@@ -210,7 +224,15 @@ internal class TextOverlay : Overlay
 
 
         context.SetMatrix(context.TotalMatrix.Concat(Matrix));
         context.SetMatrix(context.TotalMatrix.Concat(Matrix));
 
 
-        RenderCaret(context);
+        if (!PreviewSize)
+        {
+            RenderCaret(context);
+        }
+        else
+        {
+            RenderSampleText(context);
+        }
+
         RenderSelection(context);
         RenderSelection(context);
 
 
         context.RestoreToCount(saved);
         context.RestoreToCount(saved);
@@ -242,6 +264,11 @@ internal class TextOverlay : Overlay
         caret.Render(context);
         caret.Render(context);
     }
     }
 
 
+    private void RenderSampleText(Canvas context)
+    {
+        context.DrawText("A", new VecD(Position.X, Position.Y), Font, sampleTextPaint);
+    }
+
     private void RenderSelection(Canvas context)
     private void RenderSelection(Canvas context)
     {
     {
         if (CursorPosition == SelectionEnd) return;
         if (CursorPosition == SelectionEnd) return;