Add concept of "attributes" to UITree. So far the values are only allowed to be strings, but this will have to change later.
This commit is contained in:
parent
f0a78d13bf
commit
0db6f5cc5d
|
|
@ -15,6 +15,7 @@ namespace Microsoft.Blazor.UITree
|
|||
private UITreeNode[] _entries = new UITreeNode[100];
|
||||
private int _entriesInUse = 0;
|
||||
private Stack<int> _openElementIndices = new Stack<int>();
|
||||
private UITreeNodeType? _lastNonAttributeNodeType;
|
||||
|
||||
/// <summary>
|
||||
/// Appends a node representing an element, i.e., a container for other nodes.
|
||||
|
|
@ -46,6 +47,24 @@ namespace Microsoft.Blazor.UITree
|
|||
public void AddText(string textContent)
|
||||
=> Append(UITreeNode.Text(textContent));
|
||||
|
||||
/// <summary>
|
||||
/// Appends a node representing an attribute. The attribute is associated
|
||||
/// with the most recently added element.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the attribute.</param>
|
||||
/// <param name="value">The value of the attribute.</param>
|
||||
public void AddAttribute(string name, string value)
|
||||
{
|
||||
if (_lastNonAttributeNodeType == UITreeNodeType.Element)
|
||||
{
|
||||
Append(UITreeNode.Attribute(name, value));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException($"Attributes may only be added immediately after nodes of type {UITreeNodeType.Element}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the builder.
|
||||
/// </summary>
|
||||
|
|
@ -61,6 +80,7 @@ namespace Microsoft.Blazor.UITree
|
|||
|
||||
_entriesInUse = 0;
|
||||
_openElementIndices.Clear();
|
||||
_lastNonAttributeNodeType = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -79,6 +99,12 @@ namespace Microsoft.Blazor.UITree
|
|||
}
|
||||
|
||||
_entries[_entriesInUse++] = node;
|
||||
|
||||
var nodeType = node.NodeType;
|
||||
if (nodeType != UITreeNodeType.Attribute)
|
||||
{
|
||||
_lastNonAttributeNodeType = node.NodeType;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,10 @@
|
|||
|
||||
namespace Microsoft.Blazor.UITree
|
||||
{
|
||||
// TODO: Consider coalescing properties of compatible types that don't need to be
|
||||
// used simultaneously. For example, 'ElementName' and 'AttributeName' could be replaced
|
||||
// by a single 'Name' property.
|
||||
|
||||
/// <summary>
|
||||
/// Represents an entry in a tree of user interface (UI) items.
|
||||
/// </summary>
|
||||
|
|
@ -32,6 +36,18 @@ namespace Microsoft.Blazor.UITree
|
|||
/// </summary>
|
||||
public string TextContent { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="NodeType"/> property equals <see cref="UITreeNodeType.Attribute"/>,
|
||||
/// gets the attribute name. Otherwise, the value is <see langword="null"/>.
|
||||
/// </summary>
|
||||
public string AttributeName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="NodeType"/> property equals <see cref="UITreeNodeType.Attribute"/>,
|
||||
/// gets the attribute value. Otherwise, the value is <see langword="null"/>.
|
||||
/// </summary>
|
||||
public string AttributeValue { get; private set; }
|
||||
|
||||
internal static UITreeNode Element(string elementName) => new UITreeNode
|
||||
{
|
||||
NodeType = UITreeNodeType.Element,
|
||||
|
|
@ -44,6 +60,13 @@ namespace Microsoft.Blazor.UITree
|
|||
TextContent = textContent,
|
||||
};
|
||||
|
||||
internal static UITreeNode Attribute(string name, string value) => new UITreeNode
|
||||
{
|
||||
NodeType = UITreeNodeType.Attribute,
|
||||
AttributeName = name,
|
||||
AttributeValue = value
|
||||
};
|
||||
|
||||
internal void CloseElement(int descendantsEndIndex)
|
||||
{
|
||||
ElementDescendantsEndIndex = descendantsEndIndex;
|
||||
|
|
|
|||
|
|
@ -17,5 +17,10 @@ namespace Microsoft.Blazor.UITree
|
|||
/// Represents text content.
|
||||
/// </summary>
|
||||
Text = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Represents a key-value pair associated with another <see cref="UITreeNode"/>.
|
||||
/// </summary>
|
||||
Attribute = 3,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.Blazor.UITree;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -130,6 +131,60 @@ namespace Microsoft.Blazor.Test
|
|||
node => AssertText(node, "standalone text 2"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanAddAttributes()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new UITreeBuilder();
|
||||
|
||||
// Act
|
||||
builder.OpenElement("myelement"); // 0: <myelement
|
||||
builder.AddAttribute("attribute1", "value 1"); // 1: attribute1="value 1"
|
||||
builder.AddAttribute("attribute2", "value 2"); // 2: attribute2="value 2">
|
||||
builder.OpenElement("child"); // 3: <child
|
||||
builder.AddAttribute("attribute1", "child value"); // 4: attribute1="child value">
|
||||
builder.AddText("some text"); // 5: some text
|
||||
builder.CloseElement(); // </child>
|
||||
builder.CloseElement(); // </myelement>
|
||||
|
||||
// Assert
|
||||
Assert.Collection(builder.GetNodes(),
|
||||
node => AssertElement(node, "myelement", 5),
|
||||
node => AssertAttribute(node, "attribute1", "value 1"),
|
||||
node => AssertAttribute(node, "attribute2", "value 2"),
|
||||
node => AssertElement(node, "child", 5),
|
||||
node => AssertAttribute(node, "attribute1", "child value"),
|
||||
node => AssertText(node, "some text"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CannotAddAttributesAtRoot()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new UITreeBuilder();
|
||||
|
||||
// Act/Assert
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
builder.AddAttribute("name", "value");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CannotAddAttributesToText()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new UITreeBuilder();
|
||||
|
||||
// Act/Assert
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
builder.OpenElement("some element");
|
||||
builder.AddText("hello");
|
||||
builder.AddAttribute("name", "value");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanClear()
|
||||
{
|
||||
|
|
@ -160,5 +215,12 @@ namespace Microsoft.Blazor.Test
|
|||
Assert.Equal(elementName, node.ElementName);
|
||||
Assert.Equal(descendantsEndIndex, node.ElementDescendantsEndIndex);
|
||||
}
|
||||
|
||||
void AssertAttribute(UITreeNode node, string attributeName, string attributeValue)
|
||||
{
|
||||
Assert.Equal(UITreeNodeType.Attribute, node.NodeType);
|
||||
Assert.Equal(attributeName, node.AttributeName);
|
||||
Assert.Equal(attributeValue, node.AttributeValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue