public RichTextNode ToRichTextNode(FengDocument doc)
        {
            var output = new RichTextNode()
            {
                VerticalContainer = new RichTextNode.Types.VerticalContainerNode()
                {
                    Children =
                    {
                        SectionHeader(zc.tH(doc.HanziOriginal),
                                      RenderSourcePronunciations(
                                          ToFeng(doc.YngpingUnderlyingOriginal),
                                          ToFeng(doc.YngpingCanonicalOriginal))),
                    }
                }
            };

            if (doc.ExplanationStructured != null)
            {
                output.VerticalContainer.Children.Add(explanationRenderer.ToRichTextNode(doc.ExplanationStructured, doc.HanziCanonical));
            }
            else
            {
                output.VerticalContainer.Children.Add(SimpleText(zc.tH(doc.Explanation)));
            }
            output.VerticalContainer.Children.Add(Source(zc.tM($"出处:冯爱珍. 1998. 福州方言词典. 南京: 江苏教育出版社. 第 {doc.Source.PageNumber} 页. 用字可能经过编辑修订.")));
            return(output);
        }
Beispiel #2
0
        public RichTextNode ToRichTextNode(ContribDocument doc)
        {
            var output = new RichTextNode()
            {
                VerticalContainer = new RichTextNode.Types.VerticalContainerNode()
                {
                    Children =
                    {
                        SectionHeader(doc.Hanzi, RenderSourcePronunciations(doc.YngpingUnderlying, doc.YngpingSandhi)),
                    }
                }
            };

            if (doc.ExplanationStructured != null)
            {
                output.VerticalContainer.Children.Add(explanationRenderer.ToRichTextNode(doc.ExplanationStructured, doc.Hanzi));
            }
            else
            {
                output.VerticalContainer.Children.Add(SimpleText(zc.tH(doc.ExplanationRaw)));
            }
            output.VerticalContainer.Children.Add(
                Source(zc.tM("此释义来自网友贡献。 贡献者: " + string.Join(",", doc.Contributors)))
                );
            return(output);
        }
Beispiel #3
0
    GameObject AddTexture(RichTextNode node)
    {
        if (node.Texture == null)
        {
            throw new ArgumentException("node");
        }

        var assert = Resources.Load(node.Texture);
        var go     = GameObject.Instantiate(assert) as GameObject;

        go.name = NodeName;
        HideGameObject(go);

        var sprite = go.GetComponent <UISprite>();

        sprite.depth = mLabel.depth;

        if (mPostion.x + sprite.width > this.mLayoutWidth)
        {
            Newline();
        }

        go.transform.SetParent(this.transform, false);
        go.transform.localPosition = new Vector3(mPostion.x + sprite.width / 2, mPostion.y - sprite.height / 2, 0);

        mPostion.x   += sprite.width;
        mCurLineHight = Mathf.Max(mCurLineHight, sprite.height);

        return(go);
    }
 public RichTextParser(string text)
 {
     m_Text       = text;
     m_TextLength = text.Length;
     m_Index      = 0;
     m_RootNode   = new RichTextNode();
     Parse();
 }
        TagNode ParseStartTag(RichTextNode parent)
        {
            TagNode node = null;

            string tag = null;

            while (m_Index < m_TextLength)
            {
                if (m_Text[m_Index] == '>')
                {
                    // Attribute無し
                    m_Index++;
                    if (tag.ToLower() == TagTypes.B.ToString().ToLower())
                    {
                        node = new BoldTagNode(parent);
                    }
                    else if (tag.ToLower() == TagTypes.I.ToString().ToLower())
                    {
                        node = new ItalicTagNode(parent);
                    }
                    return(node);
                }
                else if (m_Text[m_Index] == '=')
                {
                    // Attributeあり
                    m_Index++;
                    var attribute = ParseTagAttribute();
                    if (tag.ToLower() == TagTypes.Color.ToString().ToLower())
                    {
                        node = new ColorTagNode(parent, attribute);
                    }
                    else if (tag.ToLower() == TagTypes.Size.ToString().ToLower())
                    {
                        var size = 0;
                        if (int.TryParse(attribute, out size))
                        {
                            node = new SizeTagNode(parent, size);
                        }
                        else
                        {
                            throw new RichTextException("size attribute exception: size=" + attribute);
                        }
                    }
                    return(node);
                }
                tag += m_Text[m_Index++];
            }

            // 最後までパースした
            throw new RichTextException();
        }
