diff --git a/Perspex.Direct2D1/Direct2D1Platform.cs b/Perspex.Direct2D1/Direct2D1Platform.cs
index fd5e9bd376..b280a31ba6 100644
--- a/Perspex.Direct2D1/Direct2D1Platform.cs
+++ b/Perspex.Direct2D1/Direct2D1Platform.cs
@@ -32,6 +32,11 @@ namespace Perspex.Direct2D1
locator.Register(() => imagingFactory, typeof(SharpDX.WIC.ImagingFactory));
}
+ public ITextService TextService
+ {
+ get { return textService; }
+ }
+
public IBitmapImpl CreateBitmap(int width, int height)
{
return new BitmapImpl(imagingFactory, width, height);
@@ -51,10 +56,5 @@ namespace Perspex.Direct2D1
{
return new StreamGeometryImpl();
}
-
- public ITextService GetTextService()
- {
- return textService;
- }
}
}
diff --git a/Perspex.Direct2D1/Media/DrawingContext.cs b/Perspex.Direct2D1/Media/DrawingContext.cs
index 17b20e1d70..00fb0bdaae 100644
--- a/Perspex.Direct2D1/Media/DrawingContext.cs
+++ b/Perspex.Direct2D1/Media/DrawingContext.cs
@@ -51,6 +51,23 @@ namespace Perspex.Direct2D1.Media
this.renderTarget.EndDraw();
}
+ ///
+ /// Draws a line.
+ ///
+ /// The stroke pen.
+ /// The first point of the line.
+ /// The second point of the line.
+ public void DrawLine(Pen pen, Perspex.Point p1, Perspex.Point p2)
+ {
+ if (pen != null)
+ {
+ using (SharpDX.Direct2D1.SolidColorBrush d2dBrush = this.Convert(pen.Brush))
+ {
+ this.renderTarget.DrawLine(p1.ToSharpDX(), p2.ToSharpDX(), d2dBrush);
+ }
+ }
+ }
+
///
/// Draws a geometry.
///
@@ -105,7 +122,7 @@ namespace Perspex.Direct2D1.Media
if (!string.IsNullOrEmpty(text.Text))
{
using (SharpDX.Direct2D1.SolidColorBrush brush = this.Convert(foreground))
- using (SharpDX.DirectWrite.TextFormat format = TextService.Convert(this.directWriteFactory, text))
+ using (SharpDX.DirectWrite.TextFormat format = TextService.GetTextFormat(this.directWriteFactory, text))
{
this.renderTarget.DrawText(
text.Text,
diff --git a/Perspex.Direct2D1/PrimitiveExtensions.cs b/Perspex.Direct2D1/PrimitiveExtensions.cs
index a7b01ee5db..d3469d78a0 100644
--- a/Perspex.Direct2D1/PrimitiveExtensions.cs
+++ b/Perspex.Direct2D1/PrimitiveExtensions.cs
@@ -6,11 +6,6 @@
namespace Perspex.Direct2D1
{
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
using SharpDX;
public static class PrimitiveExtensions
diff --git a/Perspex.Direct2D1/TextService.cs b/Perspex.Direct2D1/TextService.cs
index fc03940292..948d9efef2 100644
--- a/Perspex.Direct2D1/TextService.cs
+++ b/Perspex.Direct2D1/TextService.cs
@@ -6,6 +6,7 @@
namespace Perspex.Direct2D1
{
+ using System;
using Perspex.Media;
using Perspex.Platform;
using SharpDX.DirectWrite;
@@ -19,7 +20,7 @@ namespace Perspex.Direct2D1
this.factory = factory;
}
- public static TextFormat Convert(Factory factory, FormattedText text)
+ public static TextFormat GetTextFormat(Factory factory, FormattedText text)
{
return new TextFormat(
factory,
@@ -27,10 +28,43 @@ namespace Perspex.Direct2D1
(float)text.FontSize);
}
+ public TextLayout GetTextLayout(Factory factory, FormattedText text)
+ {
+ return new TextLayout(
+ factory,
+ text.Text,
+ GetTextFormat(factory, text),
+ float.MaxValue,
+ float.MaxValue);
+ }
+
+ public int GetCaretIndex(FormattedText text, Point point)
+ {
+ TextLayout layout = GetTextLayout(this.factory, text);
+ SharpDX.Bool isTrailingHit;
+ SharpDX.Bool isInside;
+
+ HitTestMetrics result = layout.HitTestPoint(
+ (float)point.X,
+ (float)point.Y,
+ out isTrailingHit,
+ out isInside);
+
+ return result.TextPosition + (isTrailingHit ? 1 : 0);
+ }
+
+ public Point GetCaretPosition(FormattedText text, int caretIndex)
+ {
+ TextLayout layout = GetTextLayout(this.factory, text);
+ float x;
+ float y;
+ layout.HitTestTextPosition(caretIndex, false, out x, out y);
+ return new Point(x, y);
+ }
+
public Size Measure(FormattedText text)
{
- TextFormat f = Convert(this.factory, text);
- TextLayout layout = new TextLayout(this.factory, text.Text, f, float.MaxValue, float.MaxValue);
+ TextLayout layout = GetTextLayout(this.factory, text);
return new Size(
layout.Metrics.WidthIncludingTrailingWhitespace,
layout.Metrics.Height);
diff --git a/Perspex.Windows/Input/WindowsMouseDevice.cs b/Perspex.Windows/Input/WindowsMouseDevice.cs
index cc675e5975..3ff7ef5de8 100644
--- a/Perspex.Windows/Input/WindowsMouseDevice.cs
+++ b/Perspex.Windows/Input/WindowsMouseDevice.cs
@@ -6,7 +6,9 @@
namespace Perspex.Windows.Input
{
+ using System;
using Perspex.Input;
+ using Perspex.Windows.Interop;
public class WindowsMouseDevice : MouseDevice
{
@@ -28,6 +30,14 @@ namespace Perspex.Windows.Input
get { return base.Position; }
internal set { base.Position = value; }
}
+
+ protected override Point GetClientPosition()
+ {
+ UnmanagedMethods.POINT p;
+ UnmanagedMethods.GetCursorPos(out p);
+ UnmanagedMethods.ScreenToClient(this.CurrentWindow.Handle, ref p);
+ return new Point(p.X, p.Y);
+ }
}
}
diff --git a/Perspex/Controls/TextBox.cs b/Perspex/Controls/TextBox.cs
index c190435292..8b3e5a2417 100644
--- a/Perspex/Controls/TextBox.cs
+++ b/Perspex/Controls/TextBox.cs
@@ -123,10 +123,10 @@ namespace Perspex.Controls
private void OnPointerPressed(object sender, PointerEventArgs e)
{
- //IPlatformInterface platform = Locator.Current.GetService();
- //this.CaretIndex = platform.GetTextService().GetCaretIndex(
- // this.textBoxView.FormattedText,
- // e.GetPosition(this.textBoxView));
+ IPlatformInterface platform = Locator.Current.GetService();
+ this.CaretIndex = platform.TextService.GetCaretIndex(
+ this.textBoxView.FormattedText,
+ e.GetPosition(this.textBoxView));
}
}
}
diff --git a/Perspex/Controls/TextBoxView.cs b/Perspex/Controls/TextBoxView.cs
index 4bdfcc7999..7668c8f4cf 100644
--- a/Perspex/Controls/TextBoxView.cs
+++ b/Perspex/Controls/TextBoxView.cs
@@ -9,6 +9,8 @@ namespace Perspex.Controls
using System;
using System.Globalization;
using Perspex.Media;
+ using Perspex.Platform;
+ using Splat;
internal class TextBoxView : Control
{
@@ -73,32 +75,20 @@ namespace Perspex.Controls
context.DrawText(Brushes.Black, rect, this.FormattedText);
- //if (this.parent.IsKeyboardFocused)
- //{
- // Point caretPos = this.FormattedText.GetCaretPosition(this.parent.CaretIndex);
- // Brush caretBrush = this.parent.CaretBrush;
-
- // if (caretBrush == null)
- // {
- // Color color = Colors.Black;
- // SolidColorBrush background = this.parent.Background as SolidColorBrush;
-
- // if (background != null)
- // {
- // color = Color.FromUInt32(0x00ffffffu ^ background.Color.ToUint32());
- // }
-
- // caretBrush = new SolidColorBrush(color);
- // }
-
- // if (this.caretBlink)
- // {
- // drawingContext.DrawLine(
- // new Pen(caretBrush, 1),
- // caretPos,
- // caretPos + new Vector(0, this.FormattedText.Height));
- // }
- //}
+ if (this.parent.IsFocused)
+ {
+ IPlatformInterface platform = Locator.Current.GetService();
+ Point caretPos = platform.TextService.GetCaretPosition(this.formattedText, this.parent.CaretIndex);
+ Brush caretBrush = Brushes.Black;
+
+ //if (!this.caretBlink)
+ {
+ context.DrawLine(
+ new Pen(caretBrush, 1),
+ caretPos,
+ new Point(caretPos.X, caretPos.Y + this.FormattedText.Size.Height));
+ }
+ }
}
protected override Size MeasureOverride(Size constraint)
diff --git a/Perspex/Input/IPointerDevice.cs b/Perspex/Input/IPointerDevice.cs
index ed93439f6d..338b325c56 100644
--- a/Perspex/Input/IPointerDevice.cs
+++ b/Perspex/Input/IPointerDevice.cs
@@ -13,5 +13,7 @@ namespace Perspex.Input
Interactive Captured { get; }
void Capture(Interactive visual);
+
+ Point GetPosition(IVisual relativeTo);
}
}
diff --git a/Perspex/Input/MouseDevice.cs b/Perspex/Input/MouseDevice.cs
index 9eaf573b82..54d986ca18 100644
--- a/Perspex/Input/MouseDevice.cs
+++ b/Perspex/Input/MouseDevice.cs
@@ -45,6 +45,22 @@ namespace Perspex.Input
this.Captured = visual;
}
+ public Point GetPosition(IVisual relativeTo)
+ {
+ Point p = this.GetClientPosition();
+ IVisual v = relativeTo;
+
+ while (v != null)
+ {
+ p -= v.Bounds.Position;
+ v = v.VisualParent;
+ }
+
+ return p;
+ }
+
+ protected abstract Point GetClientPosition();
+
private void ProcessRawEvent(RawMouseEventArgs e)
{
this.Position = e.Position;
diff --git a/Perspex/Input/PointerEventArgs.cs b/Perspex/Input/PointerEventArgs.cs
index 056328f5a1..4417c59949 100644
--- a/Perspex/Input/PointerEventArgs.cs
+++ b/Perspex/Input/PointerEventArgs.cs
@@ -11,5 +11,10 @@ namespace Perspex.Input
public class PointerEventArgs : RoutedEventArgs
{
public IPointerDevice Device { get; set; }
+
+ public Point GetPosition(IVisual relativeTo)
+ {
+ return this.Device.GetPosition(relativeTo);
+ }
}
}
diff --git a/Perspex/Media/FormattedText.cs b/Perspex/Media/FormattedText.cs
index 12a1cd1b1d..e1b890f87f 100644
--- a/Perspex/Media/FormattedText.cs
+++ b/Perspex/Media/FormattedText.cs
@@ -22,8 +22,7 @@ namespace Perspex.Media
get
{
IPlatformInterface factory = Locator.Current.GetService();
- ITextService service = factory.GetTextService();
- return service.Measure(this);
+ return factory.TextService.Measure(this);
}
}
}
diff --git a/Perspex/Media/IDrawingContext.cs b/Perspex/Media/IDrawingContext.cs
index 92a001169a..c22fbfe172 100644
--- a/Perspex/Media/IDrawingContext.cs
+++ b/Perspex/Media/IDrawingContext.cs
@@ -13,6 +13,14 @@ namespace Perspex.Media
///
public interface IDrawingContext : IDisposable
{
+ ///
+ /// Draws a line.
+ ///
+ /// The stroke pen.
+ /// The first point of the line.
+ /// The second point of the line.
+ void DrawLine(Pen pen, Point p1, Point p2);
+
///
/// Draws a geometry.
///
diff --git a/Perspex/Platform/IPlatformInterface.cs b/Perspex/Platform/IPlatformInterface.cs
index 5138df4846..0964ec3ad7 100644
--- a/Perspex/Platform/IPlatformInterface.cs
+++ b/Perspex/Platform/IPlatformInterface.cs
@@ -10,6 +10,8 @@ namespace Perspex.Platform
public interface IPlatformInterface
{
+ ITextService TextService { get; }
+
IBitmapImpl CreateBitmap(int width, int height);
IStreamGeometryImpl CreateStreamGeometry();
@@ -17,7 +19,5 @@ namespace Perspex.Platform
IRenderer CreateRenderer(IntPtr handle, double width, double height);
IRenderTargetBitmapImpl CreateRenderTargetBitmap(int width, int height);
-
- ITextService GetTextService();
}
}
diff --git a/Perspex/Platform/ITextService.cs b/Perspex/Platform/ITextService.cs
index 0e6e36e745..d9e05ce4c6 100644
--- a/Perspex/Platform/ITextService.cs
+++ b/Perspex/Platform/ITextService.cs
@@ -11,5 +11,9 @@ namespace Perspex.Platform
public interface ITextService
{
Size Measure(FormattedText text);
+
+ int GetCaretIndex(FormattedText text, Point point);
+
+ Point GetCaretPosition(FormattedText text, int caretIndex);
}
}
diff --git a/Perspex/Themes/Default/TextBoxStyle.cs b/Perspex/Themes/Default/TextBoxStyle.cs
index 7b36d60a18..574eae6261 100644
--- a/Perspex/Themes/Default/TextBoxStyle.cs
+++ b/Perspex/Themes/Default/TextBoxStyle.cs
@@ -43,6 +43,7 @@ namespace Perspex.Themes.Default
Border result = new Border
{
Id = "border",
+ Padding = new Thickness(2),
[~Border.BackgroundProperty] = control[~TextBox.BackgroundProperty],
[~Border.BorderBrushProperty] = control[~TextBox.BorderBrushProperty],
[~Border.BorderThicknessProperty] = control[~TextBox.BorderThicknessProperty],