Browse Source

Merge branch 'master' into fixes/702_textbox_tab_focus_select_all_text

pull/745/head
Steven Kirk 10 years ago
parent
commit
d5e220279f
  1. 5
      src/Avalonia.Controls/TextBox.cs
  2. 59
      src/Avalonia.Controls/Utils/UndoRedoHelper.cs
  3. 4
      src/Skia/Avalonia.Skia/FormattedTextImpl.cs
  4. 52
      tests/Avalonia.Controls.UnitTests/TextBoxTests.cs

5
src/Avalonia.Controls/TextBox.cs

@ -148,7 +148,8 @@ namespace Avalonia.Controls
{ {
value = CoerceCaretIndex(value); value = CoerceCaretIndex(value);
SetAndRaise(CaretIndexProperty, ref _caretIndex, value); SetAndRaise(CaretIndexProperty, ref _caretIndex, value);
if (_undoRedoHelper.IsLastState && _undoRedoHelper.LastState.Text == Text) UndoRedoState state;
if (_undoRedoHelper.TryGetLastState(out state) && state.Text == Text)
_undoRedoHelper.UpdateLastState(); _undoRedoHelper.UpdateLastState();
} }
} }
@ -732,7 +733,7 @@ namespace Avalonia.Controls
private void SelectAll() private void SelectAll()
{ {
SelectionStart = 0; SelectionStart = 0;
SelectionEnd = Text.Length; SelectionEnd = Text?.Length ?? 0;
} }
private bool DeleteSelection() private bool DeleteSelection()

59
src/Avalonia.Controls/Utils/UndoRedoHelper.cs

@ -8,20 +8,19 @@ using Avalonia.Utilities;
namespace Avalonia.Controls.Utils namespace Avalonia.Controls.Utils
{ {
class UndoRedoHelper<TState> : WeakTimer.IWeakTimerSubscriber where TState : IEquatable<TState> class UndoRedoHelper<TState> : WeakTimer.IWeakTimerSubscriber where TState : struct, IEquatable<TState>
{ {
private readonly IUndoRedoHost _host; private readonly IUndoRedoHost _host;
public interface IUndoRedoHost public interface IUndoRedoHost
{ {
TState UndoRedoState { get; set; } TState UndoRedoState { get; set; }
} }
private readonly LinkedList<TState> _states = new LinkedList<TState>(); private readonly LinkedList<TState> _states = new LinkedList<TState>();
[NotNull]
private LinkedListNode<TState> _currentNode; private LinkedListNode<TState> _currentNode;
public int Limit { get; set; } = 10; public int Limit { get; set; } = 10;
@ -29,24 +28,31 @@ namespace Avalonia.Controls.Utils
public UndoRedoHelper(IUndoRedoHost host) public UndoRedoHelper(IUndoRedoHost host)
{ {
_host = host; _host = host;
_states.AddFirst(_host.UndoRedoState); WeakTimer.StartWeakTimer(this, TimeSpan.FromSeconds(1));
_currentNode = _states.First;
WeakTimer.StartWeakTimer(this, new TimeSpan(0, 0, 1));
} }
public void Undo() public void Undo()
{ {
if (_currentNode?.Previous != null) if (_currentNode?.Previous != null)
{ {
_currentNode = _currentNode.Previous; _currentNode = _currentNode.Previous;
} _host.UndoRedoState = _currentNode.Value;
}
_host.UndoRedoState = _currentNode.Value;
} }
public bool IsLastState => _currentNode.Next == null; public bool IsLastState => _currentNode != null && _currentNode.Next == null;
public bool TryGetLastState(out TState _state)
{
_state = default(TState);
if (!IsLastState)
return false;
_state = _currentNode.Value;
return true;
}
public bool HasState => _currentNode != null;
public void UpdateLastState(TState state) public void UpdateLastState(TState state)
{ {
_states.Last.Value = state; _states.Last.Value = state;
@ -57,34 +63,31 @@ namespace Avalonia.Controls.Utils
_states.Last.Value = _host.UndoRedoState; _states.Last.Value = _host.UndoRedoState;
} }
public TState LastState => _currentNode.Value;
public void DiscardRedo() public void DiscardRedo()
{ {
//Linked list sucks, so we are doing this while (_currentNode?.Next != null)
while (_currentNode.Next != null)
_states.Remove(_currentNode.Next); _states.Remove(_currentNode.Next);
} }
public void Redo() public void Redo()
{ {
if (_currentNode?.Next != null) { if (_currentNode?.Next != null)
_currentNode = _currentNode.Next; {
} _currentNode = _currentNode.Next;
_host.UndoRedoState = _currentNode.Value;
_host.UndoRedoState = _currentNode.Value; }
} }
public void Snapshot() public void Snapshot()
{ {
var current = _host.UndoRedoState; var current = _host.UndoRedoState;
if (!_currentNode.Value.Equals(current)) if (_currentNode == null || !_currentNode.Value.Equals(current))
{ {
if(_currentNode.Next != null) if (_currentNode?.Next != null)
DiscardRedo(); DiscardRedo();
_states.AddLast(current); _states.AddLast(current);
_currentNode = _states.Last; _currentNode = _states.Last;
if(_states.Count > Limit) if (_states.Count > Limit)
_states.RemoveFirst(); _states.RemoveFirst();
} }
} }

4
src/Skia/Avalonia.Skia/FormattedTextImpl.cs

@ -28,7 +28,9 @@ namespace Avalonia.Skia
//Paint.TextEncoding = SKTextEncoding.Utf8; //Paint.TextEncoding = SKTextEncoding.Utf8;
_paint.TextEncoding = SKTextEncoding.Utf16; _paint.TextEncoding = SKTextEncoding.Utf16;
_paint.IsStroke = false; _paint.IsStroke = false;
_paint.IsAntialias = true; _paint.IsAntialias = true;
_paint.LcdRenderText = true;
_paint.SubpixelText = true;
_paint.Typeface = typeface; _paint.Typeface = typeface;
_paint.TextSize = (float)fontSize; _paint.TextSize = (float)fontSize;
_paint.TextAlign = textAlignment.ToSKTextAlign(); _paint.TextAlign = textAlignment.ToSKTextAlign();

52
tests/Avalonia.Controls.UnitTests/TextBoxTests.cs

@ -41,6 +41,58 @@ namespace Avalonia.Controls.UnitTests
} }
} }
[Fact]
public void Press_Ctrl_A_Select_All_Text()
{
using (UnitTestApplication.Start(Services))
{
var target = new TextBox
{
Template = CreateTemplate(),
Text = "1234"
};
RaiseKeyEvent(target, Key.A, InputModifiers.Control);
Assert.Equal(0, target.SelectionStart);
Assert.Equal(4, target.SelectionEnd);
}
}
[Fact]
public void Press_Ctrl_A_Select_All_Null_Text()
{
using (UnitTestApplication.Start(Services))
{
var target = new TextBox
{
Template = CreateTemplate()
};
RaiseKeyEvent(target, Key.A, InputModifiers.Control);
Assert.Equal(0, target.SelectionStart);
Assert.Equal(0, target.SelectionEnd);
}
}
[Fact]
public void Press_Ctrl_Z_Will_Not_Modify_Text()
{
using (UnitTestApplication.Start(Services))
{
var target = new TextBox
{
Template = CreateTemplate(),
Text = "1234"
};
RaiseKeyEvent(target, Key.Z, InputModifiers.Control);
Assert.Equal("1234", target.Text);
}
}
[Fact] [Fact]
public void Typing_Beginning_With_0_Should_Not_Modify_Text_When_Bound_To_Int() public void Typing_Beginning_With_0_Should_Not_Modify_Text_When_Bound_To_Int()
{ {

Loading…
Cancel
Save