Browse Source

Added selection to TextBox.

pull/10/head
Steven Kirk 12 years ago
parent
commit
2e0e225e26
  1. 73
      Perspex.Controls/TextBox.cs
  2. 25
      Perspex.Controls/TextBoxView.cs
  3. 4
      Perspex.SceneGraph/Media/FormattedText.cs
  4. 17
      Windows/Perspex.Win32/Input/WindowsKeyboardDevice.cs

73
Perspex.Controls/TextBox.cs

@ -20,11 +20,18 @@ namespace Perspex.Controls
public static readonly PerspexProperty<bool> AcceptsTabProperty =
PerspexProperty.Register<TextBox, bool>("AcceptsTab");
public static readonly PerspexProperty<int> CaretIndexProperty =
PerspexProperty.Register<TextBox, int>("CaretIndex", coerce: CoerceCaretIndex);
public static readonly PerspexProperty<int> SelectionStartProperty =
PerspexProperty.Register<TextBox, int>("SelectionStart", coerce: CoerceCaretIndex);
public static readonly PerspexProperty<int> SelectionEndProperty =
PerspexProperty.Register<TextBox, int>("SelectionEnd", coerce: CoerceCaretIndex);
public static readonly PerspexProperty<string> TextProperty =
TextBlock.TextProperty.AddOwner<TextBox>();
private int caretIndex;
private TextBoxView textBoxView;
static TextBox()
@ -54,23 +61,20 @@ namespace Perspex.Controls
public int CaretIndex
{
get
{
return this.caretIndex;
}
set
{
var text = this.Text ?? string.Empty;
get { return this.GetValue(CaretIndexProperty); }
set { this.SetValue(CaretIndexProperty, value); }
}
value = Math.Min(Math.Max(value, 0), text.Length);
public int SelectionStart
{
get { return this.GetValue(SelectionStartProperty); }
set { this.SetValue(SelectionStartProperty, value); }
}
if (this.caretIndex != value)
{
this.caretIndex = value;
this.textBoxView.CaretMoved();
}
}
public int SelectionEnd
{
get { return this.GetValue(SelectionEndProperty); }
set { this.SetValue(SelectionEndProperty, value); }
}
public string Text
@ -95,33 +99,54 @@ namespace Perspex.Controls
textContainer.Content = this.textBoxView = new TextBoxView(this);
}
private static int CoerceCaretIndex(PerspexObject o, int value)
{
var text = o.GetValue(TextProperty);
var length = (text != null) ? text.Length : 0;
return Math.Max(0, Math.Min(length, value));
}
private void MoveHorizontal(int count, ModifierKeys modifiers)
{
if (modifiers == ModifierKeys.None)
{
this.CaretIndex += count;
this.SelectionStart = this.SelectionEnd = this.CaretIndex;
}
else if ((modifiers & ModifierKeys.Shift) == ModifierKeys.Shift)
{
this.SelectionEnd = (this.CaretIndex += count);
}
}
private void OnKeyDown(object sender, KeyEventArgs e)
{
string text = this.Text ?? string.Empty;
var caretIndex = this.CaretIndex;
switch (e.Key)
{
case Key.Left:
--this.CaretIndex;
this.MoveHorizontal(-1, e.Device.Modifiers);
break;
case Key.Right:
++this.CaretIndex;
this.MoveHorizontal(1, e.Device.Modifiers);
break;
case Key.Back:
if (this.caretIndex > 0)
if (this.CaretIndex > 0)
{
this.Text = text.Substring(0, this.caretIndex - 1) + text.Substring(this.caretIndex);
this.Text = text.Substring(0, caretIndex - 1) + text.Substring(caretIndex);
--this.CaretIndex;
}
break;
case Key.Delete:
if (this.caretIndex < text.Length)
if (caretIndex < text.Length)
{
this.Text = text.Substring(0, this.caretIndex) + text.Substring(this.caretIndex + 1);
this.Text = text.Substring(0, caretIndex) + text.Substring(caretIndex + 1);
}
break;
@ -145,7 +170,7 @@ namespace Perspex.Controls
default:
if (!string.IsNullOrEmpty(e.Text))
{
this.Text = text.Substring(0, this.caretIndex) + e.Text + text.Substring(this.caretIndex);
this.Text = text.Substring(0, caretIndex) + e.Text + text.Substring(caretIndex);
++this.CaretIndex;
}

25
Perspex.Controls/TextBoxView.cs

@ -7,6 +7,7 @@
namespace Perspex.Controls
{
using System;
using System.Reactive.Linq;
using Perspex.Media;
using Perspex.Threading;
@ -25,6 +26,13 @@ namespace Perspex.Controls
this.caretTimer.Tick += this.CaretTimerTick;
this.parent = parent;
this[!TextProperty] = parent[!TextProperty];
Observable.Merge(
this.parent.GetObservable(TextBox.SelectionStartProperty),
this.parent.GetObservable(TextBox.SelectionEndProperty))
.Subscribe(_ => this.InvalidateVisual());
parent.GetObservable(TextBox.CaretIndexProperty).Subscribe(_ => this.CaretMoved());
}
public int GetCaretIndex(Point point)
@ -47,6 +55,23 @@ namespace Perspex.Controls
public override void Render(IDrawingContext context)
{
var selectionStart = this.parent.SelectionStart;
var selectionEnd = this.parent.SelectionEnd;
if (selectionStart != selectionEnd)
{
var start = Math.Min(selectionStart, selectionEnd);
var length = Math.Max(selectionStart, selectionEnd) - start;
var rects = this.FormattedText.HitTestTextRange(start, length);
var brush = new SolidColorBrush(0xff086f9e);
foreach (var rect in rects)
{
context.FillRectange(brush, rect);
}
}
base.Render(context);
if (this.parent.IsFocused)

4
Perspex.SceneGraph/Media/FormattedText.cs

@ -79,7 +79,7 @@ namespace Perspex.Media
return this.PlatformImpl.HitTestTextPosition(index);
}
public IEnumerable<Rect> HitTestTextRange(int index, int length, Point origin)
public IEnumerable<Rect> HitTestTextRange(int index, int length, Point origin = default(Point))
{
return this.PlatformImpl.HitTestTextRange(index, length, origin);
}
@ -89,4 +89,4 @@ namespace Perspex.Media
return this.PlatformImpl.Measure();
}
}
}
}

