Browse Source

Make TextBox work (a bit).

pull/10/head
Steven Kirk 12 years ago
parent
commit
127c27fd6b
  1. 11
      Cairo/Perspex.Cairo/Media/TextService.cs
  2. 3
      Gtk/Perspex.Gtk/GtkPlatform.cs
  3. 22
      Gtk/Perspex.Gtk/Input/GtkKeyboardDevice.cs
  4. 2
      Gtk/Perspex.Gtk/WindowImpl.cs
  5. 252
      Perspex.Controls/TextBoxView.cs
  6. 42
      Perspex.SceneGraph/Platform/ITextService.cs

11
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)

3
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));
}

22
Gtk/Perspex.Gtk/Input/GtkKeyboardDevice.cs

@ -3,8 +3,10 @@
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
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;
}
}
}
}
}

2
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;
}

252
Perspex.Controls/TextBoxView.cs

@ -1,126 +1,126 @@
// -----------------------------------------------------------------------
// <copyright file="TextBoxView.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
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<ITextService>();
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<ITextService>();
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 file="TextBoxView.cs" company="Steven Kirk">
// Copyright 2013 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
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<ITextService>();
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<ITextService>();
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();
}
}
}

42
Perspex.SceneGraph/Platform/ITextService.cs

@ -1,21 +1,21 @@
// -----------------------------------------------------------------------
// <copyright file="ITextService.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
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 file="ITextService.cs" company="Steven Kirk">
// Copyright 2014 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
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);
}
}

Loading…
Cancel
Save