From 31a3b9ea78f5d12bc2ff281f94d44656ff150be9 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 10 Dec 2014 00:22:39 +0100 Subject: [PATCH] Make Up/Down arrows work in text boxes. --- Perspex.Controls/TextBox.cs | 109 ++++++++++++++++++++++++------------ 1 file changed, 73 insertions(+), 36 deletions(-) diff --git a/Perspex.Controls/TextBox.cs b/Perspex.Controls/TextBox.cs index d2d135a529..aa7ce14e29 100644 --- a/Perspex.Controls/TextBox.cs +++ b/Perspex.Controls/TextBox.cs @@ -7,9 +7,11 @@ namespace Perspex.Controls { using System; + using System.Collections.Generic; using System.Linq; using Perspex.Controls.Primitives; using Perspex.Input; + using Perspex.Media; using Perspex.Styling; public class TextBox : TemplatedControl @@ -126,14 +128,23 @@ namespace Perspex.Controls } this.CaretIndex = caretIndex += count; - - if ((modifiers & ModifierKeys.Shift) == 0) - { - this.SelectionStart = this.SelectionEnd = this.CaretIndex; - } - else + } + + private void MoveVertical(int count, ModifierKeys modifiers) + { + var formattedText = this.textBoxView.FormattedText; + var lines = formattedText.GetLines().ToList(); + var caretIndex = this.CaretIndex; + var lineIndex = this.GetLine(caretIndex, lines) + count; + + if (lineIndex >= 0 && lineIndex < lines.Count) { - this.SelectionEnd = this.CaretIndex; + var line = lines[lineIndex]; + var rect = formattedText.HitTestTextPosition(caretIndex); + var y = count < 0 ? rect.Y : rect.Bottom; + var point = new Point(rect.X, y + (count * (line.Height / 2))); + var hit = formattedText.HitTestPoint(point); + this.CaretIndex = caretIndex = hit.TextPosition + (hit.IsTrailing ? 1 : 0); } } @@ -165,15 +176,6 @@ namespace Perspex.Controls } this.CaretIndex = caretIndex; - - if ((modifiers & ModifierKeys.Shift) != 0) - { - this.SelectionEnd = caretIndex; - } - else - { - this.SelectionStart = this.SelectionEnd = caretIndex; - } } private void MoveEnd(ModifierKeys modifiers) @@ -209,47 +211,54 @@ namespace Perspex.Controls } this.CaretIndex = caretIndex; - - if ((modifiers & ModifierKeys.Shift) != 0) - { - this.SelectionEnd = caretIndex; - } - else - { - this.SelectionStart = this.SelectionEnd = caretIndex; - } } private void OnKeyDown(object sender, KeyEventArgs e) { string text = this.Text ?? string.Empty; - var caretIndex = this.CaretIndex; + int caretIndex = this.CaretIndex; + bool movement = false; + var modifiers = e.Device.Modifiers; switch (e.Key) { case Key.Left: - this.MoveHorizontal(-1, e.Device.Modifiers); + this.MoveHorizontal(-1, modifiers); + movement = true; break; case Key.Right: - this.MoveHorizontal(1, e.Device.Modifiers); + this.MoveHorizontal(1, modifiers); + movement = true; break; - case Key.Back: - if (this.CaretIndex > 0) - { - this.Text = text.Substring(0, caretIndex - 1) + text.Substring(caretIndex); - --this.CaretIndex; - } + case Key.Up: + this.MoveVertical(-1, modifiers); + movement = true; + break; + case Key.Down: + this.MoveVertical(1, modifiers); + movement = true; break; case Key.Home: - this.MoveHome(e.Device.Modifiers); + this.MoveHome(modifiers); + movement = true; break; case Key.End: - this.MoveEnd(e.Device.Modifiers); + this.MoveEnd(modifiers); + movement = true; + break; + + case Key.Back: + if (this.CaretIndex > 0) + { + this.Text = text.Substring(0, caretIndex - 1) + text.Substring(caretIndex); + --this.CaretIndex; + } + break; case Key.Delete: @@ -286,9 +295,37 @@ namespace Perspex.Controls break; } + if (movement && ((modifiers & ModifierKeys.Shift) != 0)) + { + this.SelectionEnd = this.CaretIndex; + } + else + { + this.SelectionStart = this.SelectionEnd = this.CaretIndex; + } + e.Handled = true; } + private int GetLine(int caretIndex, IList lines) + { + int pos = 0; + int i; + + for (i = 0; i < lines.Count; ++i) + { + var line = lines[i]; + pos += line.Length; + + if (pos > caretIndex) + { + break; + } + } + + return i; + } + private int NextWord(string text, int direction, int caretIndex) { int pos = caretIndex;