17
Windows/Perspex.Win32/Input/WindowsKeyboardDevice.cs

@ -28,26 +28,22 @@ namespace Perspex.Win32.Input
{
ModifierKeys result = 0;
if (this.GetKeyStates(Key.LeftAlt) == KeyStates.Down ||
this.GetKeyStates(Key.RightAlt) == KeyStates.Down)
if (this.IsDown(Key.LeftAlt) || this.IsDown(Key.RightAlt))
{
result |= ModifierKeys.Alt;
}
if (this.GetKeyStates(Key.LeftCtrl) == KeyStates.Down ||
this.GetKeyStates(Key.RightCtrl) == KeyStates.Down)
if (this.IsDown(Key.LeftCtrl) || this.IsDown(Key.RightCtrl))
{
result |= ModifierKeys.Control;
}
if (this.GetKeyStates(Key.LeftShift) == KeyStates.Down ||
this.GetKeyStates(Key.RightShift) == KeyStates.Down)
if (this.IsDown(Key.LeftShift) || this.IsDown(Key.RightShift))
{
result |= ModifierKeys.Shift;
}
if (this.GetKeyStates(Key.LWin) == KeyStates.Down ||
this.GetKeyStates(Key.RWin) == KeyStates.Down)
if (this.IsDown(Key.LWin) || this.IsDown(Key.RWin))
{
result |= ModifierKeys.Windows;
}
@ -79,6 +75,11 @@ namespace Perspex.Win32.Input
UnmanagedMethods.GetKeyboardState(this.keyStates);
}
private bool IsDown(Key key)
{
return (this.GetKeyStates(key) & KeyStates.Down) != 0;
}
private KeyStates GetKeyStates(Key key)
{
int vk = KeyInterop.VirtualKeyFromKey(key);

Loading…
Cancel
Save