Initial commit: Unity WordConnect project
This commit is contained in:
@ -0,0 +1,323 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using VContainer.Diagnostics;
|
||||
using VContainer.Unity;
|
||||
|
||||
namespace VContainer.Editor.Diagnostics
|
||||
{
|
||||
public sealed class DiagnosticsInfoTreeViewItem : TreeViewItem
|
||||
{
|
||||
public string ScopeName { get; set; }
|
||||
public DiagnosticsInfo DiagnosticsInfo { get; }
|
||||
|
||||
public RegistrationBuilder RegistrationBuilder => DiagnosticsInfo.RegisterInfo.RegistrationBuilder;
|
||||
public Registration Registration => DiagnosticsInfo.ResolveInfo.Registration;
|
||||
public int? RefCount => DiagnosticsInfo.ResolveInfo.RefCount;
|
||||
public long ResolveTime => DiagnosticsInfo.ResolveInfo.ResolveTime;
|
||||
|
||||
public string TypeSummary => TypeNameHelper.GetTypeAlias(Registration.ImplementationType);
|
||||
|
||||
public string ContractTypesSummary
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Registration.InterfaceTypes != null)
|
||||
{
|
||||
var values = Registration.InterfaceTypes.Select(TypeNameHelper.GetTypeAlias);
|
||||
return string.Join(", ", values);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public string RegisterSummary
|
||||
{
|
||||
get
|
||||
{
|
||||
if (RegistrationBuilder == null)
|
||||
return "";
|
||||
|
||||
var type = RegistrationBuilder.GetType();
|
||||
if (type == typeof(RegistrationBuilder))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
var typeName = type.Name;
|
||||
var suffixIndex = typeName.IndexOf("Builder");
|
||||
if (suffixIndex > 0)
|
||||
{
|
||||
typeName = typeName.Substring(0, suffixIndex);
|
||||
}
|
||||
suffixIndex = typeName.IndexOf("Registration");
|
||||
if (suffixIndex > 0)
|
||||
{
|
||||
typeName = typeName.Substring(0, suffixIndex);
|
||||
}
|
||||
|
||||
if (typeName.StartsWith("Instance") && TypeSummary.StartsWith("Func<"))
|
||||
{
|
||||
return "FuncFactory";
|
||||
}
|
||||
|
||||
return typeName;
|
||||
}
|
||||
}
|
||||
|
||||
public DiagnosticsInfoTreeViewItem(DiagnosticsInfo info)
|
||||
{
|
||||
ScopeName = info.ScopeName;
|
||||
DiagnosticsInfo = info;
|
||||
displayName = TypeSummary;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class VContainerDiagnosticsInfoTreeView : TreeView
|
||||
{
|
||||
static readonly MultiColumnHeaderState.Column[] Columns =
|
||||
{
|
||||
new MultiColumnHeaderState.Column { headerContent = new GUIContent("Type") },
|
||||
new MultiColumnHeaderState.Column { headerContent = new GUIContent("ContractTypes"), canSort = false },
|
||||
new MultiColumnHeaderState.Column { headerContent = new GUIContent("Lifetime"), width = 15f },
|
||||
new MultiColumnHeaderState.Column { headerContent = new GUIContent("Register"), width = 15f },
|
||||
new MultiColumnHeaderState.Column { headerContent = new GUIContent("RefCount"), width = 5f },
|
||||
new MultiColumnHeaderState.Column { headerContent = new GUIContent("Scope"), width = 20f },
|
||||
new MultiColumnHeaderState.Column { headerContent = new GUIContent("Time"), width = 20f },
|
||||
};
|
||||
|
||||
static int idSeed;
|
||||
static int NextId() => ++idSeed;
|
||||
|
||||
const string SessionStateKeySortedColumnIndex = "VContainer.Editor.DiagnosticsInfoTreeView:sortedColumnIndex";
|
||||
|
||||
public bool Flatten
|
||||
{
|
||||
get => flatten;
|
||||
set
|
||||
{
|
||||
flatten = value;
|
||||
multiColumnHeader.ResizeToFit();
|
||||
}
|
||||
}
|
||||
|
||||
bool flatten;
|
||||
|
||||
public VContainerDiagnosticsInfoTreeView()
|
||||
: this(new TreeViewState(), new MultiColumnHeader(new MultiColumnHeaderState(Columns)))
|
||||
{
|
||||
}
|
||||
|
||||
VContainerDiagnosticsInfoTreeView(TreeViewState state, MultiColumnHeader header)
|
||||
: base(state, header)
|
||||
{
|
||||
rowHeight = 20;
|
||||
showAlternatingRowBackgrounds = true;
|
||||
showBorder = true;
|
||||
header.sortingChanged += OnSortedChanged;
|
||||
|
||||
header.ResizeToFit();
|
||||
Reload();
|
||||
|
||||
header.sortedColumnIndex = Math.Min(
|
||||
header.state.columns.Length - 1,
|
||||
SessionState.GetInt(SessionStateKeySortedColumnIndex, 0));
|
||||
}
|
||||
|
||||
public DiagnosticsInfoTreeViewItem GetSelectedItem()
|
||||
{
|
||||
if (state.selectedIDs.Count <= 0) return null;
|
||||
|
||||
var selectedId = state.selectedIDs[0];
|
||||
return GetRows().FirstOrDefault(x => x.id == selectedId) as DiagnosticsInfoTreeViewItem;
|
||||
}
|
||||
|
||||
public void ReloadAndSort()
|
||||
{
|
||||
var currentSelected = state.selectedIDs;
|
||||
Reload();
|
||||
OnSortedChanged(multiColumnHeader);
|
||||
state.selectedIDs = currentSelected;
|
||||
}
|
||||
|
||||
void OnSortedChanged(MultiColumnHeader multiColumnHeader)
|
||||
{
|
||||
var columnIndex = multiColumnHeader.sortedColumnIndex;
|
||||
if (columnIndex < 0) return;
|
||||
|
||||
SessionState.SetInt(SessionStateKeySortedColumnIndex, columnIndex);
|
||||
var ascending = multiColumnHeader.IsSortedAscending(columnIndex);
|
||||
|
||||
if (Flatten)
|
||||
{
|
||||
var items = rootItem.children.Cast<DiagnosticsInfoTreeViewItem>();
|
||||
rootItem.children = new List<TreeViewItem>(Sort(items, columnIndex, ascending));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var sectionHeaderItem in rootItem.children)
|
||||
{
|
||||
var items = sectionHeaderItem.children.Cast<DiagnosticsInfoTreeViewItem>();
|
||||
sectionHeaderItem.children = new List<TreeViewItem>(Sort(items, columnIndex, ascending));
|
||||
}
|
||||
}
|
||||
BuildRows(rootItem);
|
||||
}
|
||||
|
||||
protected override TreeViewItem BuildRoot()
|
||||
{
|
||||
var root = new TreeViewItem { depth = -1 };
|
||||
var children = new List<TreeViewItem>();
|
||||
|
||||
if (VContainerSettings.DiagnosticsEnabled)
|
||||
{
|
||||
if (Flatten)
|
||||
{
|
||||
var infos = DiagnositcsContext.GetDiagnosticsInfos();
|
||||
foreach (var info in infos)
|
||||
{
|
||||
children.Add(new DiagnosticsInfoTreeViewItem(info)
|
||||
{
|
||||
id = NextId(),
|
||||
depth = 0,
|
||||
ScopeName = info.ScopeName,
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var grouped = DiagnositcsContext.GetGroupedDiagnosticsInfos();
|
||||
foreach (var scope in grouped)
|
||||
{
|
||||
var sectionHeaderItem = new TreeViewItem(NextId(), 0, scope.Key);
|
||||
children.Add(sectionHeaderItem);
|
||||
SetExpanded(sectionHeaderItem.id, true);
|
||||
|
||||
foreach (var info in scope)
|
||||
{
|
||||
AddDependencyItemsRecursive(info, sectionHeaderItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
root.children = children;
|
||||
return root;
|
||||
}
|
||||
|
||||
protected override bool CanMultiSelect(TreeViewItem item) => false;
|
||||
|
||||
protected override void RowGUI(RowGUIArgs args)
|
||||
{
|
||||
var item = args.item as DiagnosticsInfoTreeViewItem;
|
||||
if (item is null)
|
||||
{
|
||||
var cellRect = args.GetCellRect(0);
|
||||
GUI.BeginGroup(cellRect);
|
||||
{
|
||||
args.rowRect = new Rect(0, 0, cellRect.width, cellRect.height);
|
||||
base.RowGUI(args);
|
||||
}
|
||||
GUI.EndGroup();
|
||||
return;
|
||||
}
|
||||
|
||||
for (var visibleColumnIndex = 0; visibleColumnIndex < args.GetNumVisibleColumns(); visibleColumnIndex++)
|
||||
{
|
||||
var cellRect = args.GetCellRect(visibleColumnIndex);
|
||||
// CenterRectUsingSingleLineHeight(ref cellRect);
|
||||
var columnIndex = args.GetColumn(visibleColumnIndex);
|
||||
|
||||
var labelStyle = args.selected ? EditorStyles.whiteLabel : EditorStyles.label;
|
||||
labelStyle.alignment = TextAnchor.MiddleLeft;
|
||||
|
||||
switch (columnIndex)
|
||||
{
|
||||
case 0:
|
||||
GUI.BeginGroup(cellRect);
|
||||
{
|
||||
args.rowRect = new Rect(0, 0, cellRect.width, cellRect.height);
|
||||
base.RowGUI(args);
|
||||
}
|
||||
GUI.EndGroup();
|
||||
break;
|
||||
case 1:
|
||||
EditorGUI.LabelField(cellRect, item.ContractTypesSummary, labelStyle);
|
||||
break;
|
||||
case 2:
|
||||
EditorGUI.LabelField(cellRect, item.Registration.Lifetime.ToString(), labelStyle);
|
||||
break;
|
||||
case 3:
|
||||
EditorGUI.LabelField(cellRect, item.RegisterSummary, labelStyle);
|
||||
break;
|
||||
case 4:
|
||||
EditorGUI.LabelField(cellRect, item.RefCount.ToString(), labelStyle);
|
||||
break;
|
||||
case 5:
|
||||
EditorGUI.LabelField(cellRect, item.ScopeName, labelStyle);
|
||||
break;
|
||||
case 6:
|
||||
EditorGUI.LabelField(cellRect, item.ResolveTime.ToString(), labelStyle);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(columnIndex), columnIndex, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddDependencyItemsRecursive(DiagnosticsInfo info, TreeViewItem parent)
|
||||
{
|
||||
var item = new DiagnosticsInfoTreeViewItem(info)
|
||||
{
|
||||
id = NextId(),
|
||||
depth = parent.depth + 1
|
||||
};
|
||||
parent.AddChild(item);
|
||||
SetExpanded(item.id, item.depth <= 1);
|
||||
|
||||
foreach (var dependency in info.Dependencies)
|
||||
{
|
||||
AddDependencyItemsRecursive(dependency, item);
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerable<DiagnosticsInfoTreeViewItem> Sort(
|
||||
IEnumerable<DiagnosticsInfoTreeViewItem> items,
|
||||
int sortedColumnIndex,
|
||||
bool ascending)
|
||||
{
|
||||
switch (sortedColumnIndex)
|
||||
{
|
||||
case 0:
|
||||
return ascending
|
||||
? items.OrderBy(x => x.TypeSummary)
|
||||
: items.OrderByDescending(x => x.TypeSummary);
|
||||
case 2:
|
||||
return ascending
|
||||
? items.OrderBy(x => x.Registration.Lifetime)
|
||||
: items.OrderByDescending(x => x.Registration.Lifetime);
|
||||
case 3:
|
||||
return ascending
|
||||
? items.OrderBy(x => x.RegisterSummary)
|
||||
: items.OrderByDescending(x => x.RegisterSummary);
|
||||
case 4:
|
||||
return ascending
|
||||
? items.OrderBy(x => x.RefCount)
|
||||
: items.OrderByDescending(x => x.RefCount);
|
||||
case 5:
|
||||
return ascending
|
||||
? items.OrderBy(x => x.ScopeName)
|
||||
: items.OrderByDescending(x => x.ScopeName);
|
||||
case 6:
|
||||
return ascending
|
||||
? items.OrderBy(x => x.ResolveTime)
|
||||
: items.OrderByDescending(x => x.ResolveTime);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(sortedColumnIndex), sortedColumnIndex, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user