コード例 #1
0
 public RichTextPanelRow(RichTextPanelRow row)
 {
     Start      = row.Start;
     End        = row.End;
     Dimensions = new Point(Dimensions.X, Dimensions.Y);
     Position   = new Point(Position.X, Position.Y);
     Margin     = new Thickness(row.Margin.Left, row.Margin.Top, row.Margin.Right, row.Margin.Bottom);
 }
コード例 #2
0
        /// <summary>
        /// Gets the element at the provided position
        /// </summary>
        /// <param name="position">Position</param>
        /// <returns>Element at the position or null</returns>
        public UIElement GetRowElementAtPosition(Point position, RichTextPanelRow row)
        {
            UIElement result     = null;
            int       startIndex = ContentChildren.IndexOf(row.Start);
            int       endIndex   = ContentChildren.IndexOf(row.End);
            double    x;
            double    width;
            int       i;

            if (startIndex >= 0)
            {
                for (i = startIndex; i <= endIndex; i++)
                {
                    x     = (double)ContentChildren[i].GetValue(Canvas.LeftProperty);
                    width = (double)ContentChildren[i].GetValue(Canvas.WidthProperty);

                    if (ContentChildren[i] is TextBlockPlus)
                    {
                        width = ((TextBlockPlus)ContentChildren[i]).ContentWidth;
                    }
                    else
                    {
                        width = (double)ContentChildren[i].GetValue(Canvas.ActualWidthProperty);
                    }

                    if (position.X >= x && position.X <= x + width)
                    {
                        result = ContentChildren[i];
                        break;
                    }
                }

                if (result == null)
                {
                    x      = (double)ContentChildren[startIndex].GetValue(Canvas.LeftProperty);
                    result = (position.X < x ? ContentChildren[startIndex] : ContentChildren[endIndex]);
                }
            }

            return(result);
        }
コード例 #3
0
        /// <summary>
        /// Removes the provided element from the panel
        /// </summary>
        /// <param name="element">Element to remove</param>
        public UIElement Remove(UIElement element)
        {
            RichTextPanelRow insertRow = GetRowForElement(element);

            if (insertRow == null)
            {
                return(null);
            }

            List <UIElement> children = insertRow.GetChildren(_contentChildren.Children);

            if (children.Count > 1)
            {
                if (children[0] == element)
                {
                    insertRow.Start = children[1];
                }
            }

            ContentChildren.Remove(element);
            return(insertRow.Start);
        }
コード例 #4
0
        /// <summary>
        /// Calculates the size of a given row
        /// </summary>
        /// <param name="row">Row index</param>
        private double CalculateRowDimensions(RichTextPanelRow row, bool updatePosition)
        {
            int              startIndex = ContentChildren.IndexOf(row.Start);
            int              endIndex   = ContentChildren.IndexOf(row.End);
            int              rowIndex   = Rows.IndexOf(row);
            double           tempY;
            double           tempX;
            Point            dims = new Point();
            double           topY = 0;
            FrameworkElement element;
            TextBlockPlus    currentTextBlock;
            double           marginTop    = 0;
            double           marginBottom = 0;
            int              i;

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

            for (i = startIndex; i <= endIndex; i++)
            {
                element = (FrameworkElement)ContentChildren[i];
                if (element is TextBlockPlus)
                {
                    currentTextBlock = (TextBlockPlus)element;

                    if (currentTextBlock.Text.Length == 0)
                    {
                        currentTextBlock.Text = "I";
                        tempY = currentTextBlock.ContentHeight;
                        currentTextBlock.Text = "";
                    }
                    else
                    {
                        tempY = currentTextBlock.ContentHeight;
                    }
                    tempY *= currentTextBlock.LineHeightMultiplier;
                    tempX  = currentTextBlock.ContentWidth;
                }
                else
                {
                    tempY = (double.IsNaN(element.Height) ? element.ActualHeight : element.Height);
                    tempX = (double.IsNaN(element.Width) ? element.ActualWidth : element.Width);

                    if (element is Bullet)
                    {
                        tempX = ((Bullet)element).IndentWidth;
                    }
                }

                if (element.Margin.Top > marginTop)
                {
                    marginTop = element.Margin.Top;
                }
                if (element.Margin.Bottom > marginBottom)
                {
                    marginBottom = element.Margin.Bottom;
                }

                if (tempY > dims.Y)
                {
                    dims.Y = tempY;
                }
                dims.X += tempX;

                tempY = (double)element.GetValue(Canvas.TopProperty);
                if (tempY > topY)
                {
                    topY = tempY;
                }
            }

            if (!(row.End is Newline) || (rowIndex >= 0 && rowIndex == Rows.Count - 1))
            {
                marginBottom = 0;
            }
            if (startIndex > 0)
            {
                if (!(ContentChildren[startIndex - 1] is Newline))
                {
                    marginTop = 0;
                }
            }

            row.Margin     = new Thickness(0, marginTop, 0, marginBottom);
            row.Dimensions = new Point(dims.X, dims.Y + marginTop + marginBottom);

            if (updatePosition)
            {
                row.Position = new Point(0, topY);
            }

            return(row.Dimensions.Y);
        }