Beispiel #6
0
        public RichTextNode ToRichTextNode(Explanation.Types.Sense sense, string currentWord = "~")
        {
            var output = new RichTextNode()
            {
                VerticalContainer = new RichTextNode.Types.VerticalContainerNode()
                {
                },
                Styles = { "sense" }
            };

            if (!string.IsNullOrWhiteSpace(sense.Text))
            {
                output.VerticalContainer.Children.Add(SimpleTextWithOuterStyles(
                                                          zc.tM(MaybeAddPeriod(sense.Text)),
                                                          new string[] { "sense" }));
            }
            if (sense.Examples.Count() > 0)
            {
                output.VerticalContainer.Children.Add(
                    new RichTextNode()
                {
                    List = new RichTextNode.Types.ListNode()
                    {
                        Children = { sense.Examples.Select(ex =>
                                                           ToRichTextNode(ex, currentWord)
                                                           ) }
                    },
                    Styles = { "examples-list" }
                }
                    );
            }
            if (sense.ChildSenses.Count() > 0)
            {
                output.VerticalContainer.Children.Add(
                    new RichTextNode()
                {
                    List = new RichTextNode.Types.ListNode()
                    {
                        Ordered  = true,
                        Children = { sense.ChildSenses.Select(c =>
                                                              ToRichTextNode(c, currentWord)
                                                              ) }
                    }
                }
                    );
            }
            return(output);
        }
        void ParseText(RichTextNode parent)
        {
            var node = new PureTextNode(parent);

            parent.ChildNodes.Add(node);

            string text = "";

            while (m_Index < m_TextLength)
            {
                if (m_Text[m_Index] == '<')
                {
                    node.Text = text;
                    break;
                }
                text += m_Text[m_Index++];
            }
        }
Beispiel #8
0
    void AddText(List <RichTextNode> nodes, string text, string color, string link)
    {
        if (nodes.Count > 0)
        {
            var node = nodes[nodes.Count - 1];
            if (node.Color == color && node.Link == link)
            {
                node.Text += text;
                return;
            }
        }

        var newNode = new RichTextNode();

        newNode.Text  = text;
        newNode.Color = color;
        newNode.Link  = link;
        nodes.Add(newNode);
    }
 TagNode ParseTag(RichTextNode parent)
 {
     m_Index++;
     if (m_Text[m_Index] == '/')
     {
         // 終了タグ
         m_Index++;
         ParseEndTag((TagNode)parent);
         return(null);
     }
     else
     {
         // 開始タグ
         var node = ParseStartTag(parent);
         if (node != null)
         {
             parent.ChildNodes.Add(node);
         }
         return(node);
     }
 }
