Editor/Dock/ReadinessCard.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Editor;
using Sandbox;
namespace TeamCreate;
public sealed class ReadinessCard : DockCard
{
private sealed class ItemBody : Widget
{
private readonly ReadinessItem item;
public ItemBody(Widget parent, ReadinessItem item)
: base(parent)
{
this.item = item;
FixedHeight = DockTheme.RowHeight;
ToolTip = item.Detail ?? string.Empty;
OnPaintOverride = PaintItem;
}
private bool PaintItem()
{
Rect localRect = LocalRect;
Paint.SetPen(DockTheme.StatusColor(item.Level), 0f, PenStyle.Solid);
Paint.DrawIcon(new Rect(localRect.Left, localRect.Top, 16f, localRect.Height), DockTheme.LevelIcon(item.Level), 14f, TextFlag.LeftCenter);
Paint.SetPen(Theme.Text.WithAlpha(0.55f), 0f, PenStyle.Solid);
Paint.DrawIcon(new Rect(localRect.Left + 18f, localRect.Top, 14f, localRect.Height), DockTheme.ReadinessIcon(item.Key), 12f, TextFlag.LeftCenter);
string text = item.Title ?? string.Empty;
float width = ((text.Length == 0) ? 0f : (Paint.MeasureText(text).x + 8f));
float x = localRect.Left + 36f;
Paint.SetPen(in Theme.Text, 0f, PenStyle.Solid);
if (width > 0f)
{
Paint.DrawText(new Rect(in x, localRect.Top, in width, localRect.Height), text, TextFlag.LeftCenter | TextFlag.SingleLine);
}
string text2 = item.Detail ?? string.Empty;
float x2 = x + width;
float width2 = localRect.Right - x2 - 4f;
if (text2.Length > 0 && width2 > 8f)
{
string elidedText = Paint.GetElidedText(text2, width2);
Paint.SetPen(Theme.Text.WithAlpha(0.6f), 0f, PenStyle.Solid);
Paint.DrawText(new Rect(in x2, localRect.Top, in width2, localRect.Height), elidedText, TextFlag.LeftCenter | TextFlag.SingleLine);
}
return false;
}
}
private readonly Widget rows;
private readonly Label notice;
private IReadOnlyList<ReadinessItem> lastList;
private string signature;
protected override bool FieldsAssigned => rows != null && notice != null;
public ReadinessCard(Widget parent)
: base(parent, "Readiness")
{
rows = Layout.Add(new Widget(this));
rows.Layout = Layout.Column();
rows.Layout.Spacing = 4f;
notice = Layout.Add(new Label("", this)
{
WordWrap = true,
Color = DockTheme.WarningColor
});
notice.Visible = false;
Refresh();
}
public void Refresh()
{
IReadOnlyList<ReadinessItem> readiness = CollaborationSession.Current.Readiness;
if (readiness != lastList)
{
lastList = readiness;
string a = Signature(readiness);
if (!string.Equals(a, signature, StringComparison.Ordinal))
{
signature = a;
Rebuild(readiness);
}
}
}
private static string Signature(IReadOnlyList<ReadinessItem> list)
{
if (list == null || list.Count == 0)
{
return string.Empty;
}
StringBuilder stringBuilder = new StringBuilder(list.Count * 64);
foreach (ReadinessItem item in list)
{
if ((object)item != null)
{
stringBuilder.Append(item.Key).Append('|').Append(item.Level)
.Append('|')
.Append(item.Title)
.Append('|')
.Append(item.Detail)
.Append('|')
.Append(item.Fix)
.Append('\n');
}
}
return stringBuilder.ToString();
}
private void Rebuild(IReadOnlyList<ReadinessItem> list)
{
rows.Layout.Clear(deleteWidgets: true);
if (list == null || list.Count == 0)
{
rows.Layout.Add(new Label("The readiness checklist has not been evaluated yet.", this)
{
WordWrap = true,
Color = DockTheme.MutedColor
});
return;
}
foreach (ReadinessItem item in list)
{
if ((object)item != null)
{
Widget widget = rows.Layout.Add(new Widget(rows));
widget.Layout = Layout.Row();
widget.Layout.Spacing = 4f;
widget.Layout.Add(new ItemBody(widget, item), 1);
Widget widget2 = FixButton(widget, item);
if (widget2 != null)
{
widget.Layout.Add(widget2);
}
}
}
}
private Widget FixButton(Widget parent, ReadinessItem item)
{
if (string.IsNullOrWhiteSpace(item.Fix))
{
return null;
}
if (string.Equals(item.Fix, "Update", StringComparison.Ordinal))
{
return new Button("Update", parent)
{
ToolTip = "Install the current copy of the collaboration library from Asset Party.",
Clicked = () =>
{
_ = UpdateLibrary();
}
};
}
return new Button(item.Fix, parent)
{
Enabled = false,
ToolTip = "This build has no action for this item."
};
}
private async Task UpdateLibrary()
{
try
{
CollaborationConfig config = CollaborationSession.Current.Config;
string ident = FullIdent(config);
if (ident == null)
{
SetNotice("The collaboration library ident is not configured in ProjectSettings/collaboration.json.");
return;
}
SetNotice("Requesting the current copy of " + ident + " from Asset Party…");
Package package = await Package.FetchAsync(ident, partial: false);
if (package?.Revision == null)
{
SetNotice("The package " + ident + " could not be fetched from Asset Party.");
return;
}
await LibrarySystem.Install(ident, package.Revision.VersionId);
SetNotice("The collaboration library is being installed. The checklist reports the installed version when it finishes.");
}
catch (Exception ex)
{
Exception e = ex;
SetNotice(CollaborationDiagnostics.Bounded(e.Message));
}
}
private static string FullIdent(CollaborationConfig config)
{
string text = config?.LibraryIdent;
if (string.IsNullOrWhiteSpace(text))
{
// A project with no settings file yet still knows which package to fetch: the published one under its own organization.
return LibraryInfo.DefaultLibraryIdent(config?.Org);
}
if (text.Contains('.'))
{
return text;
}
string org = config.Org;
return string.IsNullOrWhiteSpace(org) ? text : (org + "." + text);
}
private void SetNotice(string text)
{
notice.Text = text ?? string.Empty;
notice.Visible = notice.Text.Length > 0;
}
}