Browse Source

Merge branch 'master' into wip-animations

pull/1461/head
Jumar Macato 8 years ago
committed by GitHub
parent
commit
df34e26ade
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      src/Avalonia.Controls/Presenters/TextPresenter.cs
  2. 2
      src/Avalonia.Controls/TextBlock.cs
  3. 8
      src/Avalonia.Controls/ToolTip.cs
  4. 4
      src/Markup/Avalonia.Markup/Data/Parsers/ArgumentListParser.cs
  5. 42
      src/Markup/Avalonia.Markup/Data/Parsers/ExpressionParser.cs
  6. 40
      tests/Avalonia.Controls.UnitTests/Presenters/TextPresenter_Tests.cs
  7. 10
      tests/Avalonia.Controls.UnitTests/TextBlockTests.cs
  8. 12
      tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Indexer.cs

4
src/Avalonia.Controls/Presenters/TextPresenter.cs

@ -223,11 +223,11 @@ namespace Avalonia.Controls.Presenters
if (PasswordChar != default(char))
{
result = base.CreateFormattedText(constraint, new string(PasswordChar, Text.Length));
result = base.CreateFormattedText(constraint, new string(PasswordChar, text?.Length ?? 0));
}
else
{
result = base.CreateFormattedText(constraint, Text);
result = base.CreateFormattedText(constraint, text);
}
var selectionStart = SelectionStart;

2
src/Avalonia.Controls/TextBlock.cs

@ -111,6 +111,8 @@ namespace Avalonia.Controls
/// </summary>
public TextBlock()
{
_text = string.Empty;
Observable.Merge(
this.GetObservable(TextProperty).Select(_ => Unit.Default),
this.GetObservable(TextAlignmentProperty).Select(_ => Unit.Default),

8
src/Avalonia.Controls/ToolTip.cs

@ -34,25 +34,25 @@ namespace Avalonia.Controls
/// Defines the ToolTip.Placement property.
/// </summary>
public static readonly AttachedProperty<PlacementMode> PlacementProperty =
AvaloniaProperty.RegisterAttached<Popup, Control, PlacementMode>("Placement", defaultValue: PlacementMode.Pointer);
AvaloniaProperty.RegisterAttached<ToolTip, Control, PlacementMode>("Placement", defaultValue: PlacementMode.Pointer);
/// <summary>
/// Defines the ToolTip.HorizontalOffset property.
/// </summary>
public static readonly AttachedProperty<double> HorizontalOffsetProperty =
AvaloniaProperty.RegisterAttached<Popup, Control, double>("HorizontalOffset");
AvaloniaProperty.RegisterAttached<ToolTip, Control, double>("HorizontalOffset");
/// <summary>
/// Defines the ToolTip.VerticalOffset property.
/// </summary>
public static readonly AttachedProperty<double> VerticalOffsetProperty =
AvaloniaProperty.RegisterAttached<Popup, Control, double>("VerticalOffset", 20);
AvaloniaProperty.RegisterAttached<ToolTip, Control, double>("VerticalOffset", 20);
/// <summary>
/// Defines the ToolTip.ShowDelay property.
/// </summary>
public static readonly AttachedProperty<int> ShowDelayProperty =
AvaloniaProperty.RegisterAttached<Popup, Control, int>("ShowDelay", 400);
AvaloniaProperty.RegisterAttached<ToolTip, Control, int>("ShowDelay", 400);
/// <summary>
/// Stores the curernt <see cref="ToolTip"/> instance in the control.

4
src/Markup/Avalonia.Markup/Data/Parsers/ArgumentListParser.cs

@ -51,10 +51,10 @@ namespace Avalonia.Markup.Data.Parsers
}
}
throw new ExpressionParseException(r.Position, "Expected ']'.");
throw new ExpressionParseException(r.Position, $"Expected '{close}'.");
}
return null;
throw new ExpressionParseException(r.Position, $"Expected '{open}'.");
}
}
}

42
src/Markup/Avalonia.Markup/Data/Parsers/ExpressionParser.cs