Beispiel #10
0
    GameObject AddText(RichTextNode node, int start, int count)
    {
        var text  = node.Text.Substring(start, count);
        var color = node.Color;

        var go = GameObject.Instantiate(mLabel.gameObject) as GameObject;

        go.name = NodeName;
        go.SetActive(true);
        HideGameObject(go);

        var label = go.GetComponent <UILabel>();

        label.width  = 0;
        label.height = 0;
        label.color  = new Color(
            int.Parse(color.Substring(2, 2), System.Globalization.NumberStyles.HexNumber) / 255f,
            int.Parse(color.Substring(4, 2), System.Globalization.NumberStyles.HexNumber) / 255f,
            int.Parse(color.Substring(6, 2), System.Globalization.NumberStyles.HexNumber) / 255f,
            int.Parse(color.Substring(0, 2), System.Globalization.NumberStyles.HexNumber) / 255f);

        label.text = text;

        var size = label.printedSize;

        label.transform.SetParent(this.transform, false);
        label.transform.localPosition = new Vector3(mPostion.x + size.x / 2, mPostion.y - size.y / 2, 0);

        if (node.Link != null)
        {
            var box = go.AddComponent <BoxCollider>();
            box.size = new Vector3(size.x, size.y);

            UIEventListener.Get(go).onClick = node.OnClick;
        }

        mPostion.x   += size.x;
        mCurLineHight = Mathf.Max(mCurLineHight, size.y);
        return(go);
    }
Beispiel #11
0
        public RichTextNode ToRichTextNode(Explanation e, string currentWord = "~")
        {
            var output = new RichTextNode()
            {
                VerticalContainer = new RichTextNode.Types.VerticalContainerNode()
                {
                    Children =
                    {
                        Label(zc.tM("释义")),
                        new RichTextNode {
                            List = new RichTextNode.Types.ListNode {
                                Ordered  = true,
                                Children = { e.Senses.Select(s =>
                                                             ToRichTextNode(s, currentWord)
                                                             ) }
                            }
                        }
                    }
                }
            };

            if (!string.IsNullOrEmpty(e.NotesOriginal))
            {
                output.VerticalContainer.Children.Add(Label(zc.tM("注")));
                output.VerticalContainer.Children.Add(
                    SimpleTextWithOuterStyles(zc.tM(MaybeAddPeriod(e.NotesOriginal)),
                                              new string[] { "notes" }));
            }
            if (!string.IsNullOrEmpty(e.NotesOurs))
            {
                output.VerticalContainer.Children.Add(Label(zc.tM("榕典注")));
                output.VerticalContainer.Children.Add(
                    SimpleTextWithOuterStyles(zc.tM(MaybeAddPeriod(e.NotesOurs)),
                                              new string[] { "notes" }));
            }
            return(output);
        }
 public ItalicTagNode(RichTextNode parent) : base(parent)
 {
     TagType = TagTypes.I;
 }
 public PureTextNode(RichTextNode parent) : base(parent)
 {
     NodeType = NodeTypes.Text;
 }
 public BoldTagNode(RichTextNode parent) : base(parent)
 {
     TagType = TagTypes.B;
 }
Beispiel #15
0
    GameObject AddText(RichTextNode node, int start, int count)
    {
        var text = node.Text.Substring(start, count);
        var color = node.Color;

        var go = GameObject.Instantiate(mLabel.gameObject) as GameObject;
        go.name = NodeName;
        go.SetActive (true);
        HideGameObject(go);

        var label = go.GetComponent<UILabel>();
        label.width = 0;
        label.height = 0;
        label.color = new Color(
            int.Parse(color.Substring(2, 2), System.Globalization.NumberStyles.HexNumber) / 255f,
            int.Parse(color.Substring(4, 2), System.Globalization.NumberStyles.HexNumber) / 255f,
            int.Parse(color.Substring(6, 2), System.Globalization.NumberStyles.HexNumber) / 255f,
            int.Parse(color.Substring(0, 2), System.Globalization.NumberStyles.HexNumber) / 255f);

        label.text = text;

        var size = label.printedSize;
        label.transform.SetParent(this.transform, false);
        label.transform.localPosition = new Vector3(mPostion.x + size.x / 2, mPostion.y - size.y / 2, 0);

        if (node.Link != null)
        {
            var box = go.AddComponent<BoxCollider>();
            box.size = new Vector3(size.x, size.y);

            UIEventListener.Get(go).onClick = node.OnClick;
        }

        mPostion.x += size.x;
        mCurLineHight = Mathf.Max(mCurLineHight, size.y);
        return go;
    }