コード例 #5
0
        /// <summary>
        /// Positions each row element based on it's alignment properties
        /// </summary>
        /// <param name="row">Row index</param>
        /// <returns>Height of the row</returns>
        private double SetElementAlignment(RichTextPanelRow row)
        {
            Point            currentDims = new Point();
            FrameworkElement current;
            Point            position = new Point();
            int    startIndex         = ContentChildren.IndexOf(row.Start);
            int    endIndex           = ContentChildren.IndexOf(row.End);
            double baseX = 0;
            int    i;

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

            for (i = startIndex; i <= endIndex; i++)
            {
                current       = (FrameworkElement)ContentChildren[i];
                currentDims.X = (current is TextBlockPlus ? ((TextBlockPlus)current).ContentWidth : (double.IsNaN(current.Width) ? current.ActualWidth : current.Width));
                currentDims.Y = (current is TextBlockPlus ? ((TextBlockPlus)current).ContentHeight : (double.IsNaN(current.Height) ? current.ActualHeight : current.Height));

                if (current is Bullet)
                {
                    currentDims.X = ((Bullet)current).IndentWidth;
                }

                switch (current.VerticalAlignment)
                {
                case VerticalAlignment.Top:
                    position.Y = row.Position.Y;
                    break;

                case VerticalAlignment.Center:
                    position.Y = row.Position.Y + ((row.Dimensions.Y - (currentDims.Y + row.Margin.Top + row.Margin.Bottom)) * 0.5);
                    break;

                default:
                    position.Y = ((row.Position.Y + (row.Dimensions.Y - row.Margin.Bottom)) - currentDims.Y) - row.Margin.Top;
                    break;
                }

                if (row.Margin.Top != current.Margin.Top)
                {
                    position.Y -= current.Margin.Top;
                }

                switch (((FrameworkElement)ContentChildren[startIndex]).HorizontalAlignment)
                {
                case HorizontalAlignment.Center:
                    baseX = (ActualWidth - row.Dimensions.X) * 0.5;
                    break;

                case HorizontalAlignment.Right:
                    baseX = ActualWidth - row.Dimensions.X;
                    break;

                default:
                    baseX = 0;
                    break;
                }

                current.SetValue(Canvas.LeftProperty, baseX + position.X);
                position.X += currentDims.X;

                current.SetValue(Canvas.TopProperty, position.Y);
            }

            row.Position = new Point(baseX, row.Position.Y);

            return(row.Dimensions.Y);
        }
コード例 #6
0
        /// <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++;
                        }
                    }
                }
            }
        }
コード例 #7
0
        public int GetRowIndexForElement(UIElement element)
        {
            RichTextPanelRow row = GetRowForElement(element);

            return(_rows.IndexOf(row));
        }
コード例 #8
0
        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);
        }