PackageNotificationUtils.cs
5.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.XR.Management.Metadata;
using UnityEngine;
using Styles = UnityEditor.XR.Management.XRSettingsManager.Styles;
namespace UnityEditor.XR.Management
{
/// <summary>
/// This class holds information that should be displayed in an Editor tooltip for a given package.
/// </summary>
public class PackageNotificationInfo
{
private PackageNotificationInfo() {}
/// <summary>
/// Constructs a container for package notification information that displays in the XR Plug-in Management window.
/// </summary>
/// <param name="userInterfaceIcon">
/// The <c>GUIContent</c> icon to display in the XR Plug-in Management window. If the tooltip of this
/// icon is empty, null, only whitespace, or otherwise invalid, the constructor will throw an exception.
/// </param>
/// <param name="additionalInfoUri">
/// Used to surface a URI that points to additional information about the notification. For example, clicking the
/// icon directly could send the user to the package documentation website.
/// </param>
/// <exception cref="ArgumentException">
/// Thrown if either <see cref="userInterfaceIcon"/> does not contain a valid tooltip or if
/// <see cref="additionalInfoUri"/> is not empty and isn't a valid URI string.
/// </exception>
public PackageNotificationInfo(GUIContent userInterfaceIcon, string tooltip, string additionalInfoUri = default)
{
if (string.IsNullOrWhiteSpace(tooltip) || tooltip.Length == 0)
throw new ArgumentException("The package warning tooltip must contain a displayable message!");
if (additionalInfoUri != default)
{
if (!(Uri.TryCreate(additionalInfoUri, UriKind.Absolute, out var uriResult) && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps)))
throw new ArgumentException($"The supplied information URI {additionalInfoUri} must be a well formatted URI string!");
userInterfaceIcon.tooltip = $"{tooltip}\n\nClick the icon for additional information.";
}
else
userInterfaceIcon.tooltip = tooltip;
this.additionalInfoUri = additionalInfoUri;
this.userInterfaceIcon = userInterfaceIcon;
}
/// <summary>
/// A read-only string that contains a link to additional information about the warning.
/// </summary>
/// <remarks>
/// If this is null or empty, the window will not redirect the user.
/// </remarks>
public readonly string additionalInfoUri;
/// <summary>
/// The GUI icon and tooltip that will be drawn for this <c>PackageNotificationInfo</c>.
/// </summary>
public readonly GUIContent userInterfaceIcon;
}
/// <summary>
/// Static utility class for managing package notifications for packages.
/// </summary>
public static class PackageNotificationUtils
{
static Dictionary<string, PackageNotificationInfo> s_RegisteredPackagesWithNotifications = new Dictionary<string, PackageNotificationInfo>();
/// <summary>
/// Dictionary of packages that have notification to report. When a package is added to the project,
/// that package will register itself with this container if it requires access to notification functionality.
/// </summary>
/// <remarks>
/// This is a read-only dictionary and cannot be modified. To modify the dictionary, use the
/// <see cref="RegisterPackageNotificationInformation"/> method.
/// </remarks>
public static IReadOnlyDictionary<string, PackageNotificationInfo> registeredPackagesWithNotifications =>
s_RegisteredPackagesWithNotifications.ToDictionary(pair => pair.Key, pair => pair.Value);
/// <summary>
/// Registers a given package ID as having a notification and supplies that notification.
/// </summary>
/// <param name="packageId">
/// The metadata identifier for a given package <see cref="IXRPackageMetadata.packageId"/>
/// </param>
/// <param name="notificationInfo">
/// The <see cref="PackageNotificationInfo"/> for the package that corresponds to <see cref="packageId"/>.
/// </param>
public static void RegisterPackageNotificationInformation(string packageId, PackageNotificationInfo notificationInfo)
{
if (s_RegisteredPackagesWithNotifications.ContainsKey(packageId))
s_RegisteredPackagesWithNotifications[packageId] = notificationInfo;
else
s_RegisteredPackagesWithNotifications.Add(packageId, notificationInfo);
}
const int k_RectPixelOffsetWidth = 5;
internal static void DrawNotificationIconUI(PackageNotificationInfo notificationInfo, Rect guiRect, int pixelOffset = k_RectPixelOffsetWidth)
{
var position = new Vector2(guiRect.xMax - (notificationInfo.userInterfaceIcon.image.width + pixelOffset), guiRect.y);
var size = new Vector2(notificationInfo.userInterfaceIcon.image.width, guiRect.height);
var toolTipRect = new Rect(position, size);
var labelStyle = EditorGUIUtility.isProSkin ? Styles.k_UrlLabelProfessional : Styles.k_UrlLabelPersonal;
if (GUI.Button(toolTipRect, notificationInfo.userInterfaceIcon, labelStyle))
LaunchLink(notificationInfo);
}
static void LaunchLink(PackageNotificationInfo info)
{
if (info.additionalInfoUri.Length > 0)
Application.OpenURL(info.additionalInfoUri);
}
}
}