Beispiel #16
0
    List <RichTextNode> ParseText(string text)
    {
        var    nodes         = new List <RichTextNode>();
        string originalColor = "FFFFFFFF";
        string currentColor  = originalColor;
        string currentLink   = null;

        var start = 0;

        while (true)
        {
            var index = text.IndexOf("|", start);
            if (index == -1)
            {
                index = text.Length;
            }

            if (index > start)
            {
                AddText(nodes, text.Substring(start, index - start), currentColor, currentLink);
            }

            if (index == text.Length)
            {
                break;
            }

            index++;
            var cur = text[index];
            switch (cur)
            {
            case 'n':
                AddText(nodes, "\n", currentColor, currentLink);
                start = index + 1;
                break;

            case 'c':
                index++;
                currentColor = text.Substring(index, 8);
                start        = index + 8;
                break;

            case 'r':
                currentColor = originalColor;
                start        = index + 1;
                break;

            case 'T':
            {
                index++;
                var nextIndex = text.IndexOf("|t", index);
                if (nextIndex == -1)
                {
                    start = index;
                    AddText(nodes, "|T", currentColor, currentLink);
                }
                else
                {
                    var node = new RichTextNode();
                    node.Texture = text.Substring(index, nextIndex - index);
                    if (null != Resources.Load(node.Texture))
                    {
                        nodes.Add(node);
                    }
                    else
                    {
                        AddText(nodes, "|T" + node.Texture + "|t", currentColor, currentLink);
                    }
                    start = nextIndex + 2;
                }
                break;
            }

            case 'H':
            {
                index++;
                var nextIndex = text.IndexOf("|h", index);
                if (nextIndex == -1)
                {
                    start = index;
                    AddText(nodes, "|H", currentColor, currentLink);
                }
                else
                {
                    currentLink = text.Substring(index, nextIndex - index);
                    start       = nextIndex + 2;
                }
                break;
            }

            case 'h':
                if (currentLink == null)
                {
                    start = index + 1;
                    AddText(nodes, "|h", currentColor, currentLink);
                }
                else
                {
                    currentLink = null;
                    start       = index + 1;
                }
                break;

            default:
                AddText(nodes, "|" + cur.ToString(), currentColor, currentLink);
                start = index + 1;
                break;
            }
        }
        return(nodes);
    }
