Skip to content

Commit

Permalink
feat: add event interfaces IOnAttachToPanel, IOnDetachFromPanel & IOn…
Browse files Browse the repository at this point in the history
…GeometryChanged
  • Loading branch information
jonisavo committed Jun 11, 2022
1 parent cebefa4 commit ee16a5e
Show file tree
Hide file tree
Showing 14 changed files with 202 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Assets/UIComponents.Tests/Editor/Interfaces.meta

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using UnityEditor;
using UnityEngine.UIElements;

namespace UIComponents.Tests.Editor.Interfaces
{
public class InterfacesTestEditorWindow : EditorWindow
{
private void CreateGUI()
{
rootVisualElement.Add(new Label("Hello world"));
}

public void AddTestComponent(UIComponent component)
{
rootVisualElement.Add(component);
}
}
}

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using NUnit.Framework;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

namespace UIComponents.Tests.Editor.Interfaces
{
[TestFixture]
public class UIComponentInterfaceTests
{
private class BaseTestComponent : UIComponent
{
public bool Fired { get; protected set; }
}

private static void Assert_Registers_Event_Callback<TComponent, TEvent>()
where TComponent : BaseTestComponent, new()
where TEvent : EventBase<TEvent>, new()
{
var window = EditorWindow.GetWindow<InterfacesTestEditorWindow>();
var component = new TComponent();
Assert.That(component.Fired, Is.False);
window.AddTestComponent(component);

using (var evt = new TEvent() { target = component })
component.SendEvent(evt);

Assert.That(component.Fired, Is.True);
window.Close();
}

private class UIComponentWithOnGeometryChanged : BaseTestComponent, IOnGeometryChanged
{
public void OnGeometryChanged(GeometryChangedEvent evt) => Fired = true;
}

[Test]
public void IOnGeometryChanged_Registers_GeometryChangedEvent_Callback()
{
Assert_Registers_Event_Callback<UIComponentWithOnGeometryChanged, GeometryChangedEvent>();
}

private class UIComponentWithOnAttachToPanel : BaseTestComponent, IOnAttachToPanel
{
public void OnAttachToPanel(AttachToPanelEvent evt) => Fired = true;
}

[Test]
public void IOnAttachToPanel_Registers_AttachToPanelEvent_Callback()
{
Assert_Registers_Event_Callback<UIComponentWithOnAttachToPanel, AttachToPanelEvent>();
}

private class UIComponentWithOnDetachFromPanel : BaseTestComponent, IOnDetachFromPanel
{
public void OnDetachFromPanel(DetachFromPanelEvent evt) => Fired = true;
}

[Test]
public void IOnDetachFromPanel_Registers_DetachFromPanelEvent_Callback()
{
Assert_Registers_Event_Callback<UIComponentWithOnDetachFromPanel, DetachFromPanelEvent>();
}
}
}

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

3 changes: 3 additions & 0 deletions Assets/UIComponents/Core/EventInterfaces.meta

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

15 changes: 15 additions & 0 deletions Assets/UIComponents/Core/EventInterfaces/IOnAttachToPanel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using JetBrains.Annotations;
using UnityEngine.UIElements;

namespace UIComponents
{
/// <summary>
/// When implemented by a <see cref="UIComponent"/>,
/// a callback for <see cref="AttachToPanelEvent"/> is
/// automatically registered in the UIComponent constructor.
/// </summary>
public interface IOnAttachToPanel
{
void OnAttachToPanel([NotNull] AttachToPanelEvent evt);
}
}

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

15 changes: 15 additions & 0 deletions Assets/UIComponents/Core/EventInterfaces/IOnDetachFromPanel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using JetBrains.Annotations;
using UnityEngine.UIElements;

namespace UIComponents
{
/// <summary>
/// When implemented by a <see cref="UIComponent"/>,
/// a callback for <see cref="DetachFromPanelEvent"/> is
/// automatically registered in the UIComponent constructor.
/// </summary>
public interface IOnDetachFromPanel
{
void OnDetachFromPanel([NotNull] DetachFromPanelEvent evt);
}
}

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

15 changes: 15 additions & 0 deletions Assets/UIComponents/Core/EventInterfaces/IOnGeometryChanged.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using JetBrains.Annotations;
using UnityEngine.UIElements;

namespace UIComponents
{
/// <summary>
/// When implemented by a <see cref="UIComponent"/>,
/// a callback for <see cref="GeometryChangedEvent"/> is
/// automatically registered in the UIComponent constructor.
/// </summary>
public interface IOnGeometryChanged
{
void OnGeometryChanged([NotNull] GeometryChangedEvent evt);
}
}

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

14 changes: 14 additions & 0 deletions Assets/UIComponents/Core/UIComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,20 @@ protected UIComponent()
QueryFieldsSetupProfilerMarker.Begin();
PopulateQueryFields();
QueryFieldsSetupProfilerMarker.End();

RegisterEventInterfaceCallbacks();
}

private void RegisterEventInterfaceCallbacks()
{
if (this is IOnAttachToPanel onAttachToPanel)
RegisterCallback<AttachToPanelEvent>(onAttachToPanel.OnAttachToPanel);

if (this is IOnDetachFromPanel onDetachFromPanel)
RegisterCallback<DetachFromPanelEvent>(onDetachFromPanel.OnDetachFromPanel);

if (this is IOnGeometryChanged onGeometryChanged)
RegisterCallback<GeometryChangedEvent>(onGeometryChanged.OnGeometryChanged);
}

/// <summary>
Expand Down
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,37 @@ Stylesheets will be applied to `ChildComponent` in the following order:

This means that child components can override styles from their parents.

## Event interfaces

UIComponents supports a number of event interfaces. When implemented, the callbacks
are automatically registered in the UIComponent constructor.

The interfaces are:
- `IOnAttachToPanel` for `AttachToPanelEvent`
- `IOnDetachFromPanel` for `DetachFromPanelEvent`
- `IOnGeometryChanged` for `GeometryChangedEvent`

```c#
public class ComponentWithCallbacks : UIComponent, IOnAttachToPanel, IOnGeometryChanged, IOnDetachFromPanel
{
public void OnAttachToPanel(AttachToPanelEvent evt)
{
Debug.Log("Hello world");
}

public void OnGeometryChanged(GeometryChangedEvent evt)
{
Debug.Log("Geometry changed");
UnregisterCallback<GeometryChangedEvent>(OnGeometryChanged);
}

public void OnDetachFromPanel(DetachFromPanelEvent evt)
{
Debug.Log("Goodbye world");
}
}
```

## Experimental features

`[Query]` is an experimental feature that allows for populating fields automatically.
Expand Down

0 comments on commit ee16a5e

Please sign in to comment.