/// <summary>
 /// Adds VisualElements corresponding to the provided rich text to a root.
 /// </summary>
 /// <param name="text">The rich text to parse</param>
 /// <param name="root">Visual Element to append the rich text UI to, current default if left null</param>
 /// <returns>A list of all immediate children added to the root.</returns>
 public List <VisualElement> AddRichText(string text, VisualElement root = null) => RichTextUtility.AddRichText(text, content, content.GetRoot(root));
Esempio n. 2
0
        void DoSearch()
        {
            EditorPrefs.SetString(searchEditorPrefsKey, searchString);

            if (string.IsNullOrEmpty(searchString))
            {
                searchRoot.Clear();
                searchRoot.visible = false;
                return;
            }

            string searchStringLower = searchString.ToLower();

            //Cache current page
            string currentPageStateNameCached = currentPageStateName;

            //Clear the previous search
            searchRoot.Clear();
            searchRoot.visible = true;

            //searchRootTemp is an un-parented root to append to so we can search content.
            VisualElement searchRootTemp = new VisualElement();
            Dictionary <IDocumentationPage <T>, List <string> > searchResults = new Dictionary <IDocumentationPage <T>, List <string> >();

            StringBuilder stringBuilder = new StringBuilder();

            foreach (IDocumentationPage <T> page in pages.Values)
            {
                if (!searchStringsCache.TryGetValue(page, out var searchStrings))
                {
                    searchStrings = new List <string>();
                    searchStringsCache.Add(page, searchStrings);

                    //Load the page under searchRootTemp
                    LoadPage(page, searchRootTemp);

                    //Get all the paragraph element's text (combined together)
                    searchRootTemp.Query(null, "paragraph-container").ForEach(paragraph =>
                    {
                        stringBuilder.Clear();
                        paragraph.Query <TextElement>().Build().ForEach(tE => stringBuilder.Append(tE.text));
                        searchStrings.Add(stringBuilder.ToString());
                        paragraph.Clear();
                    });
                    //Get all the text from the Text elements under searchRootTemp
                    searchRootTemp.Query <TextElement>().ForEach(element => searchStrings.Add(element.text));
                }

                foreach (string searchStringLocal in searchStrings)
                {
                    string searchStringLocalLower = searchStringLocal.ToLower();
                    if (searchStringLocalLower.Contains(searchStringLower))
                    {
                        if (!searchResults.TryGetValue(page, out var resultStrings))
                        {
                            searchResults.Add(page, resultStrings = new List <string>());
                        }
                        resultStrings.Add(searchStringLocal);
                    }
                }
            }

            List <string> matches = new List <string>(maxMatchCount);

            foreach (var result in searchResults)
            {
                //Result Container
                VisualElement resultContainer = new VisualElement();
                resultContainer.ClearClassList();
                resultContainer.AddToClassList("result-container");
                resultContainer.userData = result.Key;
                searchRoot.Add(resultContainer);

                //Result Button
                Button searchResultButton = window.AddFullWidthButton(result.Key.GetType(), resultContainer);
                searchResultButton.AddToClassList("result");
                Label resultLabel = RichTextUtility.AddInlineText(searchResultButton.text, searchResultButton);
                resultLabel.style.color = searchResultButton.style.color;
                searchResultButton.text = null;
                Label resultCountLabel = RichTextUtility.AddInlineText($" ({result.Value.Count} Results)", searchResultButton);
                resultCountLabel.style.color = new Color(1, 1, 1, 0.35f);
                searchResultButton.RegisterCallback <MouseUpEvent>(evt => searchRoot.visible = false);

                //Results (the string matches)
                VisualElement resultMatchesContainer = new VisualElement();
                resultMatchesContainer.ClearClassList();
                resultMatchesContainer.AddToClassList("result-matches-container");
                resultContainer.Add(resultMatchesContainer);

                //Create a hashset of all the matched words.
                matches.Clear();
                foreach (string m in result.Value)
                {
                    string match = Regex.Match(m, $@"\w*{searchStringLower}\w*", RegexOptions.IgnoreCase).Value;
                    if (matches.Contains(match))
                    {
                        continue;
                    }
                    matches.Add(match);
                    if (matches.Count > maxMatchCount)
                    {
                        break;
                    }
                }

                //Add a max of maxMatchCount inline text to the resultMatchesContainer
                int l = Mathf.Min(maxMatchCount, matches.Count);
                for (int i = 0; i < l; i++)
                {
                    //Create group for matched coloured text.
                    VisualElement inlineTextGroup = new VisualElement();
                    inlineTextGroup.ClearClassList();
                    inlineTextGroup.AddToClassList("inline-text-group");
                    inlineTextGroup.AddToClassList("result");
                    resultMatchesContainer.Add(inlineTextGroup);

                    int indexOf = matches[i].IndexOf(searchStringLower, StringComparison.OrdinalIgnoreCase);

                    Label matchContent;
                    if (matches[i].Length == searchStringLower.Length)
                    {
                        matchContent = RichTextUtility.AddInlineText(matches[i], inlineTextGroup);
                    }
                    else if (indexOf == 0)
                    {
                        matchContent = RichTextUtility.AddInlineText(matches[i].Substring(indexOf, searchStringLower.Length), inlineTextGroup);
                        RichTextUtility.AddInlineText(matches[i].Substring(searchStringLower.Length), inlineTextGroup);
                    }
                    else if (indexOf == matches[i].Length - searchStringLower.Length)
                    {
                        RichTextUtility.AddInlineText(matches[i].Substring(0, indexOf), inlineTextGroup);
                        matchContent = RichTextUtility.AddInlineText(matches[i].Substring(indexOf), inlineTextGroup);
                    }
                    else
                    {
                        RichTextUtility.AddInlineText(matches[i].Substring(0, indexOf), inlineTextGroup);
                        matchContent = RichTextUtility.AddInlineText(matches[i].Substring(indexOf, searchStringLower.Length), inlineTextGroup);
                        RichTextUtility.AddInlineText(matches[i].Substring(indexOf + searchStringLower.Length), inlineTextGroup);
                    }

                    matchContent.style.color = new Color(1, 0.5f, 0);
                }

                if (l != matches.Count)
                {
                    RichTextUtility.AddInlineText("...", resultMatchesContainer);
                }
            }

            searchRoot.Sort((a, b) => searchResults[(IDocumentationPage <T>)b.userData].Count.CompareTo(searchResults[(IDocumentationPage <T>)a.userData].Count));

            //Reset page
            currentPageStateName = currentPageStateNameCached;
        }