Beispiel #17
0
        /// <summary>
        /// initializes the Diagram data
        /// </summary>
        private void InitializeDiagram()
        {
            Syncfusion.Windows.Forms.Diagram.Rectangle rect = new Syncfusion.Windows.Forms.Diagram.Rectangle(100, 25, 120, 75);
            rect.FillStyle.Color     = Color.FromArgb(240, 242, 240);
            rect.FillStyle.ForeColor = Color.White;
            rect.FillStyle.Type      = FillStyleType.LinearGradient;
            rect.LineStyle.LineColor = Color.DarkGray;
            AddLabel(rect, "Rectangle", Position.Center);
            diagram1.Model.AppendChild(rect);

            Syncfusion.Windows.Forms.Diagram.RoundRect roundRect = new Syncfusion.Windows.Forms.Diagram.RoundRect(400, 25, 120, 75, MeasureUnits.Pixel);
            roundRect.FillStyle.Color     = Color.FromArgb(240, 242, 240);
            roundRect.FillStyle.ForeColor = Color.White;
            roundRect.LineStyle.LineColor = Color.DarkGray;
            roundRect.FillStyle.Type      = FillStyleType.LinearGradient;
            AddLabel(roundRect, "RoundRect1", Position.Center);
            diagram1.Model.AppendChild(roundRect);

            Ellipse ellipse1 = new Ellipse(100, 125, 120, 80);

            ellipse1.FillStyle.Color     = Color.FromArgb(240, 242, 240);
            ellipse1.FillStyle.ForeColor = Color.White;
            ellipse1.LineStyle.LineColor = Color.DarkGray;
            ellipse1.FillStyle.Type      = FillStyleType.LinearGradient;
            AddLabel(ellipse1, "Ellipse", Position.Center);
            diagram1.Model.AppendChild(ellipse1);

            Polygon poly = new Polygon(new PointF[] { new PointF(160, 235), new PointF(100, 265), new PointF(120, 325), new PointF(200, 325), new PointF(220, 265) });

            poly.FillStyle.Color     = Color.FromArgb(240, 242, 240);
            poly.FillStyle.ForeColor = Color.White;
            poly.FillStyle.Type      = FillStyleType.LinearGradient;
            poly.LineStyle.LineColor = Color.DarkGray;
            AddLabel(poly, "Polygon", Position.Center);
            diagram1.Model.AppendChild(poly);

            SemiCircle semiCircle = new SemiCircle(400, 125, 120, 75);

            semiCircle.FillStyle.Color     = Color.FromArgb(240, 242, 240);
            semiCircle.FillStyle.ForeColor = Color.White;
            semiCircle.FillStyle.Type      = FillStyleType.LinearGradient;
            semiCircle.LineStyle.LineColor = Color.DarkGray;
            AddLabel(semiCircle, "SemiCircle", Position.Center);
            diagram1.Model.AppendChild(semiCircle);

            TextNode textNode = new TextNode("TextNode1", new RectangleF(400, 245, 120, 50));

            textNode.FontStyle.Size       = 9;
            textNode.FontStyle.Family     = "Segoe UI";
            textNode.HorizontalAlignment  = StringAlignment.Center;
            textNode.VerticalAlignment    = StringAlignment.Center;
            textNode.LineStyle.LineColor  = Color.DarkGray;
            textNode.FontColorStyle.Color = Color.Black;
            diagram1.Model.AppendChild(textNode);

            RichTextNode richTextNode = new RichTextNode(@"{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil\fcharset0 Meiryo UI;}{\f1\fnil\fcharset0 Microsoft Sans Serif;}}
{\colortbl ;\red255\green0\blue0;\red0\green64\blue128;}
\viewkind4\uc1\pard\b\f0\fs17 This is a text symbol\f1  \b0\f0 designed using the \cf1\b\i Essential Diagram\i0  \cf2\ul RichText\ulnone  node\cf0\b0 .\par
\i\f1\fs20\par
}", new RectangleF(400, 320, 120, 100));

            richTextNode.LineStyle.LineColor = Color.DarkGray;
            diagram1.Model.AppendChild(richTextNode);

#if !NETCORE
            BitmapNode bmpNode = new BitmapNode(@"..\..\..\..\..\..\common\Images\Diagram\OrgChart Layout\image3.png");
#else
            BitmapNode bmpNode = new BitmapNode(@"..\..\..\..\..\..\..\common\Images\Diagram\OrgChart Layout\image3.png");
#endif
            bmpNode.Name                = "BitmapNode1";
            bmpNode.PinPoint            = new PointF(700, 75);
            bmpNode.Size                = new SizeF(120, 100);
            bmpNode.LineStyle.LineWidth = 0;
            diagram1.Model.AppendChild(bmpNode);

            ClosedCurveNode curve = new ClosedCurveNode(new PointF[] { new PointF(120, 350), new PointF(120, 450), new PointF(220, 400) });
            curve.FillStyle.Color     = Color.FromArgb(240, 242, 240);
            curve.FillStyle.ForeColor = Color.White;
            curve.FillStyle.Type      = FillStyleType.LinearGradient;
            curve.LineStyle.LineColor = Color.DarkGray;
            AddLabel(curve, "ClosedCurve", Position.Center);
            diagram1.Model.AppendChild(curve);

            CurveNode curve1 = new CurveNode(new PointF[] { new PointF(120, 100), new PointF(120, 200), new PointF(220, 150) });
            curve1 = new CurveNode(new PointF[] { new PointF(0, 30), new PointF(4.99999952f, 25), new PointF(18.3333321f, 0), new PointF(30, 0), new PointF(41.66666641f, 0), new PointF(58.33333321f, 30), new PointF(70, 30), new PointF(81.66666f, 30), new PointF(95, 4.99999952f), new PointF(100, 0) });
            AddLabel(curve1, "CurveNode", Position.Center);
            diagram1.Model.AppendChild(curve1);

            CircularArc circular = new CircularArc(new RectangleF(640, 150, 100, 100), 0, 270);
            circular.FillStyle.Color     = Color.FromArgb(240, 242, 240);
            circular.FillStyle.ForeColor = Color.White;
            circular.FillStyle.Type      = FillStyleType.LinearGradient;
            circular.LineStyle.LineColor = Color.DarkGray;
            circular.PinPoint            = new PointF(700, 200);
            AddLabel(circular, "CircularArc", Position.Center);
            diagram1.Model.AppendChild(circular);

            Line line1 = new Line(new PointF(700, 320), new PointF(700, 430));
            line1.LineStyle.LineColor = Color.DarkGray;
            AddLabel(line1, "line", Position.TopCenter);
            diagram1.Model.AppendChild(line1);

            PolylineNode polyLine = new PolylineNode(new PointF[] { new PointF(640, 500), new PointF(760, 500), new PointF(640, 540), new PointF(760, 540) });
            polyLine.LineStyle.LineColor = Color.DarkGray;
            polyLine.LineStyle.LineWidth = 1;
            Syncfusion.Windows.Forms.Diagram.Label label = new Syncfusion.Windows.Forms.Diagram.Label(polyLine, "PolyLine Node");
            label.OffsetX              = polyLine.BoundingRectangle.Width / 5f;
            label.OffsetY              = polyLine.BoundingRectangle.Height + 10;
            label.FontStyle.Family     = "Segoe UI";
            label.FontColorStyle.Color = Color.Black;
            label.FontStyle.Size       = 9;
            polyLine.Labels.Add(label);
            diagram1.Model.AppendChild(polyLine);

            BezierCurve bezier = new BezierCurve(new PointF[] { new PointF(100, 470), new PointF(160, 470), new PointF(160, 560), new PointF(220, 560) });
            AddLabel(bezier, "BezierCurve", Position.BottomCenter);
            diagram1.Model.AppendChild(bezier);

            SplineNode spline = new SplineNode(new PointF[] { new PointF(400, 460), new PointF(520, 500), new PointF(400, 520) });
            spline.LineStyle.LineColor = Color.Black;
            spline.LineStyle.LineWidth = 1;
            AddLabel(spline, "Spline", Position.BottomCenter);
            diagram1.Model.AppendChild(spline);
        }
