Ejemplo n.º 1
0
        /// <summary>
        /// Calculates the parameters with which to draw the selection.
        /// </summary>
        private void UpdateSelection()
        {
            if (View == null || textLayoutStream.Count == 0 || !selectionPosition.HasValue || pendingTextLayout)
                return;

            if (SelectionLength == 0)
            {
                selectionLineStart = 0;
                selectionLineCount = 0;

                selectionTop = default(Ultraviolet.Rectangle);
                selectionBottom = default(Ultraviolet.Rectangle);
            }
            else
            {
                var selectionStart = SelectionStart;
                var selectionStartLineInfo = default(LineInfo);
                var selectionStartGlyphBounds = View.Resources.TextRenderer.GetGlyphBounds(textLayoutStream,
                    selectionStart, out selectionStartLineInfo, true);

                var selectionEnd = SelectionStart + (SelectionLength - 1);
                var selectionEndLineInfo = default(LineInfo);
                var selectionEndGlyphBounds = View.Resources.TextRenderer.GetGlyphBounds(textLayoutStream,
                    selectionEnd, out selectionEndLineInfo, true);

                selectionLineStart = selectionStartLineInfo.LineIndex;
                selectionLineCount = 1 + (selectionEndLineInfo.LineIndex - selectionStartLineInfo.LineIndex);

                // Top
                var selectionTopX = selectionStartGlyphBounds.X;
                var selectionTopY = selectionStartGlyphBounds.Y;
                var selectionTopWidth = (selectionLineCount == 1) ? selectionEndGlyphBounds.Right - selectionStartGlyphBounds.Left :
                    selectionStartLineInfo.Width - (selectionStartGlyphBounds.X - selectionStartLineInfo.X);
                var selectionTopHeight = selectionStartLineInfo.Height;
                selectionTop = new Ultraviolet.Rectangle(selectionTopX, selectionTopY, selectionTopWidth, selectionTopHeight);

                // Bottom
                if (selectionLineCount > 1)
                {
                    var selectionBottomX = selectionEndLineInfo.X;
                    var selectionBottomY = selectionEndGlyphBounds.Y;
                    var selectionBottomWidth = selectionEndGlyphBounds.Right - selectionBottomX;
                    var selectionBottomHeight = selectionEndLineInfo.Height;
                    selectionBottom = new Ultraviolet.Rectangle(selectionBottomX, selectionBottomY, selectionBottomWidth, selectionBottomHeight);
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Scrolls to ensure that the caret is within the viewport.
        /// </summary>
        private void ScrollToCaret(Boolean showMaximumLineWidth, Boolean jumpLeft, Boolean jumpRight)
        {
            var scrollViewer = Parent as ScrollViewer;
            if (scrollViewer == null)
                return;

            var boundsViewport = new RectangleD(scrollViewer.HorizontalOffset, scrollViewer.VerticalOffset,
                scrollViewer.ViewportWidth, scrollViewer.ViewportHeight);

            var boundsCaretPixs = new Ultraviolet.Rectangle(caretBounds.X, caretBounds.Y, caretRenderBounds.Width, caretBounds.Height);
            var boundsCaretDips = Display.PixelsToDips(boundsCaretPixs);

            var isHorizontalScrollingNecessary = (boundsCaretDips.Left < boundsViewport.Left || boundsCaretDips.Right > boundsViewport.Right);
            var isVerticalScrollingNecessary = (boundsCaretDips.Top < boundsViewport.Top || boundsCaretDips.Bottom > boundsViewport.Bottom);

            if (!isHorizontalScrollingNecessary && !isVerticalScrollingNecessary)
                return;

            if (isVerticalScrollingNecessary)
            {
                if (boundsCaretDips.Top < boundsViewport.Top)
                {
                    var verticalOffset = boundsCaretDips.Top;
                    scrollViewer.ScrollToVerticalOffset(verticalOffset);
                }
                else
                {
                    var verticalOffset = (boundsCaretDips.Bottom - boundsViewport.Height);
                    scrollViewer.ScrollToVerticalOffset(verticalOffset);
                }
            }

            if (showMaximumLineWidth)
            {
                var owner = TemplatedParent as Control;
                var alignment = (owner == null) ? TextAlignment.Left : owner.GetValue<TextAlignment>(TextBox.TextAlignmentProperty);
                var horizontalOffset = (alignment == TextAlignment.Right) ? boundsCaretDips.Left : boundsCaretDips.Right - boundsViewport.Width;
                scrollViewer.ScrollToHorizontalOffset(horizontalOffset);
            }
            else
            {
                if (isHorizontalScrollingNecessary)
                {
                    if (boundsCaretDips.Left < boundsViewport.Left)
                    {
                        var horizontalOffset = boundsCaretDips.Left -
                            (jumpLeft ? (boundsViewport.Width / 3.0) : 0);

                        scrollViewer.ScrollToHorizontalOffset(horizontalOffset);
                    }
                    else
                    {
                        var horizontalOffset = (boundsCaretDips.Right - boundsViewport.Width) +
                            (jumpRight ? (boundsViewport.Width / 3.0) : 0);

                        scrollViewer.ScrollToHorizontalOffset(horizontalOffset);
                    }
                }
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Calculates the position at which to draw the text caret.
        /// </summary>
        private void UpdateCaret()
        {
            if (View == null || pendingTextLayout)
                return;

            var owner = TemplatedParent as Control;

            var isReadOnly = (owner != null && owner.GetValue<Boolean>(TextBox.IsReadOnlyProperty));

            var fontFace = TextFontFace;
            var fontLineSpacing = (fontFace != null) ? fontFace.LineSpacing : 0;
            var fontLineSpacingHalf = (Int32)Math.Ceiling(fontLineSpacing / 2f);

            var styledCaretWidth = (Int32)Display.DipsToPixels(CaretWidth);
            var styledCaretThickness = (Int32)Display.DipsToPixels(CaretThickness);

            var caretAlignment = TextAlignment.Left;
            var caretRenderX = 0;
            var caretRenderY = 0;
            var caretRenderWidth = 0;
            var caretRenderHeight = 0;

            if (caretInsertionMode == CaretMode.Overwrite && !IsLineBreak(caretPosition) && !isReadOnly)
            {
                actualInsertionMode = CaretMode.Overwrite;

                var caretDefaultSize = GetDefaultSizeOfOverwriteCaret();
                var caretX = 0;
                var caretY = 0;
                var caretWidth = caretDefaultSize.Width;
                var caretHeight = caretDefaultSize.Height;

                if (textLayoutStream.TotalLength > 0)
                {
                    var glyphLineInfo = default(LineInfo);
                    var glyphBounds = View.Resources.TextRenderer.GetGlyphBounds(textLayoutStream, caretPosition, out glyphLineInfo, true);

                    caretX = glyphBounds.Left;
                    caretY = glyphBounds.Top;
                    caretWidth = glyphBounds.Width;
                    caretBounds = new Ultraviolet.Rectangle(caretX, caretY, caretWidth, glyphBounds.Height);
                    caretLineIndex = glyphLineInfo.LineIndex;
                }
                else
                {
                    caretAlignment = (owner == null) ? TextAlignment.Left : owner.GetValue<TextAlignment>(TextBox.TextAlignmentProperty);
                    caretBounds = new Ultraviolet.Rectangle(caretX, caretY, caretWidth, fontLineSpacing);
                    caretLineIndex = 0;
                }

                caretRenderWidth = caretWidth;
                caretRenderHeight = Math.Min(caretBounds.Height, styledCaretThickness);
                caretRenderY = caretBounds.Bottom - caretRenderHeight;
            }
            else
            {
                actualInsertionMode = CaretMode.Insert;

                var caretDefaultSize = GetDefaultSizeOfInsertionCaret();
                var caretX = 0;
                var caretY = 0;
                var caretWidth = caretDefaultSize.Width;
                var caretHeight = caretDefaultSize.Height;

                if (textLayoutStream.TotalLength > 0)
                {
                    var lineInfo = default(LineInfo);
                    var boundsGlyph = default(Ultraviolet.Rectangle?);
                    var boundsInsert = View.Resources.TextRenderer.GetInsertionPointBounds(textLayoutStream,
                        caretPosition, out lineInfo, out boundsGlyph);

                    caretX = boundsInsert.X;
                    caretY = boundsInsert.Y;
                    caretWidth = (boundsGlyph.HasValue && boundsGlyph.Value.Width > 0) ? boundsGlyph.Value.Width : fontLineSpacingHalf;
                    caretHeight = boundsInsert.Height;
                    caretBounds = new Ultraviolet.Rectangle(caretX, caretY, caretWidth, caretHeight);
                    caretLineIndex = lineInfo.LineIndex;
                }
                else
                {
                    caretAlignment = (owner == null) ? TextAlignment.Left : owner.GetValue<TextAlignment>(TextBox.TextAlignmentProperty);
                    caretBounds = new Ultraviolet.Rectangle(caretX, caretY, caretWidth, caretHeight);
                    caretLineIndex = 0;
                }

                caretRenderWidth = Math.Min(caretBounds.Width, styledCaretWidth);
                caretRenderHeight = caretBounds.Height;
                caretRenderY = caretBounds.Top;
            }

            switch (caretAlignment)
            {
                case TextAlignment.Left:
                    caretRenderX = caretBounds.Left;
                    break;

                case TextAlignment.Center:
                    caretRenderX = caretBounds.Center.X - (caretRenderWidth / 2);
                    break;

                case TextAlignment.Right:
                    caretRenderX = (caretBounds.Right - caretRenderWidth);
                    break;
            }

            caretRenderBounds = new Ultraviolet.Rectangle(caretRenderX, caretRenderY, caretRenderWidth, caretRenderHeight);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Draws the current selection.
        /// </summary>
        private void DrawSelection(UltravioletTime time, DrawingContext dc)
        {
            if (!selectionPosition.HasValue || SelectionLength == 0)
                return;

            // Don't draw the selection unless we have keyboard focus (unless IsInactiveSelectionHighlightEnabled is true).
            var owner = TemplatedParent as Control;
            if (owner == null)
                return;

            var isActive = owner.IsKeyboardFocusWithin;
            var isEnabledIfInactive = owner.GetValue<Boolean>(TextBox.IsInactiveSelectionHighlightEnabledProperty);
            if (!isActive && !isEnabledIfInactive)
                return;

            var selectionColor = isActive ? SelectionColor : InactiveSelectionColor;

            // Draw the first line
            var selectionTopDips = Display.PixelsToDips(selectionTop);
            DrawImage(dc, SelectionImage, selectionTopDips, selectionColor, true);

            // Draw the middle
            if (selectionLineCount > 2)
            {
                textLayoutStream.AcquirePointers();

                var lineInfo = textLayoutStream.GetLineInfo(selectionLineStart);

                for (int i = selectionLineStart + 1; i < selectionLineStart + selectionLineCount - 1; i++)
                {
                    textLayoutStream.GetNextLineInfoRef(ref lineInfo, out lineInfo);

                    var lineBounds = new Ultraviolet.Rectangle(lineInfo.X, lineInfo.Y, lineInfo.Width, lineInfo.Height);
                    var lineBoundsDips = Display.PixelsToDips(lineBounds);
                    DrawImage(dc, SelectionImage, lineBoundsDips, selectionColor, true);
                }

                textLayoutStream.ReleasePointers();
            }

            // Draw the last line
            if (selectionLineCount > 1)
            {
                var selectionBottomDips = Display.PixelsToDips(selectionBottom);
                DrawImage(dc, SelectionImage, selectionBottomDips, selectionColor, true);
            }
        }