Пример #1
0
        private void UpdateText(Style style)
        {
            Lines.Clear();

            if (string.IsNullOrEmpty(_text))
            {
                return;
            }

            TextElement def = new TextElement();

            def.Font = style.Font;

            List <TextElement> elements     = BBCode.Parse(_text, style, false);
            List <TextElement> textElements = new List <TextElement>();

            Point pos   = new Point();
            Point tsize = new Point();

            int lineHeight = 0;
            List <TextElement> thisLine = new List <TextElement>();

            TextSize = Point.Zero;

            if (TextWrap)
            {
                #region TextWrap = true
                foreach (TextElement element in elements)
                {
                    int font = Gui.Renderer.GetFont(element.Font);

                    if (element.Linebreak)
                    {
                        pos.x  = 0;
                        pos.y += lineHeight + Leading;

                        element.Position = pos;
                        element.Size     = Gui.Renderer.GetTextSize(" ", font);

                        foreach (TextElement el in thisLine)
                        {
                            if (!el.Linebreak)
                            {
                                el.Position.y += lineHeight - el.Size.y;
                            }
                        }

                        thisLine.Clear();
                        lineHeight = element.Size.y;
                        textElements.Add(element);
                    }
                    else
                    {
                        #region wrap

                        string[] words = element.Text.Split(' ');

                        List <TextElement> sub = new List <TextElement>();

                        TextElement e = new TextElement(element);
                        e.Text     = string.Empty;
                        e.Position = pos;
                        sub.Add(e);

                        int i = 0;

                        foreach (string word in words)
                        {
                            string temp = word;
                            if (i > 0)
                            {
                                temp = " " + word;
                            }

                            tsize      = Gui.Renderer.GetTextSize(temp, font);
                            lineHeight = Math.Max(lineHeight, tsize.y);
                            int limit = Size.x - (style.TextPadding.Left + style.TextPadding.Right);

                            i++;

                            // the word fits, add to current element
                            if (pos.x + tsize.x < limit)
                            {
                                e.Text += temp;
                                e.Size  = Gui.Renderer.GetTextSize(e.Text, font);
                                pos.x  += tsize.x;
                            }
                            else
                            {
                                // the whole word is larger than the text area
                                if (tsize.x > limit)
                                {
                                }
                                // the whole word fits into text area
                                else
                                {
                                    pos.x  = 0;
                                    pos.y += lineHeight + Leading;
                                    thisLine.Add(e);

                                    foreach (TextElement el in thisLine)
                                    {
                                        if (!el.Linebreak)
                                        {
                                            el.Position.y += lineHeight - el.Size.y;
                                        }
                                    }

                                    thisLine.Clear();
                                    lineHeight = 0;

                                    TextElement linebreak = new TextElement(e);
                                    linebreak.Text      = string.Empty;
                                    linebreak.Linebreak = true;
                                    linebreak.Position  = pos;
                                    sub.Add(linebreak);

                                    e          = new TextElement(element);
                                    e.Text     = word;
                                    e.Position = pos;
                                    e.Size     = Gui.Renderer.GetTextSize(e.Text, font);
                                    sub.Add(e);

                                    lineHeight = Math.Max(lineHeight, e.Size.y);

                                    pos.x += tsize.x;
                                }
                            }
                        }

                        thisLine.AddRange(sub);
                        textElements.AddRange(sub);
                        #endregion
                    }
                }

                foreach (TextElement el in thisLine)
                {
                    if (!el.Linebreak)
                    {
                        el.Position.y += lineHeight - el.Size.y;
                    }
                }
                #endregion
            }
            else
            {
                foreach (TextElement element in elements)
                {
                    int font = Gui.Renderer.GetFont(element.Font);

                    if (element.Linebreak)
                    {
                        pos.x  = 0;
                        pos.y += lineHeight + Leading;

                        element.Position = pos;
                        element.Size     = Gui.Renderer.GetTextSize(" ", font);

                        foreach (TextElement el in thisLine)
                        {
                            if (!el.Linebreak)
                            {
                                el.Position.y += lineHeight - el.Size.y;
                            }
                        }

                        thisLine.Clear();
                        lineHeight = element.Size.y;

                        textElements.Add(element);
                    }
                    else
                    {
                        //if (!string.IsNullOrEmpty(element.Text))
                        //{
                        tsize      = Gui.Renderer.GetTextSize(string.IsNullOrEmpty(element.Text) ? " " : element.Text, font);
                        lineHeight = Math.Max(lineHeight, tsize.y);

                        element.Position = pos;
                        element.Size     = tsize;

                        textElements.Add(element);

                        pos.x += tsize.x;

                        thisLine.Add(element);
                        //}
                    }
                }

                foreach (TextElement el in thisLine)
                {
                    if (!el.Linebreak)
                    {
                        el.Position.y += lineHeight - el.Size.y;
                    }
                }
            }

            TextLine line = new TextLine();

            foreach (TextElement element in textElements)
            {
                if (element.Linebreak)
                {
                    line.CharLength += 1;
                    line.Elements.Add(element);
                    Lines.Add(line);
                    line = new TextLine();
                }
                else
                {
                    line.Width      += element.Size.x;
                    line.CharLength += element.Text.Length;
                    line.Elements.Add(element);
                }

                TextSize.x = Math.Max(TextSize.x, line.Width);
                TextSize.y = Math.Max(TextSize.y, element.Position.y + element.Size.y);
            }

            Lines.Add(line);

            TextSize += new Point(style.TextPadding.Left + style.TextPadding.Right, style.TextPadding.Top + style.TextPadding.Bottom);

            LastSize = Size;
            IsDirty  = false;

            //GetLineAndCol();
        }