Beispiel #18
0
    GameObject AddTexture(RichTextNode node)
    {
        if (node.Texture == null)
            throw new ArgumentException("node");

        var assert = Resources.Load(node.Texture);
        var go = GameObject.Instantiate(assert) as GameObject;
        go.name = NodeName;
        HideGameObject(go);

        var sprite = go.GetComponent<UISprite>();
        sprite.depth = mLabel.depth;

        if (mPostion.x + sprite.width > this.mLayoutWidth)
            Newline();

        go.transform.SetParent(this.transform, false);
        go.transform.localPosition = new Vector3(mPostion.x + sprite.width / 2, mPostion.y - sprite.height / 2, 0);

        mPostion.x += sprite.width;
        mCurLineHight = Mathf.Max(mCurLineHight, sprite.height);

        return go;
    }
Beispiel #19
0
 public TagNode(RichTextNode parent) : base(parent)
 {
     NodeType = NodeTypes.Tag;
 }
Beispiel #20
0
 public ColorTagNode(RichTextNode parent, string color) : base(parent)
 {
     TagType = TagTypes.Color;
     Color   = color;
 }
Beispiel #21
0
    void AddText(List<RichTextNode> nodes, string text, string color, string link)
    {
        if (nodes.Count > 0)
        {
            var node = nodes[nodes.Count - 1];
            if (node.Color == color && node.Link == link)
            {
                node.Text += text;
                return;
            }
        }

        var newNode = new RichTextNode();
        newNode.Text = text;
        newNode.Color = color;
        newNode.Link = link;
        nodes.Add(newNode);
    }
        public SizeTagNode(RichTextNode parent, int size) : base(parent)
        {
            TagType = TagTypes.Size;

            Size = size;
        }
