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); } }