示例#1
0
        private void ElementChildren_Updated(object sender, RichTextPanelEventArgs e)
        {
            double viewportWidth;
            double widthWithScroll;

            if (ElementContainer != null && AutoWrap)
            {
                viewportWidth   = RenderSize.Width - (ElementContainer.BorderThickness.Left + ElementContainer.BorderThickness.Right + ElementContainer.Padding.Left + ElementContainer.Padding.Right);
                widthWithScroll = viewportWidth - 17;

                if (ElementChildren.Height > ElementContainer.ViewportHeight && _wrapWidth > widthWithScroll)
                {
                    _wrapWidth = (RenderSize.Width >= 74 ? widthWithScroll : 20);
                    if (VerticalScrollBarVisibility == ScrollBarVisibility.Disabled || VerticalScrollBarVisibility == ScrollBarVisibility.Hidden)
                    {
                        _wrapWidth = viewportWidth;
                    }
                    ElementChildren.Width = _wrapWidth;
                }
                else if (ElementChildren.Height < ElementContainer.ViewportHeight && _wrapWidth < viewportWidth)
                {
                    _wrapWidth            = viewportWidth;
                    ElementChildren.Width = _wrapWidth;
                }
                else
                {
                    if (VerticalScrollBarVisibility == ScrollBarVisibility.Disabled || VerticalScrollBarVisibility == ScrollBarVisibility.Hidden)
                    {
                        _wrapWidth = viewportWidth;
                    }
                    ElementChildren.Width = _wrapWidth;
                }

                if (ElementChildren.Height < ElementContainer.ViewportHeight && _contentScrollable)
                {
                    _contentScrollable = false;
                    RaiseRichTextEvent(ContentHideVerticalScrollBar, this, new RichTextBoxEventArgs(), false);
                }
                else if (ElementChildren.Height >= ElementContainer.ViewportHeight && !_contentScrollable)
                {
                    _contentScrollable = true;
                    RaiseRichTextEvent(ContentShowVerticalScrollBar, this, new RichTextBoxEventArgs(), false);
                }

                ElementChildren.MinHeight = ElementContainer.ViewportHeight;
            }
        }
        /// <summary>
        /// Merges TextBlock elements with the same style name (Tag property)
        /// </summary>
        /// <param name="row">Row to compact</param>
        /// <param name="ignore">Element to ignore when compacting the row</param>
        private void CompactRow(RichTextPanelRow row, UIElement ignore)
        {
            _removed = 0;

            if (row == null)
            {
                return;
            }

            int startIndex = ContentChildren.IndexOf(row.Start);
            int endIndex   = ContentChildren.IndexOf(row.End);
            RichTextPanelEventArgs args;
            TextBlockPlus          current;
            TextBlockPlus          next;
            bool tagMatched = false;
            int  i;

            if (startIndex < 0 || endIndex < 0)
            {
                return;
            }

            for (i = endIndex - 1; i >= startIndex; i--)
            {
                if (ContentChildren[i] is TextBlockPlus && ContentChildren[i] != ignore)
                {
                    current = (TextBlockPlus)ContentChildren[i];
                    if (ContentChildren[i + 1] is TextBlockPlus && ContentChildren[i + 1] != ignore)
                    {
                        next       = (TextBlockPlus)ContentChildren[i + 1];
                        tagMatched = false;

                        if (current.Tag is RichTextTag && next.Tag is RichTextTag)
                        {
                            if (((RichTextTag)current.Tag).CompareTo(next.Tag) == 0)
                            {
                                if (current.Text.Length > 0)
                                {
                                    args = new RichTextPanelEventArgs(current)
                                    {
                                        Created = next, Index = current.Text.Length
                                    };

                                    current.Text += next.Text;
                                    RaiseEvent(TextBlockMerge, this, args);

                                    if (!args.Cancel)
                                    {
                                        ContentChildren.Remove(next);
                                        if (row.End == next)
                                        {
                                            row.End = current;
                                        }
                                        _removed++;
                                    }
                                }
                                else
                                {
                                    ContentChildren.Remove(current);
                                    if (row.End == current)
                                    {
                                        row.End = next;
                                    }
                                    if (row.Start == current)
                                    {
                                        row.Start = next;
                                    }
                                    _removed++;
                                }

                                tagMatched = true;
                            }
                        }

                        if (!tagMatched && current.Text.Length == 0)
                        {
                            ContentChildren.Remove(current);
                            if (row.Start == current)
                            {
                                row.Start = next;
                            }
                            _removed++;
                        }
                    }
                }
            }
        }
        internal void Update(RichTextPanelRow topRow, bool updateAll, UIElement ignore)
        {
            int                    rowIndex    = _rows.IndexOf(topRow);
            int                    startIndex  = 0;
            int                    rowEndIndex = 0;
            Point                  pos         = new Point();
            double                 thisWidth   = 0;
            List <string>          splitText;
            TextBlockPlus          currentTextBlock;
            TextBlockPlus          next;
            RichTextPanelRow       temp;
            RichTextPanelEventArgs args;
            FrameworkElement       current;
            Table                  table;
            bool                   updateNextLine = false;
            bool                   newlineStarted = false;
            bool                   createBlankTextBlock;
            int                    startRow = 0;
            int                    lineOut  = 1;
            int                    endRow;
            double                 offset;
            int                    i;
            int                    a;
            int                    b;

            if (ActualWidth == 0)
            {
                return;
            }

            if (rowIndex >= 0)
            {
                startIndex  = ContentChildren.IndexOf(_rows[rowIndex].Start);
                rowEndIndex = ContentChildren.IndexOf(_rows[rowIndex].End);
            }
            else
            {
                rowIndex = 0;
            }

            startRow = rowIndex;
            _tempRows.Clear();

            if (rowIndex < _rows.Count)
            {
                pos.Y = _rows[rowIndex].Position.Y;
            }

            if (startIndex < 0)
            {
                return;
            }

            for (i = startIndex; i < ContentChildren.Count; i++)
            {
                newlineStarted = false;
                current        = (FrameworkElement)ContentChildren[i];

                current.SetValue(Canvas.LeftProperty, pos.X);
                current.SetValue(Canvas.TopProperty, pos.Y);

                if (!(current is TextBlockPlus))
                {
                    if (current is Table)
                    {
                        table = (Table)current;
                        if (table.AutoWidth)
                        {
                            table.Width = (double.IsNaN(Width) ? ActualWidth : Width) - pos.X;
                        }
                        thisWidth = table.Width;
                    }
                    else
                    {
                        thisWidth = (double.IsNaN(current.Width) ? current.ActualWidth : current.Width);
                    }
                }
                else
                {
                    currentTextBlock = (TextBlockPlus)current;
                    thisWidth        = currentTextBlock.ContentWidth;

                    if (pos.X + thisWidth > ActualWidth)
                    {
                        splitText = SplitText(currentTextBlock, currentTextBlock.Text, pos.X, ActualWidth);

                        if (splitText.Count > 1)
                        {
                            b    = 0;
                            args = new RichTextPanelEventArgs(currentTextBlock)
                            {
                                Created = null, Index = b
                            };
                            RaiseEvent(TextBlockSplit, this, args);

                            if (!args.Cancel)
                            {
                                currentTextBlock.Text = splitText[0];

                                args = new RichTextPanelEventArgs(currentTextBlock)
                                {
                                    Created = currentTextBlock, Index = b
                                };
                                RaiseEvent(TextBlockSplit, this, args);

                                for (a = 1; a < splitText.Count; a++)
                                {
                                    next = CreateTextBlock(splitText[a]);
                                    args = new RichTextPanelEventArgs(currentTextBlock)
                                    {
                                        Created = next, Index = b
                                    };
                                    RaiseEvent(TextBlockSplit, this, args);

                                    if (!args.Cancel)
                                    {
                                        ContentChildren.Insert(i + a, next);
                                        b += splitText[a].Length;
                                    }
                                }
                            }
                            if (currentTextBlock.Text.Length == 0)
                            {
                                pos.X = 99999;
                            }
                        }
                        updateNextLine = true;
                        lineOut        = 1;
                    }
                    thisWidth = currentTextBlock.ContentWidth;
                }

                pos.X += thisWidth;

                if (current is Newline)
                {
                    createBlankTextBlock = (i == 0);
                    if (i > 0)
                    {
                        if (ContentChildren[i - 1] is TextBlockPlus)
                        {
                            currentTextBlock = (TextBlockPlus)ContentChildren[i - 1];
                            if (current.Tag != currentTextBlock.Tag)
                            {
                                RaiseEvent(ApplyFormatting, this, new RichTextPanelEventArgs(currentTextBlock)
                                {
                                    Created = current
                                });
                            }
                        }
                        else
                        {
                            createBlankTextBlock = true;
                        }
                    }

                    if (createBlankTextBlock)
                    {
                        next = CreateTextBlock("");
                        args = new RichTextPanelEventArgs(current)
                        {
                            Created = next
                        };
                        RaiseEvent(TextBlockSplit, this, args);

                        if (!args.Cancel)
                        {
                            next.SetValue(Canvas.LeftProperty, pos.X - thisWidth);
                            next.SetValue(Canvas.TopProperty, pos.Y);
                            ContentChildren.Insert(i, next);
                            i++;
                        }
                    }
                    newlineStarted = true;
                    pos.Y         += UpdateRowContent(startIndex, i, ignore);
                    i         -= _removed;
                    pos.X      = 0;
                    startIndex = i + 1;
                }
                else
                {
                    if (pos.X > ActualWidth)
                    {
                        newlineStarted = true;
                        pos.Y         += UpdateRowContent(startIndex, i - 1, ignore);
                        i -= _removed;
                        if (i < 0)
                        {
                            break;
                        }
                        pos.X = 0;

                        current.SetValue(Canvas.LeftProperty, pos.X);
                        current.SetValue(Canvas.TopProperty, pos.Y);

                        pos.X      = thisWidth;
                        startIndex = i;
                    }
                }

                if (newlineStarted && i > rowEndIndex)
                {
                    if (!updateAll && !updateNextLine)
                    {
                        if (lineOut <= 0)
                        {
                            break;
                        }
                        lineOut--;
                    }

                    updateNextLine = false;
                }
                else if (i == ContentChildren.Count - 1 && startIndex < i)
                {
                    UpdateRowContent(startIndex, i, ignore);
                    i -= _removed;
                }
            }

            temp   = GetRowForElementIndex(i);
            endRow = (i == ContentChildren.Count && _rows.Count > 0 ? _rows.Count - 1 : _rows.IndexOf(temp));

            if (endRow >= 0)
            {
                _rows.RemoveRange(startRow, (endRow - startRow) + 1);
            }

            _rows.InsertRange(startRow, _tempRows);
            a = startRow + _tempRows.Count;

            if (endRow >= 0 && endRow < _rows.Count - 1 && a < _rows.Count)
            {
                offset     = (_rows[a - 1].Position.Y + _rows[a - 1].Dimensions.Y) - _rows[a].Position.Y;
                startIndex = ContentChildren.IndexOf(_rows[a].Start);

                if (offset != 0)
                {
                    // Reposition following rows if the size of the modified rows has changed
                    for (i = a; i < _rows.Count; i++)
                    {
                        _rows[i].Position = new Point(_rows[i].Position.X, _rows[i].Position.Y + offset);
                    }
                    for (i = startIndex; i < ContentChildren.Count; i++)
                    {
                        ContentChildren[i].SetValue(Canvas.TopProperty, (double)ContentChildren[i].GetValue(Canvas.TopProperty) + offset);
                    }
                }
            }

            if (Rows.Count > 0)
            {
                CalculateRowDimensions(Rows[Rows.Count - 1], false);
                SetElementAlignment(Rows[Rows.Count - 1]);
            }

            _lastUpdatedSize = ActualWidth;
            UpdateCanvasSize();
            RaiseEvent(Updated, this, null);
        }
 /// <summary>
 /// Generates the specified event
 /// </summary>
 /// <param name="sender">Event source object</param>
 /// <param name="args">Event arguments</param>
 protected virtual void RaiseEvent(RichTextPanelEventHandler handler, object sender, RichTextPanelEventArgs args)
 {
     if (handler != null)
     {
         handler(sender, args);
     }
 }