diff --git a/Cairo/Perspex.Cairo/Media/TextService.cs b/Cairo/Perspex.Cairo/Media/TextService.cs index 3032786190..f37ae9ecf2 100644 --- a/Cairo/Perspex.Cairo/Media/TextService.cs +++ b/Cairo/Perspex.Cairo/Media/TextService.cs @@ -49,15 +49,20 @@ namespace Perspex.Cairo.Media var layout = this.CreateLayout(text); int result; int trailing; - layout.XyToIndex((int)point.X, (int)point.Y, out result, out trailing); - return result; + return layout.XyToIndex( + Pango.Units.FromDouble(point.X), + Pango.Units.FromDouble(point.Y), + out result, + out trailing) ? result : text.Text.Length; } public Point GetCaretPosition(FormattedText text, int caretIndex, Size constraint) { + // TODO: Rather than have this and GetLineHeights, might be best to just return + // the rect if that's also possible in Direct2D backend. var layout = this.CreateLayout(text); var rect = layout.IndexToPos(caretIndex); - return new Point(rect.X, rect.Y); + return new Point(Pango.Units.ToDouble(rect.X), Pango.Units.ToDouble(rect.Y)); } public double[] GetLineHeights(FormattedText text, Size constraint) diff --git a/Gtk/Perspex.Gtk/GtkPlatform.cs b/Gtk/Perspex.Gtk/GtkPlatform.cs index 34023ff732..70c0342ea0 100644 --- a/Gtk/Perspex.Gtk/GtkPlatform.cs +++ b/Gtk/Perspex.Gtk/GtkPlatform.cs @@ -8,6 +8,7 @@ namespace Perspex.Gtk { using System; using System.Reactive.Disposables; + using Perspex.Input; using Perspex.Platform; using Splat; using Gtk = global::Gtk; @@ -25,7 +26,7 @@ namespace Perspex.Gtk { var locator = Locator.CurrentMutable; locator.Register(() => new WindowImpl(), typeof(IWindowImpl)); - //locator.Register(() => WindowsKeyboardDevice.Instance, typeof(IKeyboardDevice)); + locator.Register(() => GtkKeyboardDevice.Instance, typeof(IKeyboardDevice)); locator.Register(() => instance, typeof(IPlatformThreadingInterface)); } diff --git a/Gtk/Perspex.Gtk/Input/GtkKeyboardDevice.cs b/Gtk/Perspex.Gtk/Input/GtkKeyboardDevice.cs index 2329d3acc2..fb42e5e817 100644 --- a/Gtk/Perspex.Gtk/Input/GtkKeyboardDevice.cs +++ b/Gtk/Perspex.Gtk/Input/GtkKeyboardDevice.cs @@ -3,8 +3,10 @@ // Copyright 2014 MIT Licence. See licence.md for more information. // // ----------------------------------------------------------------------- + namespace Perspex.Gtk { + using System; using Perspex.Input; public class GtkKeyboardDevice : KeyboardDevice @@ -32,7 +34,25 @@ namespace Perspex.Gtk public static Perspex.Input.Key ConvertKey(Gdk.Key key) { - return Key.X; + // TODO: Don't use reflection for this! My eyes!!! + if (key == Gdk.Key.BackSpace) + { + return Perspex.Input.Key.Back; + } + else + { + var s = Enum.GetName(typeof(Gdk.Key), key); + Perspex.Input.Key result; + + if (Enum.TryParse(s, true, out result)) + { + return result; + } + else + { + return Perspex.Input.Key.None; + } + } } } } diff --git a/Gtk/Perspex.Gtk/WindowImpl.cs b/Gtk/Perspex.Gtk/WindowImpl.cs index 01598bd482..9a78fc78fb 100644 --- a/Gtk/Perspex.Gtk/WindowImpl.cs +++ b/Gtk/Perspex.Gtk/WindowImpl.cs @@ -111,7 +111,7 @@ namespace Perspex.Gtk GtkKeyboardDevice.Instance, RawKeyEventType.KeyDown, GtkKeyboardDevice.ConvertKey(evnt.Key), - "X"); + new string((char)Gdk.Keyval.ToUnicode((uint)evnt.Key), 1)); this.Input(e); return true; } diff --git a/Perspex.Controls/TextBoxView.cs b/Perspex.Controls/TextBoxView.cs index 2a3a443939..a723395476 100644 --- a/Perspex.Controls/TextBoxView.cs +++ b/Perspex.Controls/TextBoxView.cs @@ -1,126 +1,126 @@ -// ----------------------------------------------------------------------- -// -// Copyright 2013 MIT Licence. See licence.md for more information. -// -// ----------------------------------------------------------------------- - -namespace Perspex.Controls -{ - using System; - using Perspex.Media; - using Perspex.Platform; - using Perspex.Threading; - using Splat; - - internal class TextBoxView : Control - { - private TextBox parent; - - private FormattedText formattedText; - - private DispatcherTimer caretTimer; - - private bool caretBlink; - - public TextBoxView(TextBox parent) - { - this.caretTimer = new DispatcherTimer(); - this.caretTimer.Interval = TimeSpan.FromMilliseconds(500); - this.caretTimer.Tick += this.CaretTimerTick; - this.parent = parent; - } - - public FormattedText FormattedText - { - get - { - if (this.formattedText == null) - { - this.formattedText = this.CreateFormattedText(); - } - - return this.formattedText; - } - } - - public new void GotFocus() - { - this.caretBlink = true; - this.caretTimer.Start(); - } - - public new void LostFocus() - { - this.caretTimer.Stop(); - this.InvalidateVisual(); - } - - public void InvalidateText() - { - this.formattedText = null; - this.InvalidateMeasure(); - } - - internal void CaretMoved() - { - this.caretBlink = true; - this.caretTimer.Stop(); - this.caretTimer.Start(); - this.InvalidateVisual(); - } - - public override void Render(IDrawingContext context) - { - Rect rect = new Rect(this.ActualSize); - - context.DrawText(Brushes.Black, rect, this.FormattedText); - - if (this.parent.IsFocused) - { - ITextService textService = Locator.Current.GetService(); - Point caretPos = textService.GetCaretPosition( - this.formattedText, - this.parent.CaretIndex, - this.ActualSize); - double[] lineHeights = textService.GetLineHeights(this.formattedText, this.ActualSize); - Brush caretBrush = Brushes.Black; - - if (this.caretBlink) - { - context.DrawLine( - new Pen(caretBrush, 1), - caretPos, - new Point(caretPos.X, caretPos.Y + lineHeights[0])); - } - } - } - - protected override Size MeasureOverride(Size constraint) - { - if (!string.IsNullOrEmpty(this.parent.Text)) - { - ITextService textService = Locator.Current.GetService(); - return textService.Measure(this.FormattedText, constraint); - } - - return new Size(); - } - - private FormattedText CreateFormattedText() - { - return new FormattedText - { - FontFamilyName = "Segoe UI", - FontSize = this.GetValue(TextBlock.FontSizeProperty), - FontStyle = this.GetValue(TextBlock.FontStyleProperty), - Text = this.parent.Text, - }; - } - - private void CaretTimerTick(object sender, EventArgs e) - { - this.caretBlink = !this.caretBlink; - this.InvalidateVisual(); - } - } -} +// ----------------------------------------------------------------------- +// +// Copyright 2013 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex.Controls +{ + using System; + using Perspex.Media; + using Perspex.Platform; + using Perspex.Threading; + using Splat; + + internal class TextBoxView : Control + { + private TextBox parent; + + private FormattedText formattedText; + + private DispatcherTimer caretTimer; + + private bool caretBlink; + + public TextBoxView(TextBox parent) + { + this.caretTimer = new DispatcherTimer(); + this.caretTimer.Interval = TimeSpan.FromMilliseconds(500); + this.caretTimer.Tick += this.CaretTimerTick; + this.parent = parent; + } + + public FormattedText FormattedText + { + get + { + if (this.formattedText == null) + { + this.formattedText = this.CreateFormattedText(); + } + + return this.formattedText; + } + } + + public new void GotFocus() + { + this.caretBlink = true; + this.caretTimer.Start(); + } + + public new void LostFocus() + { + this.caretTimer.Stop(); + this.InvalidateVisual(); + } + + public void InvalidateText() + { + this.formattedText = null; + this.InvalidateMeasure(); + } + + internal void CaretMoved() + { + this.caretBlink = true; + this.caretTimer.Stop(); + this.caretTimer.Start(); + this.InvalidateVisual(); + } + + public override void Render(IDrawingContext context) + { + Rect rect = new Rect(this.ActualSize); + + context.DrawText(Brushes.Black, rect, this.FormattedText); + + if (this.parent.IsFocused) + { + ITextService textService = Locator.Current.GetService(); + Point caretPos = textService.GetCaretPosition( + this.formattedText, + this.parent.CaretIndex, + this.ActualSize); + double[] lineHeights = textService.GetLineHeights(this.formattedText, this.ActualSize); + Brush caretBrush = Brushes.Black; + + if (this.caretBlink) + { + context.DrawLine( + new Pen(caretBrush, 1), + caretPos, + new Point(caretPos.X, caretPos.Y + lineHeights[0])); + } + } + } + + protected override Size MeasureOverride(Size constraint) + { + if (!string.IsNullOrEmpty(this.parent.Text)) + { + ITextService textService = Locator.Current.GetService(); + return textService.Measure(this.FormattedText, constraint); + } + + return new Size(); + } + + private FormattedText CreateFormattedText() + { + return new FormattedText + { + FontFamilyName = "Segoe UI", + FontSize = this.GetValue(TextBlock.FontSizeProperty), + FontStyle = this.GetValue(TextBlock.FontStyleProperty), + Text = this.parent.Text, + }; + } + + private void CaretTimerTick(object sender, EventArgs e) + { + this.caretBlink = !this.caretBlink; + this.InvalidateVisual(); + } + } +} diff --git a/Perspex.SceneGraph/Platform/ITextService.cs b/Perspex.SceneGraph/Platform/ITextService.cs index d4eadd7b91..9422f1c392 100644 --- a/Perspex.SceneGraph/Platform/ITextService.cs +++ b/Perspex.SceneGraph/Platform/ITextService.cs @@ -1,21 +1,21 @@ -// ----------------------------------------------------------------------- -// -// Copyright 2014 MIT Licence. See licence.md for more information. -// -// ----------------------------------------------------------------------- - -namespace Perspex.Platform -{ - using Perspex.Media; - - public interface ITextService - { - int GetCaretIndex(FormattedText text, Point point, Size constraint); - - Point GetCaretPosition(FormattedText text, int caretIndex, Size constraint); - - double[] GetLineHeights(FormattedText text, Size constraint); - - Size Measure(FormattedText text, Size constraint); - } -} +// ----------------------------------------------------------------------- +// +// Copyright 2014 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex.Platform +{ + using Perspex.Media; + + public interface ITextService + { + int GetCaretIndex(FormattedText text, Point point, Size constraint); + + Point GetCaretPosition(FormattedText text, int caretIndex, Size constraint); + + double[] GetLineHeights(FormattedText text, Size constraint); + + Size Measure(FormattedText text, Size constraint); + } +}