public TypeSelectorPopupContent(
            Func <float> widthCalculator,
            Action <Type> onTypeSelected,
            Func <Type, TypeSelectorGroup, TypeSelectorGroup> groupSelector = null,
            string noElementsFoundMessage = DefaultNoElementsFoundMessage,
            params Type[] validTypes)
        {
            this.onTypeSelected         = onTypeSelected;
            this.widthCalculator        = widthCalculator;
            this.noElementsFoundMessage = noElementsFoundMessage;
            rootGroup = new TypeSelectorGroup("Root");
            var types = new List <Type>();

            foreach (var validType in validTypes)
            {
                types.AddRange(Types.GetAllTypesOf(validType));
            }

            foreach (var type in types)
            {
                var a = (CategoryAttribute)type.GetCustomAttributes(typeof(CategoryAttribute), true)
                        .FirstOrDefault();
                TypeSelectorGroup group = null;
                if (a == null)
                {
                    if (groupSelector != null)
                    {
                        group = groupSelector(type, rootGroup);
                    }
                }
                else
                {
                    group = rootGroup.FindSubGroup(a.Category);
                }

                group = group ?? rootGroup;
                group.GroupTypes.Add(type);
            }
        }
        public override void OnGUI(Rect rect)
        {
            var pStyle      = PathStyle.Value;
            var path        = string.Join("/", Path.Reverse().ToArray());
            var pathContent = new GUIContent($"/{path}");
            var pathHeight  = pStyle.CalcHeight(pathContent, rect.width) + 5;

            GUI.Box(rect.SetHeight(SearchHeight + pathHeight), GUIContent.none);
            var searchRect = rect;

            searchRect.height = SearchHeight;
            searchString      = searchField.OnGUI(searchRect.Padding(5), searchString);

            var labelRect = rect;

            labelRect.yMin = searchRect.yMax;
            labelRect.yMax = labelRect.yMin + pathHeight;

            var groupRect = rect;

            groupRect.yMin = labelRect.yMax;
            if (!searchString.IsEmpty())
            {
                // Draw Search
                var viewRect   = groupRect.SubXMax(16);
                var foundTypes = rootGroup.SearchTypes(searchString);
                viewRect.height = foundTypes.Sum(type
                                                 => TypeSelectorGroup.ItemStyle.Value.CalcHeight(
                                                     new GUIContent(type.GetLegibleName(), type.FindUnityIcon()), viewRect.width));
                using (var scope = new GUI.ScrollViewScope(groupRect, searchScroll, viewRect)) {
                    searchScroll = scope.scrollPosition;
                    TypeSelectorGroup.DrawItems(foundTypes, viewRect, onTypeSelected);
                }
            }
            else
            {
                // Draw Tree
                searchScroll = Vector2.zero;

                var group = rootGroup.FindSubGroup(path);
                EditorGUI.LabelField(labelRect, pathContent, pStyle);
                if (!IsAtRoot)
                {
                    var backArrow = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector)
                                    .GetStyle(GUIStyles.ACLeftArrow);
                    var returnRect = labelRect.SetXMax(labelRect.x + labelRect.height);
                    if (GUI.Button(returnRect, GUIContent.none, backArrow))
                    {
                        Path.Pop();
                    }

                    //backArrow.Draw(returnRect, false, false, false, false);
                }

                if (group.IsEmpty())
                {
                    EditorGUI.LabelField(groupRect, noElementsFoundMessage, EditorStyles.boldLabel);
                }
                else
                {
                    group.Draw(groupRect, this, onTypeSelected);
                }
            }

            editorWindow.Repaint();
        }