Ejemplo n.º 1
0
        /// <summary>
        /// Transforms HTML tags to word element labels with different styles to enable rich text.
        /// </summary>
        /// <param name="htmlText"></param>
        /// <param name="targetContainer">
        /// The following need to set for the container's style:
        /// flex-direction: row;
        /// flex-wrap: wrap;
        /// </param>
        public static void RichTextToVisualElements(string htmlText, VisualElement targetContainer)
        {
            bool   addError  = false;
            string errorText = "";

            try
            {
                XDocument.Parse("<content>" + htmlText + "</content>");
            }
            catch (Exception e)
            {
                targetContainer.Clear();
                errorText = e.Message;
                htmlText  = ShowContentWithError(htmlText);
                addError  = true;
            }

            // TODO should translation be a responsibility of the caller of this function instead?
            htmlText = Localization.Tr(htmlText);

            targetContainer.Clear();
            bool   boldOn          = false; // <b> sets this on </b> sets off
            bool   italicOn        = false; // <i> </i>
            bool   linkOn          = false;
            string linkURL         = "";
            bool   firstLine       = true;
            bool   lastLineHadText = false;

            // start streaming text per word to elements while retaining current style for each word block
            string[] lines = htmlText.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);

            foreach (string line in lines)
            {
                string[] words = line.Split(new[] { " " }, StringSplitOptions.None);

                if (!firstLine && !lastLineHadText)
                {
                    AddParagraphToElement(targetContainer);
                }
                if (!firstLine && lastLineHadText)
                {
                    AddLinebreakToElement(targetContainer);
                    //AddParagraphToElement(targetContainer);
                    lastLineHadText = false;
                }

                foreach (string word in words)
                {
                    if (word == "" || word == " " || word == "   ")
                    {
                        continue;
                    }
                    lastLineHadText = true;
                    string strippedWord = word;
                    bool   removeBold   = false;
                    bool   removeItalic = false;
                    bool   addParagraph = false;
                    bool   removeLink   = false;

                    if (strippedWord.Contains("<b>"))
                    {
                        strippedWord = strippedWord.Replace("<b>", "");
                        boldOn       = true;
                    }
                    if (strippedWord.Contains("<i>"))
                    {
                        strippedWord = strippedWord.Replace("<i>", "");
                        italicOn     = true;
                    }
                    if (strippedWord.Contains("<a"))
                    {
                        strippedWord = strippedWord.Replace("<a", "");
                        linkOn       = true;
                    }
                    if (linkOn && strippedWord.Contains("href="))
                    {
                        strippedWord = strippedWord.Replace("href=", "");
                        int linkFrom = strippedWord.IndexOf("\"", StringComparison.Ordinal) + 1;
                        int linkTo   = strippedWord.LastIndexOf("\"", StringComparison.Ordinal);
                        linkURL      = strippedWord.Substring(linkFrom, linkTo - linkFrom);
                        strippedWord = strippedWord.Substring(linkTo + 2, (strippedWord.Length - 2) - linkTo);
                        strippedWord.Replace("\">", "");
                    }
                    if (strippedWord.Contains("</a>"))
                    {
                        strippedWord = strippedWord.Replace("</a>", "");
                        // TODO </a>text -> also text part is still blue. Parse - for now we can take care when authoring.
                        removeLink = true;
                    }
                    if (strippedWord.Contains("<br/>"))
                    {
                        strippedWord = strippedWord.Replace("<br/>", "");
                        addParagraph = true;
                    }
                    if (strippedWord.Contains("</b>"))
                    {
                        strippedWord = strippedWord.Replace("</b>", "");
                        removeBold   = true;
                    }
                    if (strippedWord.Contains("</i>"))
                    {
                        strippedWord = strippedWord.Replace("</i>", "");
                        removeItalic = true;
                    }
                    if (boldOn)
                    {
                        Label wordLabel = new Label(strippedWord);
                        wordLabel.style.unityFontStyleAndWeight = new StyleEnum <FontStyle>(FontStyle.Bold);
                        targetContainer.Add(wordLabel);
                    }
                    else if (italicOn)
                    {
                        Label wordLabel = new Label(strippedWord);
                        wordLabel.style.unityFontStyleAndWeight = new StyleEnum <FontStyle>(FontStyle.Italic);
                        targetContainer.Add(wordLabel);
                    }
                    else if (addParagraph)
                    {
                        AddParagraphToElement(targetContainer);
                    }
                    else if (linkOn && !string.IsNullOrEmpty(linkURL))
                    {
                        var label = new HyperlinkLabel
                        {
                            text    = strippedWord,
                            tooltip = linkURL
                        };
                        label.RegisterCallback <MouseUpEvent, string>(
                            (evt, linkurl) =>
                        {
                            // Supporting only hyperlinks to Unity's websites.
                            // The user needs be be logged in in order the hyperlink to work.
                            UnityConnectProxy.OpenAuthorizedURLInWebBrowser(linkurl);
                        },
                            linkURL
                            );

                        targetContainer.Add(label);
                    }
                    else
                    {
                        Label newlabel = new Label(strippedWord);
                        targetContainer.Add(newlabel);
                    }
                    if (removeBold)
                    {
                        boldOn = false;
                    }
                    if (removeItalic)
                    {
                        italicOn = false;
                    }
                    if (removeLink)
                    {
                        linkOn  = false;
                        linkURL = "";
                    }
                }
                firstLine = false;
            }

            if (addError)
            {
                var label = new ParseErrorLabel()
                {
                    text    = Localization.Tr("PARSE ERROR"),
                    tooltip = Localization.Tr("Click here to see more information in the console.")
                };
                label.RegisterCallback <MouseUpEvent>((e) => Debug.LogError(errorText));
                targetContainer.Add(label);
            }
        }
        /// <summary>
        /// Transforms HTML tags to word element labels with different styles to enable rich text.
        /// </summary>
        /// <param name="htmlText"></param>
        /// <param name="targetContainer">
        /// The following need to set for the container's style:
        /// flex-direction: row;
        /// flex-wrap: wrap;
        /// </param>
        /// <returns>List of VisualElements made from the parsed text.</returns>
        public static List <VisualElement> RichTextToVisualElements(string htmlText, VisualElement targetContainer)
        {
            bool   addError  = false;
            string errorText = "";

            try
            {
                XDocument.Parse("<content>" + htmlText + "</content>");
            }
            catch (Exception e)
            {
                targetContainer.Clear();
                errorText = e.Message;
                htmlText  = ShowContentWithError(htmlText);
                addError  = true;
            }
            List <VisualElement> elements = new List <VisualElement>();

            targetContainer.Clear();
            bool   boldOn          = false; // <b> sets this on </b> sets off
            bool   italicOn        = false; // <i> </i>
            bool   forceWordWrap   = false;
            bool   linkOn          = false;
            string linkURL         = "";
            bool   firstLine       = true;
            bool   lastLineHadText = false;

            // start streaming text per word to elements while retaining current style for each word block
            string[] lines = htmlText.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);

            foreach (string line in lines)
            {
                // Check if the line begins with whitespace and turn that into corresponding Label
                string initialWhiteSpaces = "";
                foreach (char singleCharacter in line)
                {
                    if (singleCharacter == ' ' || singleCharacter == '\t')
                    {
                        initialWhiteSpaces += singleCharacter;
                    }
                    else
                    {
                        break;
                    }
                }

                string processedLine = PreProcessRichText(line);

                // Separate the line into words
                string[] words = processedLine.Split(new[] { " ", "\t" }, StringSplitOptions.RemoveEmptyEntries);

                if (!lastLineHadText)
                {
                    if (!firstLine)
                    {
                        elements.Add(AddParagraphToElement(targetContainer));
                    }

                    if (initialWhiteSpaces.Length > 0)
                    {
                        WhiteSpaceLabel indentationLabel = new WhiteSpaceLabel(initialWhiteSpaces);
                        targetContainer.Add(indentationLabel);
                        elements.Add(indentationLabel);
                    }
                }

                if (!firstLine && lastLineHadText)
                {
                    elements.Add(AddLinebreakToElement(targetContainer));
                    lastLineHadText = false;
                    if (initialWhiteSpaces.Length > 0)
                    {
                        WhiteSpaceLabel indentationLabel = new WhiteSpaceLabel(initialWhiteSpaces);
                        targetContainer.Add(indentationLabel);
                        elements.Add(indentationLabel);
                    }
                }

                foreach (string word in words)
                {
                    // Wrap every character instead of word in case of Chinese and Japanese
                    // Note: override with <wordwrap>Force word wrapping here</wordwrap>

                    if (word == "" || word == " " || word == "   ")
                    {
                        continue;
                    }
                    lastLineHadText = true;
                    string strippedWord   = word;
                    bool   removeBold     = false;
                    bool   removeItalic   = false;
                    bool   addParagraph   = false;
                    bool   removeLink     = false;
                    bool   removeWordWrap = false;

                    strippedWord = strippedWord.Trim();

                    if (strippedWord.Contains("<b>"))
                    {
                        strippedWord = strippedWord.Replace("<b>", "");
                        boldOn       = true;
                    }
                    if (strippedWord.Contains("<i>"))
                    {
                        strippedWord = strippedWord.Replace("<i>", "");
                        italicOn     = true;
                    }
                    if (strippedWord.Contains("<wordwrap>"))
                    {
                        strippedWord  = strippedWord.Replace("<wordwrap>", "");
                        forceWordWrap = true;
                    }
                    if (strippedWord.Contains("<a"))
                    {
                        strippedWord = strippedWord.Replace("<a", "");
                        linkOn       = true;
                    }
                    bool wrapCharacters = !forceWordWrap && NeedSymbolWrapping(word);
                    if (linkOn && strippedWord.Contains("href="))
                    {
                        strippedWord = strippedWord.Replace("href=", "");
                        int linkFrom = strippedWord.IndexOf("\"", StringComparison.Ordinal) + 1;
                        int linkTo   = strippedWord.LastIndexOf("\"", StringComparison.Ordinal);
                        linkURL      = strippedWord.Substring(linkFrom, linkTo - linkFrom);
                        strippedWord = strippedWord.Substring(linkTo + 2, (strippedWord.Length - 2) - linkTo);
                        strippedWord.Replace("\">", "");
                    }

                    if (strippedWord.Contains("</a>"))
                    {
                        strippedWord = strippedWord.Replace("</a>", "");
                        removeLink   = true;
                    }
                    if (strippedWord.Contains("<br/>"))
                    {
                        strippedWord = strippedWord.Replace("<br/>", "");
                        addParagraph = true;
                    }
                    if (strippedWord.Contains("</b>"))
                    {
                        strippedWord = strippedWord.Replace("</b>", "");
                        removeBold   = true;
                    }
                    if (strippedWord.Contains("</i>"))
                    {
                        strippedWord = strippedWord.Replace("</i>", "");
                        removeItalic = true;
                    }
                    if (strippedWord.Contains("</wordwrap>"))
                    {
                        strippedWord   = strippedWord.Replace("</wordwrap>", "");
                        removeWordWrap = true;
                    }
                    if (boldOn && strippedWord != "")
                    {
                        if (wrapCharacters)
                        {
                            foreach (char character in strippedWord)
                            {
                                AddLabel <BoldLabel>(character.ToString(), elements, targetContainer);
                            }
                        }
                        else
                        {
                            AddLabel <BoldLabel>(strippedWord, elements, targetContainer);
                        }
                    }
                    else if (italicOn && strippedWord != "")
                    {
                        if (wrapCharacters)
                        {
                            foreach (char character in strippedWord)
                            {
                                AddLabel <ItalicLabel>(character.ToString(), elements, targetContainer);
                            }
                        }
                        else
                        {
                            AddLabel <ItalicLabel>(strippedWord, elements, targetContainer);
                        }
                    }
                    else if (addParagraph)
                    {
                        elements.Add(AddParagraphToElement(targetContainer));
                    }
                    else if (linkOn && !string.IsNullOrEmpty(linkURL))
                    {
                        var label = new HyperlinkLabel
                        {
                            text    = strippedWord,
                            tooltip = linkURL
                        };
                        label.RegisterCallback <MouseUpEvent, string>(
                            (evt, linkurl) =>
                        {
                            TutorialEditorUtils.OpenUrl(linkurl);
                        },
                            linkURL
                            );

                        targetContainer.Add(label);
                        elements.Add(label);
                    }
                    else
                    {
                        if (strippedWord != "")
                        {
                            if (wrapCharacters)
                            {
                                foreach (char character in strippedWord)
                                {
                                    AddLabel <TextLabel>(character.ToString(), elements, targetContainer);
                                }
                            }
                            else
                            {
                                AddLabel <TextLabel>(strippedWord, elements, targetContainer);
                            }
                        }
                    }

                    if (removeBold)
                    {
                        boldOn = false;
                    }
                    if (removeItalic)
                    {
                        italicOn = false;
                    }
                    if (removeLink)
                    {
                        linkOn  = false;
                        linkURL = "";
                    }
                    if (removeWordWrap)
                    {
                        forceWordWrap = false;
                    }
                }
                firstLine = false;
            }

            if (addError)
            {
                var label = new ParseErrorLabel()
                {
                    text    = Localization.Tr("PARSE ERROR"),
                    tooltip = Localization.Tr("Click here to see more information in the console.")
                };
                label.RegisterCallback <MouseUpEvent>((e) => Debug.LogError(errorText));
                targetContainer.Add(label);
                elements.Add(label);
            }
            return(elements);
        }