/// <summary>
        /// append the text string \a text to the RenderedString \a rs.
        /// </summary>
        /// <param name="rs"></param>
        /// <param name="text"></param>
        private void AppendRenderedText(RenderedString rs, string text)
        {
            var cpos = 0;

            // split the given string into lines based upon the newline character
            while (text.Length > cpos)
            {
                // find next newline
                var nlpos = text.IndexOf("\n", cpos);
                // calculate length of this substring
                var len = ((nlpos != -1) ? nlpos : text.Length) - cpos;

                // construct new text component and append it.
                var rtc = new RenderedStringTextComponent(text.Substring(cpos, len), d_fontName);
                rtc.SetPadding(d_padding);
                rtc.SetColours(new ColourRect(d_colours));
                rtc.SetVerticalFormatting(d_vertAlignment);
                rtc.SetAspectLock(d_aspectLock);
                rs.AppendComponent(rtc);

                // break line if needed
                if (nlpos != -1)
                {
                    rs.AppendLineBreak();
                }

                // advance current position.  +1 to skip the \n char
                cpos += len + 1;
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// split the string in line \a line as close to \a split_point as possible.
        /// <para>
        /// The RenderedString \a left will receive the left portion of the split,
        /// while the right portion of the split will remain in this RenderedString.
        /// </para>
        /// </summary>
        /// <param name="refWnd"></param>
        /// <param name="line">
        /// The line number on which the split is to occur.
        /// </param>
        /// <param name="splitPoint">
        /// float value specifying the pixel location where the split should occur.
        /// The actual split will occur as close to this point as possible, though
        /// preferring a shorter 'left' portion when the split can not be made
        /// exactly at the requested point.
        /// </param>
        /// <param name="left">
        /// RenderedString object that will receieve the left portion of the split.
        /// Any existing content in the RenderedString is replaced.
        /// </param>
        /// <exception cref="InvalidRequestException">
        /// thrown if \a line is out of range.
        /// </exception>
        public void Split(Window refWnd, int line, float splitPoint, RenderedString left)
        {
            // FIXME: This function is big and nasty; it breaks all the rules for a
            // 'good' function and desperately needs some refactoring work done to it.
            // On the plus side, it does seem to work though ;)

            if (line >= GetLineCount())
            {
                throw new InvalidRequestException("line number specified is invalid.");
            }

            left.ClearComponents();

            if (d_components.Count == 0)
            {
                return;
            }

            // move all components in lines prior to the line being split to the left
            if (line > 0)
            {
                // calculate size of range
                var sz = d_lines[line - 1].First + d_lines[line - 1].Second;

                //// range start
                //ComponentList::iterator cb = d_components.begin();
                //// range end (exclusive)
                //ComponentList::iterator ce = cb + sz;
                //// copy components to left side
                //left.d_components.assign(cb, ce);
                //// erase components from this side.
                //d_components.erase(cb, ce);
                for (int i = 0; i < sz; i++)
                {
                    left.d_components.Add(d_components[0]);
                    d_components.RemoveAt(0);
                }

                //LineList::iterator lb = d_lines.begin();
                //LineList::iterator le = lb + line;
                //// copy lines to left side
                //left.d_lines.assign(lb, le);
                //// erase lines from this side
                //d_lines.erase(lb, le);
                for (int i = 0; i < line; i++)
                {
                    left.d_lines.Add(d_lines[0]);
                    d_lines.RemoveAt(0);
                }
            }

            // find the component where the requested split point lies.
            var partialExtent = 0f;

            var idx           = 0;
            var lastComponent = d_lines[0].Second;

            for (; idx < lastComponent; ++idx)
            {
                partialExtent += d_components[idx].GetPixelSize(refWnd).Width;

                if (splitPoint <= partialExtent)
                {
                    break;
                }
            }

            // case where split point is past the end
            if (idx >= lastComponent)
            {
                // transfer this line's components to the 'left' string.
                //
                // calculate size of range
                var sz = d_lines[0].Second;
                //// range start
                //ComponentList::iterator cb = d_components.begin();
                //// range end (exclusive)
                //ComponentList::iterator ce = cb + sz;
                //// copy components to left side
                //left.d_components.insert(left.d_components.end(), cb, ce);
                //// erase components from this side.
                //d_components.erase(cb, ce);
                for (int i = 0; i < sz; i++)
                {
                    left.d_components.Add(d_components[0]);
                    d_components.RemoveAt(0);
                }

                // copy line info to left side
                left.d_lines.Add(d_lines[0]);
                // erase line from this side
                d_lines.RemoveAt(0);

                // fix up lines in this object
                for (int comp = 0, i = 0; i < d_lines.Count; ++i)
                {
                    d_lines[i].First = comp;
                    comp            += d_lines[i].Second;
                }

                return;
            }

            left.AppendLineBreak();
            var leftLine = left.GetLineCount() - 1;

            // Everything up to 'idx' is xfered to 'left'
            for (var i = 0; i < idx; ++i)
            {
                left.d_components.Add(d_components[0]);
                d_components.RemoveAt(0);
                ++left.d_lines[leftLine].Second;
                --d_lines[0].Second;
            }

            // now to split item 'idx' putting half in left and leaving half in this.
            RenderedStringComponent c = d_components[0];

            if (c.CanSplit())
            {
                var lc = c.Split(refWnd, splitPoint - (partialExtent - c.GetPixelSize(refWnd).Width), idx == 0);

                if (lc != null)
                {
                    left.d_components.Add(lc);
                    ++left.d_lines[leftLine].Second;
                }
            }
            // can't split, if component width is >= split_point xfer the whole
            // component to it's own line in the left part (FIX #306)
            else if (c.GetPixelSize(refWnd).Width >= splitPoint)
            {
                left.AppendLineBreak();
                left.d_components.Add(d_components[0]);
                d_components.RemoveAt(0);
                ++left.d_lines[leftLine + 1].Second;
                --d_lines[0].Second;
            }

            // fix up lines in this object
            for (int comp = 0, i = 0; i < d_lines.Count; ++i)
            {
                d_lines[i].First = comp;
                comp            += d_lines[i].Second;
            }
        }