Пример #2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TextElement"/> class.
 /// </summary>
 /// <param name="copy">The copy.</param>
 public TextElement(TextElement copy)
 {
     Font  = copy.Font;
     Color = copy.Color;
     Href  = copy.Href;
 }
Пример #3
0
        private void UpdateText(Style style)
        {
            activeLibrary.Clear();
            Lines.Clear();

            TextElement def = new TextElement();

            def.Font = style.Font;

            List <TextElement> elements     = BBCode.Parse(_text, style, BBCodeEnabled);
            List <TextElement> textElements = new List <TextElement>();

            Point pos   = new Point();
            Point tsize = new Point();
            int   advx  = 0;

            int lineHeight = 0;
            List <TextElement> thisLine = new List <TextElement>();

            TextSize = Point.Zero;

            if (TextWrap)
            {
                #region TextWrap = true
                bool firstInLine = true;

                foreach (TextElement element in elements)
                {
                    int font = Gui.Renderer.GetFont(element.Font);

                    if (element.Linebreak)
                    {
                        if (firstInLine)
                        {
                            lineHeight = Gui.Renderer.GetTextSize(" ", font).y;
                        }

                        pos.x  = 0;
                        pos.y += lineHeight + Leading;

                        foreach (TextElement el in thisLine)
                        {
                            el.Position.y += lineHeight - el.Size.y;
                        }

                        thisLine.Clear();
                        lineHeight = 0;

                        textElements.Add(element);
                        firstInLine = true;
                    }
                    else if (element.IsControl)
                    {
                        Control ctrl = null;

                        if (library.ContainsKey(element.Control))
                        {
                            ctrl = library[element.Control];
                        }
                        else if (ControlRequest != null)
                        {
                            ctrl = ControlRequest(element.Control);
                            library.Add(element.Control, ctrl);
                        }

                        if (ctrl != null)
                        {
                            activeLibrary.Add(element.Control, true);

                            ctrl.Position = pos;
                            ctrl.UserData = element.Control;

                            if (ctrl.Parent == null)
                            {
                                Elements.Add(ctrl);
                            }

                            element.Size = ctrl.Size;
                            tsize        = ctrl.Size;

                            if (pos.x + tsize.x < Size.x - (style.TextPadding.Left + style.TextPadding.Right))
                            {
                                element.Position = pos;
                                pos.x           += ctrl.Size.x;
                                lineHeight       = Math.Max(lineHeight, tsize.y);
                            }
                            else
                            {
                                pos.x  = 0;
                                pos.y += lineHeight + Leading;

                                foreach (TextElement el in thisLine)
                                {
                                    el.Position.y += lineHeight - el.Size.y;
                                }

                                thisLine.Clear();

                                textElements.Add(new TextElement {
                                    Linebreak = true
                                });

                                firstInLine = true;

                                element.Position = pos;
                                pos.x           += ctrl.Size.x;
                                lineHeight       = tsize.y;
                            }

                            textElements.Add(element);
                            //thisLine.Add(element);
                        }
                    }
                    else
                    {
                        #region wrap

                        string[] words = System.Text.RegularExpressions.Regex.Split(element.Text, @"(?=(?<=[^\s])\s+)");

                        List <TextElement> sub = new List <TextElement>();

                        TextElement e = new TextElement(element);
                        e.Text     = string.Empty;
                        e.Position = pos;

                        int  c       = 0;
                        bool isBreak = false;

                        foreach (string word in words)
                        {
                            if (word.Length == 0)
                            {
                                continue;
                            }

                            string temp = word;

                            // if this is the first word in a new line
                            // remove leading whitespaces
                            if (firstInLine)
                            {
                                temp = word.TrimStart();
                            }

                            tsize      = Gui.Renderer.GetTextSize(e.Text + temp, font);
                            lineHeight = Math.Max(lineHeight, tsize.y);

                            if (pos.x + tsize.x < Size.x - (style.TextPadding.Left + style.TextPadding.Right))
                            {
                                // the word fits, add to current element
                                e.Text     += temp;
                                e.Size      = tsize;
                                firstInLine = false;
                            }
                            else
                            {
                                #region new

                                if (firstInLine)
                                {
                                    // the word fits, add to current element
                                    e.Text     += temp;
                                    e.Size      = tsize;
                                    firstInLine = false;
                                }
                                else
                                {
                                    // word does not fit, add the current element
                                    thisLine.Add(e);
                                    sub.Add(e);
                                    textElements.AddRange(sub);

                                    foreach (TextElement el in thisLine)
                                    {
                                        el.Position.y += lineHeight - el.Size.y;
                                    }

                                    sub.Clear();
                                    thisLine.Clear();

                                    // reset line pos
                                    pos.x  = 0;
                                    pos.y += lineHeight + Leading;

                                    lineHeight = 0;

                                    // add a break
                                    TextElement linebreak = new TextElement(e);
                                    linebreak.Linebreak = true;
                                    sub.Add(linebreak);

                                    // create new starting element
                                    e           = new TextElement(element);
                                    e.Text      = temp.TrimStart();
                                    e.Position  = pos;
                                    e.Size      = Gui.Renderer.GetTextSize(e.Text, font);
                                    lineHeight  = Math.Max(lineHeight, e.Size.y);
                                    firstInLine = false;
                                }

                                #endregion

                                #region old

                                //if (c > 0)
                                //{
                                //    isBreak = true;

                                //    // the word does not fit
                                //    pos.x = 0;
                                //    pos.y += lineHeight + Leading;
                                //}

                                //// is more than one word in this line exceeding the break limit?
                                //if (c > 0)
                                //{
                                //    // if so, we need to first add the current element,
                                //    thisLine.Add(e);
                                //    sub.Add(e);

                                //    foreach (TextElement el in thisLine)
                                //    {
                                //        el.Position.y += lineHeight - el.Size.y;
                                //        // el.Size.y += lineHeight - el.Size.y;
                                //    }

                                //    thisLine.Clear();
                                //    lineHeight = 0;

                                //    TextElement linebreak = new TextElement(e);
                                //    linebreak.Linebreak = true;
                                //    sub.Add(linebreak);

                                //    e = new TextElement(element);
                                //    e.Text = temp.TrimStart();
                                //    e.Position = pos;
                                //    e.Size = Gui.Renderer.GetTextSize(e.Text, font);

                                //    lineHeight = Math.Max(lineHeight, e.Size.y);

                                //    if (c <= words.Length)
                                //        isBreak = false;
                                //}
                                //else
                                //{
                                //    // if not, we just add the current word
                                //    e.Position = pos;
                                //    e.Text = temp;
                                //    e.Size = Gui.Renderer.GetTextSize(e.Text, font);
                                //    //sub.Add(e);
                                //}

                                #endregion

                                //pos.x += tsize.x;
                            }

                            c++;
                        }

                        if (!isBreak)
                        {
                            //e.Size = Gui.Renderer.GetTextSize(e.Text, font);
                            pos.x      = pos.x + e.Size.x;
                            lineHeight = Math.Max(lineHeight, e.Size.y);
                            sub.Add(e);
                        }

                        thisLine.AddRange(sub);
                        textElements.AddRange(sub);

                        #endregion
                    }
                }

                foreach (TextElement el in thisLine)
                {
                    el.Position.y += lineHeight - el.Size.y;
                }

                #endregion
            }
            else
            {
                #region TextWrap = false

                bool firstInLine = true;
                bool singleLine  = true;

                foreach (TextElement element in elements)
                {
                    int font = Gui.Renderer.GetFont(element.Font);

                    if (element.Linebreak)
                    {
                        if (firstInLine)
                        {
                            lineHeight = Gui.Renderer.GetTextSize(" ", font).y;
                        }

                        pos.x  = 0;
                        pos.y += lineHeight + Leading;

                        foreach (TextElement el in thisLine)
                        {
                            el.Position.y += lineHeight - el.Size.y;
                            // el.Size.y += lineHeight - el.Size.y;
                        }

                        thisLine.Clear();
                        lineHeight = 0;

                        element.Position = pos;
                        textElements.Add(element);
                        firstInLine = true;
                        singleLine  = false;
                    }
                    else if (element.IsControl)
                    {
                        Control ctrl = null;

                        if (library.ContainsKey(element.Control))
                        {
                            ctrl = library[element.Control];
                        }
                        else if (ControlRequest != null)
                        {
                            ctrl = ControlRequest(element.Control);
                            library.Add(element.Control, ctrl);
                        }

                        if (ctrl != null)
                        {
                            ctrl.Position = pos;

                            if (ctrl.Parent == null)
                            {
                                Elements.Add(ctrl);
                            }

                            activeLibrary.Add(element.Control, true);

                            element.Position = pos;
                            element.Size     = ctrl.Size;

                            pos.x += ctrl.Size.x;

                            tsize      = element.Size;
                            lineHeight = Math.Max(lineHeight, tsize.y);
                            textElements.Add(element);
                            //thisLine.Add(element);
                        }
                    }
                    else
                    {
                        if (firstInLine)
                        {
                            element.Text = element.Text.TrimStart();
                            firstInLine  = false;
                        }

                        tsize      = Gui.Renderer.GetTextSize(string.IsNullOrEmpty(element.Text) ? " " : element.Text, font);
                        lineHeight = Math.Max(lineHeight, tsize.y);

                        element.Position = pos;
                        element.Size     = tsize;

                        textElements.Add(element);

                        pos.x += tsize.x;

                        thisLine.Add(element);
                    }
                }

                foreach (TextElement el in thisLine)
                {
                    el.Position.y += lineHeight - el.Size.y;
                }

                #endregion

                #region AutoEllipsis (...)

                if (singleLine && AutoEllipsis && (AutoSize == Squid.AutoSize.None || AutoSize == AutoSize.Vertical))
                {
                    int removeAt = -1;
                    int width    = 0;
                    int limit    = Size.x - style.TextPadding.Left - style.TextPadding.Right;

                    Alignment align = TextAlign != Alignment.Inherit ? TextAlign : style.TextAlign;

                    if (align == Alignment.TopLeft || align == Alignment.MiddleLeft || align == Alignment.BottomLeft)
                    {
                        for (int i = 0; i < textElements.Count; i++)
                        {
                            int font     = Gui.Renderer.GetFont(textElements[i].Font);
                            int ellipsis = Gui.Renderer.GetTextSize("...", font).x;

                            if (width + textElements[i].Size.x + ellipsis <= limit)
                            {
                                width += textElements[i].Size.x;
                                continue;
                            }
                            else
                            {
                                string text  = string.Empty;
                                string final = string.Empty;
                                removeAt = i + 1;

                                foreach (char c in textElements[i].Text)
                                {
                                    final = text + c + "...";

                                    int w = Gui.Renderer.GetTextSize(final, font).x;

                                    if (width + w >= limit)
                                    {
                                        textElements[i].Text = text + "...";
                                        break;
                                    }
                                    else
                                    {
                                        text += c;
                                    }
                                }

                                break;
                            }
                        }

                        if (removeAt > -1)
                        {
                            textElements.RemoveRange(removeAt, textElements.Count - removeAt);
                        }
                    }
                    else if (align == Alignment.TopRight || align == Alignment.MiddleRight || align == Alignment.BottomRight)
                    {
                        for (int i = textElements.Count - 1; i >= 0; i--)
                        {
                            int   font     = Gui.Renderer.GetFont(textElements[i].Font);
                            int   ellipsis = Gui.Renderer.GetTextSize("...", font).x;
                            int   fullsize = textElements[i].Size.x;
                            Point oldpos   = textElements[i].Position;

                            if (width + textElements[i].Size.x + ellipsis <= limit)
                            {
                                width += textElements[i].Size.x;
                            }
                            else
                            {
                                string inc   = string.Empty;
                                string final = string.Empty;
                                string text  = textElements[i].Text;
                                removeAt = i;

                                for (int j = text.Length; j >= 0; j--)
                                {
                                    char c = new char();

                                    if (j < text.Length)
                                    {
                                        c     = text[j];
                                        final = "..." + c + inc;
                                        inc   = c + inc;
                                    }
                                    else
                                    {
                                        final = "..." + inc;
                                    }

                                    if (j == 0 && removeAt == 0)
                                    {
                                        final = inc;
                                    }

                                    int w = Gui.Renderer.GetTextSize(final, font).x;

                                    Point position = oldpos;
                                    position.x               = oldpos.x + (fullsize - w);
                                    textElements[i].Text     = final;
                                    textElements[i].Position = position;

                                    if (width + w > limit && j > 0)
                                    {
                                        break;
                                    }
                                }

                                break;
                            }
                        }

                        if (removeAt > 0)
                        {
                            int ww = 0;
                            for (int i = 0; i < removeAt; i++)
                            {
                                ww += textElements[i].Size.x;
                            }

                            textElements.RemoveRange(0, removeAt);

                            for (int i = 0; i < textElements.Count; i++)
                            {
                                Point position = textElements[i].Position;
                                position.x -= ww;
                                textElements[i].Position = position;
                            }
                        }
                    }
                }

                #endregion
            }

            TextLine line = new TextLine();

            foreach (TextElement element in textElements)
            {
                line.Width += element.Size.x;
                line.Elements.Add(element);

                TextSize.x = Math.Max(TextSize.x, line.Width);
                TextSize.y = Math.Max(TextSize.y, element.Position.y + element.Size.y);

                if (element.Linebreak)
                {
                    Lines.Add(line);
                    line = new TextLine();
                }
            }

            TextSize += new Point(style.TextPadding.Left + style.TextPadding.Right, style.TextPadding.Top + style.TextPadding.Bottom);

            Lines.Add(line);

            LastSize = Size;
            IsDirty  = false;

            FinalizeTextLayout(style);

            foreach (KeyValuePair <string, Control> pair in library)
            {
                if (!activeLibrary.ContainsKey(pair.Key))
                {
                    Elements.Remove(pair.Value);
                }
            }
        }