Beispiel #23
0
    List<RichTextNode> ParseText(string text)
    {
        var nodes = new List<RichTextNode>();
        string originalColor = "FFFFFFFF";
        string currentColor = originalColor;
        string currentLink = null;

        var start = 0;
        while (true)
        {
            var index = text.IndexOf("|", start);
            if (index == -1)
                index = text.Length;

            if (index > start)
                AddText(nodes, text.Substring(start, index - start), currentColor, currentLink);

            if (index == text.Length)
                break;

            index++;
            var cur = text[index];
            switch (cur)
            {
                case '|':
                    AddText(nodes, "|", currentColor, currentLink);
                    start = index + 1;
                    break;

                case 'n':
                    AddText(nodes, "\n", currentColor, currentLink);
                    start = index + 1;
                    break;

                case 'c':
                    index++;
                    currentColor = text.Substring(index, 8);
                    start = index + 8;
                    break;

                case 'r':
                    currentColor = originalColor;
                    start = index + 1;
                    break;

                case 'T':
                {
                    index++;
                    var nextIndex = text.IndexOf("|t", index);

                    var node = new RichTextNode();
                    node.Texture = text.Substring(index, nextIndex - index);
                    nodes.Add(node);

                    start = nextIndex + 2;
                    break;
                }

                case 'H':
                {
                    index++;
                    var nextIndex = text.IndexOf("|h", index);
                    currentLink = text.Substring(index, nextIndex - index);
                    start = nextIndex + 2;
                    break;
                }

                case 'h':
                    if (currentLink == null)
                        throw new FormatException("currentLink == null");

                    currentLink = null;
                    start = index + 1;
                    break;
            }
        }
        return nodes;
    }
Beispiel #24
0
    List <RichTextNode> ParseText(string text)
    {
        var    nodes         = new List <RichTextNode>();
        string originalColor = "FFFFFFFF";
        string currentColor  = originalColor;
        string currentLink   = null;

        var start = 0;

        while (true)
        {
            var index = text.IndexOf("|", start);
            if (index == -1)
            {
                index = text.Length;
            }

            if (index > start)
            {
                AddText(nodes, text.Substring(start, index - start), currentColor, currentLink);
            }

            if (index == text.Length)
            {
                break;
            }

            index++;
            var cur = text[index];
            switch (cur)
            {
            case '|':
                AddText(nodes, "|", currentColor, currentLink);
                start = index + 1;
                break;

            case 'n':
                AddText(nodes, "\n", currentColor, currentLink);
                start = index + 1;
                break;

            case 'c':
                index++;
                currentColor = text.Substring(index, 8);
                start        = index + 8;
                break;

            case 'r':
                currentColor = originalColor;
                start        = index + 1;
                break;

            case 'T':
            {
                index++;
                var nextIndex = text.IndexOf("|t", index);

                var node = new RichTextNode();
                node.Texture = text.Substring(index, nextIndex - index);
                nodes.Add(node);

                start = nextIndex + 2;
                break;
            }

            case 'H':
            {
                index++;
                var nextIndex = text.IndexOf("|h", index);
                currentLink = text.Substring(index, nextIndex - index);
                start       = nextIndex + 2;
                break;
            }

            case 'h':
                if (currentLink == null)
                {
                    throw new FormatException("currentLink == null");
                }

                currentLink = null;
                start       = index + 1;
                break;
            }
        }
        return(nodes);
    }