Skip to content

Commit

Permalink
feat(QueryAttribute): move out of the experimental namespace
Browse files Browse the repository at this point in the history
BREAKING CHANGE: QueryAttribute has been moved from the UIComponents.Experimental namespace to UIComponents.
  • Loading branch information
jonisavo committed Jul 9, 2022
1 parent 35a9ab8 commit dc40380
Show file tree
Hide file tree
Showing 11 changed files with 134 additions and 59 deletions.
2 changes: 1 addition & 1 deletion Assets/Samples/Query/Editor/QueryExampleComponentWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace UIComponents.Samples.Query.Editor
{
public class QueryExampleComponentWindow : EditorWindow
{
[MenuItem("UIComponents Examples/Experimental/Query")]
[MenuItem("UIComponents Examples/Query")]
private static void ShowWindow()
{
var window = GetWindow<QueryExampleComponentWindow>();
Expand Down
3 changes: 1 addition & 2 deletions Assets/Samples/Query/QueryExampleComponent.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using UIComponents.Experimental;
using UnityEngine;
using UnityEngine;
using UnityEngine.UIElements;

namespace UIComponents.Samples.Query
Expand Down
2 changes: 1 addition & 1 deletion Assets/Samples/Query/Resources/QueryExampleComponent.uxml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<UXML xmlns:ui="UnityEngine.UIElements">
<ui:Label class="description" text="This is a component for demonstrating QueryAttribute, an experimental feature in UIComponents." />
<ui:Label class="description" text="This is a component for demonstrating QueryAttribute." />
<ui:Label class="description" text="QueryAttribute allows for populating UIComponent fields automatically." />
<ui:Label name="my-label" />
<ui:Foldout name="my-foldout" text="Foldout...">
Expand Down
2 changes: 1 addition & 1 deletion Assets/UIComponents.Benchmarks/BenchmarkUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace UIComponents.Benchmarks
{
public static class BenchmarkUtils
{
public const string Version = "0.16.0.0";
public const string Version = "0.17.0.0";

private static SampleGroup[] GetProfilerMarkers()
{
Expand Down
67 changes: 67 additions & 0 deletions Assets/UIComponents.Benchmarks/UIComponentFieldCacheBenchmarks.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using System.Collections;
using System.Collections.Generic;
using NUnit.Framework;
using UIComponents.Cache;
using UIComponents.Experimental;
using Unity.PerformanceTesting;
using UnityEngine.UIElements;

namespace UIComponents.Benchmarks
{
public class UIComponentFieldCacheBenchmarks
{
private class EmptyComponent : UIComponent {}

private static void MeasureFieldCache<TComponent>() where TComponent : UIComponent
{
Measure.Method(() => { new FieldCache(typeof(TComponent)); })
.SampleGroup(new SampleGroup("Time"))
.MeasurementCount(100)
.IterationsPerMeasurement(100)
.GC()
.Run();
}

[Test, Performance, Version(BenchmarkUtils.Version)]
public void InitializeEmptyComponent()
{
MeasureFieldCache<EmptyComponent>();
}

private class ComponentWithFields : UIComponent
{
[Query("hello-world-label")]
public readonly Label HelloWorldLabel;

[Query(Name = "test-foldout")]
public readonly Foldout TestFoldout;

[Query]
public readonly Label FirstLabel;

[Query(Class = "text")]
public readonly Label[] LabelsWithTextClass;

[Query(Name = "hello-world-label", Class = "text")]
public readonly Label HelloWorldLabelWithTextClass;

[Query]
public readonly List<Label> AllLabelsImplicit;

[Query(Name = "hello-world-label")]
[Query(Name = "foldout-content")]
public readonly List<Label> AllLabelsExplicit;

[Provide]
public readonly IList StringProperty;
[Provide]
public readonly IList FloatProperty;
}

[Test, Performance, Version(BenchmarkUtils.Version)]
public void InitializeComponentWithFields()
{
MeasureFieldCache<ComponentWithFields>();
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion Assets/UIComponents.Tests/QueryAttributeTests.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.Collections.Generic;
using NSubstitute;
using NUnit.Framework;
using UIComponents.Experimental;
using UIComponents.Utilities;
using UnityEngine.UIElements;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using JetBrains.Annotations;
using UnityEngine.UIElements;

namespace UIComponents.Experimental
namespace UIComponents
{
/// <summary>
/// An attribute for specifying a single query for a field.
Expand Down
2 changes: 1 addition & 1 deletion Assets/UIComponents/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"path": "Samples~/Addressables"
},
{
"displayName": "QueryAttribute (experimental)",
"displayName": "QueryAttribute",
"description": "Contains an example of using QueryAttribute to populate fields.",
"path": "Samples~/Query"
},
Expand Down
109 changes: 58 additions & 51 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,18 @@ class MyComponent : UIComponent
// constructor. They are retrieved from Resources by default,
// hence the lack of file extensions.
// Queries are made in the inherited constructor.
[Query("hello-world-label")]
private readonly Label _countLabel;

private readonly ICounterService _counterService;

public MyComponent()
{
// Will yield a CounterService.
_counterService = Provide<ICounterService>();

_countLabel.text = _counterService.Count.ToString();
}
}
```
Expand Down Expand Up @@ -167,6 +173,58 @@ to the root element of the UIComponent.
public class UIComponentWithRootClass : UIComponent {}
```

### QueryAttribute

`[Query]` is allows for populating fields automatically. You can query for a single
element or many at once.

```xml
<!-- Resources/MyLayout.uxml -->
<UXML xmlns:ui="UnityEngine.UIElements">
<ui:Label name="hello-world-label" text="Hello world!" class="text" />
<ui:Foldout name="test-foldout">
<ui:Label name="foldout-content" text="Foldout content" class="text" />
</ui:Foldout>
</UXML>
```
```c#
using UIComponents;

[Layout("MyLayout")]
public class MyComponent : UIComponent
{
[Query("hello-world-label")]
public readonly Label HelloWorldLabel;

[Query(Name = "test-foldout")]
public readonly Foldout TestFoldout;

[Query]
public readonly Label FirstLabel;

[Query(Class = "text")]
public readonly Label[] LabelsWithTextClass;

[Query(Name = "hello-world-label", Class = "text")]
public readonly Label HelloWorldLabelWithTextClass;

[Query]
public readonly List<Label> AllLabelsImplicit;

[Query(Name = "hello-world-label")]
[Query(Name = "foldout-content")]
public readonly List<Label> AllLabelsExplicit;

public MyComponent()
{
HelloWorldLabel.text = "Goodbye world!";
TestFoldout.Add(new Label("More content!"));
}
}
```

`[Query]` only works on fields that are assignable to `VisualElement`. Others are ignored.

## Event interfaces

UIComponents supports a number of event interfaces. When implemented, the callbacks
Expand Down Expand Up @@ -224,57 +282,6 @@ public class ComponentWithCallbacks : UIComponent,

## Experimental features

### QueryAttribute

`[Query]` is an experimental feature that allows for populating fields automatically.
It is accessible via the `UIComponents.Experimental` namespace.

```xml
<!-- Resources/MyLayout.uxml -->
<UXML xmlns:ui="UnityEngine.UIElements">
<ui:Label name="hello-world-label" text="Hello world!" class="text" />
<ui:Foldout name="test-foldout">
<ui:Label name="foldout-content" text="Foldout content" class="text" />
</ui:Foldout>
</UXML>
```
```c#
using UIComponents;
using UIComponents.Experimental;

[Layout("MyLayout")]
public class MyComponent : UIComponent
{
[Query("hello-world-label")]
public readonly Label HelloWorldLabel;

[Query(Name = "test-foldout")]
public readonly Foldout TestFoldout;

[Query]
public readonly Label FirstLabel;

[Query(Class = "text")]
public readonly Label[] LabelsWithTextClass;

[Query(Name = "hello-world-label", Class = "text")]
public readonly Label HelloWorldLabelWithTextClass;

[Query]
public readonly List<Label> AllLabelsImplicit;

[Query(Name = "hello-world-label")]
[Query(Name = "foldout-content")]
public readonly List<Label> AllLabelsExplicit;

public MyComponent()
{
HelloWorldLabel.text = "Goodbye world!";
TestFoldout.Add(new Label("More content!"));
}
}
```

### ProvideAttribute

`[Provide]` will provide dependencies for you. It is accessible via the
Expand Down

0 comments on commit dc40380

Please sign in to comment.