Пример #4
0
        public static List <TextElement> Parse(string text, Style style, bool enabled)
        {
            if (string.IsNullOrEmpty(text))
            {
                return(new List <TextElement>());
            }

            if (enabled)
            {
                text = ConvertBBCodeToHTML(text);
            }
            else
            {
                text = EscapeXML(text);

                text = text.Replace("\r\n", "<br/>");
                text = text.Replace("\n", "<br/>");

                text = text.Replace("&quot;r&quot;n", "<br/>");
                text = text.Replace("&quot;n", "<br/>");
            }

            var element = new TextElement {
                Font = style.Font, Color = style.TextColor
            };
            var lastElement = new TextElement {
                Font = style.Font, Color = style.TextColor
            };
            var result = new List <TextElement>();

            if (reader == null)
            {
                reader = new Xml.XmlReader(text);
            }
            else
            {
                reader.New(text);
            }

            while (reader.Read())
            {
                switch (reader.NodeType)
                {
                case XmlNodeType.Element:

                    switch (reader.Name.ToLower())
                    {
                    case "control":
                        if (reader.HasAttributes)
                        {
                            while (reader.MoveToNextAttribute())
                            {
                                if (reader.Name.Equals("key"))
                                {
                                    element.Control = reader.Value;
                                }
                                else if (reader.Name.Equals("data"))
                                {
                                    // element.Data = reader.Value;
                                }
                            }
                        }

                        result.Add(element);
                        element = new TextElement(element);

                        break;

                    case "font":
                        if (reader.HasAttributes)
                        {
                            lastElement.Color = element.Color;
                            lastElement.Font  = element.Font;

                            while (reader.MoveToNextAttribute())
                            {
                                if (reader.Name.Equals("name"))
                                {
                                    element.Font = reader.Value;
                                }
                                else if (reader.Name.Equals("color"))
                                {
                                    var color = element.Color.Value;

                                    if (int.TryParse(reader.Value, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture, out color))
                                    {
                                        element.Color = color;
                                    }
                                    else if (int.TryParse(reader.Value, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out color))
                                    {
                                        element.Color = color;
                                    }
                                }
                            }
                        }

                        break;

                    case "a":
                        if (reader.HasAttributes)
                        {
                            while (reader.MoveToNextAttribute())
                            {
                                if (reader.Name.Equals("href"))
                                {
                                    element.Href = reader.Value;
                                }
                            }
                        }
                        break;

                    case "br":
                        element.Linebreak = true;
                        result.Add(element);

                        element = new TextElement(element);
                        break;

                    default: break;
                    }

                    break;

                case XmlNodeType.EndElement:
                    switch (reader.Name.ToLower())
                    {
                    case "control":
                        element.Font  = lastElement.Font;
                        element.Color = lastElement.Color;
                        break;

                    case "font":
                        element.Font  = lastElement.Font;
                        element.Color = lastElement.Color;
                        break;

                    case "a":
                        element.Href = null;
                        break;
                    }

                    break;

                case XmlNodeType.Text:
                    if (reader.Value.Length > 0)
                    {
                        element.Text = UnescapeXML(reader.Value);
                        result.Add(element);

                        element = new TextElement(element);
                    }
                    break;

                default:
                    break;
                }
            }

            return(result);
        }