@ -40,6 +40,10 @@ namespace Avalonia.Markup.Data.Parsers
case State.AttachedProperty:
state = ParseAttachedProperty(r, nodes);
break;
case State.Indexer:
state = ParseIndexer(r, nodes);
break;
}
}
@ -67,6 +71,10 @@ namespace Avalonia.Markup.Data.Parsers
{
return State.AttachedProperty;
}
else if (PeekOpenBracket(r))
{
return State.Indexer;
}
else
{
var identifier = IdentifierParser.Parse(r);
@ -92,20 +100,9 @@ namespace Avalonia.Markup.Data.Parsers
nodes.Add(new StreamNode());
return State.AfterMember;
}
else
else if (PeekOpenBracket(r))
{
var args = ArgumentListParser.Parse(r, '[', ']');
if (args != null)
{
if (args.Count == 0)
{
throw new ExpressionParseException(r.Position, "Indexer may not be empty.");
}
nodes.Add(new IndexerNode(args));
return State.AfterMember;
}
return State.Indexer;
}
return State.End;
@ -151,6 +148,19 @@ namespace Avalonia.Markup.Data.Parsers
return State.AfterMember;
}
private State ParseIndexer(Reader r, List<ExpressionNode> nodes)
{
var args = ArgumentListParser.Parse(r, '[', ']');
if (args.Count == 0)
{
throw new ExpressionParseException(r.Position, "Indexer may not be empty.");
}
nodes.Add(new IndexerNode(args));
return State.AfterMember;
}
private static bool ParseNot(Reader r)
{
return !r.End && r.TakeIf('!');
@ -166,6 +176,11 @@ namespace Avalonia.Markup.Data.Parsers
return !r.End && r.TakeIf('(');
}
private static bool PeekOpenBracket(Reader r)
{
return !r.End && r.Peek == '[';
}
private static bool ParseStreamOperator(Reader r)
{
return !r.End && r.TakeIf('^');
@ -177,6 +192,7 @@ namespace Avalonia.Markup.Data.Parsers
AfterMember,
BeforeMember,
AttachedProperty,
Indexer,
End,
}
}

40
tests/Avalonia.Controls.UnitTests/Presenters/TextPresenter_Tests.cs

@ -0,0 +1,40 @@
using Avalonia.Controls.Presenters;
using Xunit;
namespace Avalonia.Controls.UnitTests.Presenters
{
public class TextPresenter_Tests
{
[Fact]
public void TextPresenter_Can_Contain_Null_With_Password_Char_Set()
{
var target = new TextPresenter
{
PasswordChar = '*'
};
Assert.NotNull(target.FormattedText);
}
[Fact]
public void TextPresenter_Can_Contain_Null_WithOut_Password_Char_Set()
{
var target = new TextPresenter();
Assert.NotNull(target.FormattedText);
}
[Fact]
public void Text_Presenter_Replaces_Formatted_Text_With_Password_Char()
{
var target = new TextPresenter
{
PasswordChar = '*',
Text = "Test"
};
Assert.NotNull(target.FormattedText);
Assert.Equal("****", target.FormattedText.Text);
}
}
}

10
tests/Avalonia.Controls.UnitTests/TextBlockTests.cs

@ -15,5 +15,15 @@ namespace Avalonia.Controls.UnitTests
BindingMode.OneWay,
TextBlock.TextProperty.GetMetadata(typeof(TextBlock)).DefaultBindingMode);
}
[Fact]
public void Default_Text_Value_Should_Be_EmptyString()
{
var textBlock = new TextBlock();
Assert.Equal(
"",
textBlock.Text);
}
}
}

12
tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Indexer.cs

@ -338,6 +338,18 @@ namespace Avalonia.Markup.UnitTests.Data
GC.KeepAlive(data);
}
[Fact]
public async Task Indexer_Only_Binding_Works()
{
var data = new[] { 1, 2, 3 };
var target = new ExpressionObserver(data, "[1]");
var value = await target.Take(1);
Assert.Equal(data[1], value);
}
private class NonIntegerIndexer : NotifyingBase
{
private readonly Dictionary<string, string> _storage = new Dictionary<string, string>();

Loading…
Cancel
Save