Ejemplo n.º 1
0
        /// <summary>
        /// Gets the wrapped line associated with this buffer position.
        /// </summary>
        /// <param name="bufferPosition">The buffer position.</param>
        /// <param name="displayContext">The display context.</param>
        /// <param name="layout">The layout.</param>
        /// <param name="wrappedLineIndex">Index of the wrapped line.</param>
        /// <returns></returns>
        public static LayoutLine GetWrappedLine(
            this TextPosition bufferPosition,
            IDisplayContext displayContext,
            out Layout layout,
            out int wrappedLineIndex)
        {
            // Get the layout and text associated with the line.
            LineBuffer lineBuffer = displayContext.LineBuffer;
            int        lineIndex  = bufferPosition.LinePosition.GetLineIndex(lineBuffer);
            string     text       = lineBuffer.GetLineText(lineIndex);

            layout = displayContext.Renderer.GetLineLayout(
                lineIndex, LineContexts.Unformatted);

            // Get the wrapped line associated with this character position.
            int characterIndex = bufferPosition.GetCharacterIndex(lineBuffer);
            int unicodeIndex   = PangoUtility.TranslateStringToPangoIndex(
                text, characterIndex);
            int x;

            layout.IndexToLineX(unicodeIndex, false, out wrappedLineIndex, out x);

            // Return the resulting line.
            return(layout.Lines[wrappedLineIndex]);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Gets the line X coordinates from either the state if we have one
        /// or calculate it from the buffer position's X coordinate.
        /// </summary>
        /// <param name="controller">The action context.</param>
        /// <param name="wrappedLine">The wrapped line.</param>
        /// <param name="position">The position.</param>
        /// <returns></returns>
        private static int GetLineX(
            EditorViewController controller,
            LayoutLine wrappedLine,
            TextPosition position)
        {
            int lineX;
            var state = controller.States.Get <VerticalMovementActionState>();

            if (state == null)
            {
                // Calculate the line state from the caret position. The cursor
                // is always to the left of the character unless we're at the
                // end, and then it's considered trailing of the previous
                // character.
                LineBuffer lineBuffer     = controller.DisplayContext.LineBuffer;
                int        lineIndex      = position.LinePosition.GetLineIndex(lineBuffer.LineCount);
                string     lineText       = lineBuffer.GetLineText(lineIndex);
                int        characterIndex = position.CharacterPosition.GetCharacterIndex(lineText);
                bool       trailing       = false;

                if (characterIndex == lineText.Length &&
                    lineText.Length > 0)
                {
                    characterIndex--;
                    trailing = true;
                }

                // Because Pango works with UTF-8-based indexes, we need to
                // convert the C# character index into that index to properly
                // identify the character.
                characterIndex = NormalizeEmptyStrings(lineText, characterIndex);
                int unicodeIndex = PangoUtility.TranslateStringToPangoIndex(
                    lineText, characterIndex);
                lineX = wrappedLine.IndexToX(unicodeIndex, trailing);

                // We need the line's style since it may have left passing
                // which will change our columns.
                LineBlockStyle style =
                    controller.DisplayContext.Renderer.GetLineStyle(
                        lineIndex, LineContexts.CurrentLine);

                var pixelPadding = (int)style.Padding.Left.GetValueOrDefault(0);
                lineX += Units.FromPixels(pixelPadding);

                // Save a new state into the states.
                state = new VerticalMovementActionState(lineX);
                controller.States.Add(state);
            }
            else
            {
                // Get the line coordinate from the state.
                lineX = state.LayoutLineX;
            }

            return(lineX);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Get the rectangle position of the given index.
        /// </summary>
        /// <param name="layout">The layout.</param>
        /// <param name="stringIndex">Index of the string.</param>
        /// <returns></returns>
        public static Rectangle TranslatedIndexToPos(
            this Layout layout,
            int stringIndex)
        {
            int pangoIndex = PangoUtility.TranslateStringToPangoIndex(
                layout.Text, stringIndex);
            Rectangle translatedIndexToPos = layout.IndexToPos(pangoIndex);

            return(translatedIndexToPos);
        }
        /// <summary>
        /// Gets the string index for an X coordinate.
        /// </summary>
        /// <param name="layoutLine">The layout line.</param>
        /// <param name="stringIndex">Index of the string.</param>
        /// <param name="trailing">if set to <c>true</c> [trailing].</param>
        /// <returns></returns>
        public static int TranslatedIndexToX(
            this LayoutLine layoutLine,
            int stringIndex,
            bool trailing)
        {
            int pangoIndex =
                PangoUtility.TranslateStringToPangoIndex(
                    layoutLine.Layout.Text, stringIndex);

            return(layoutLine.IndexToX(pangoIndex, trailing));
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Gets the cursor position inside the layout.
        /// </summary>
        /// <param name="layout">The layout.</param>
        /// <param name="stringIndex">The string index into the layout text.</param>
        /// <param name="strongPosition">The resulting strong position.</param>
        /// <param name="weakPosition">The resulting weak position.</param>
        public static void GetTranslatedCursorPos(
            this Layout layout,
            int stringIndex,
            out Rectangle strongPosition,
            out Rectangle weakPosition)
        {
            int pangoIndex = PangoUtility.TranslateStringToPangoIndex(
                layout.Text, stringIndex);

            layout.GetCursorPos(pangoIndex, out strongPosition, out weakPosition);
        }
        public void ToPangoOnEndOfSimpleString()
        {
            // Arrange
            const int    stringIndex = 6;
            const string text        = "simple";

            // Act
            int pangoIndex = PangoUtility.TranslateStringToPangoIndex(text, stringIndex);

            // Assert
            Assert.AreEqual(6, pangoIndex);
        }
        public void ToPangoOnEmptyString()
        {
            // Arrange
            const int    stringIndex = 0;
            const string text        = "";

            // Act
            int pangoIndex = PangoUtility.TranslateStringToPangoIndex(text, stringIndex);

            // Assert
            Assert.AreEqual(0, pangoIndex);
        }
        public void ToPangoOnBeginningOfTwoByteString()
        {
            // Arrange
            const int    stringIndex = 0;
            const string text        = "éâäàçê";

            // Act
            int pangoIndex = PangoUtility.TranslateStringToPangoIndex(text, stringIndex);

            // Assert
            Assert.AreEqual(0, pangoIndex);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Gets the line X coordinate for a given index.
        /// </summary>
        /// <param name="layout">The layout.</param>
        /// <param name="stringIndex">The string index of the string.</param>
        /// <param name="trailing">if set to <c>true</c> the position is trailing the glyph.</param>
        /// <param name="line">The resulting logical line in the layout.</param>
        /// <param name="x">The resulting x coordinate (in Pango units) in the layout.</param>
        public static void TranslatedIndexToLineX(
            this Layout layout,
            int stringIndex,
            bool trailing,
            out int line,
            out int x)
        {
            int pangoIndex = PangoUtility.TranslateStringToPangoIndex(
                layout.Text, stringIndex);

            layout.IndexToLineX(pangoIndex, trailing, out line, out x);
        }
        /// <summary>
        /// Gets the X ranges from the given string indexes.
        /// </summary>
        /// <param name="layoutLine">The layout line.</param>
        /// <param name="startStringIndex">Start index of the string.</param>
        /// <param name="endStringIndex">End index of the string.</param>
        /// <param name="ranges">The ranges.</param>
        public static void GetTranslatedXRanges(
            this LayoutLine layoutLine,
            int startStringIndex,
            int endStringIndex,
            out int[][] ranges)
        {
            int startPangoIndex =
                PangoUtility.TranslateStringToPangoIndex(
                    layoutLine.Layout.Text, startStringIndex);
            int endPangoIndex =
                PangoUtility.TranslateStringToPangoIndex(
                    layoutLine.Layout.Text, endStringIndex);

            layoutLine.GetXRanges(startPangoIndex, endPangoIndex, out ranges);
        }
        public void ToPangoOnBeyondTwoByteString()
        {
            // Arrange
            const int    stringIndex = 7;
            const string text        = "éâäàçê";

            // Act
            var exception =
                Assert.Throws <ArgumentOutOfRangeException>(
                    () => PangoUtility.TranslateStringToPangoIndex(text, stringIndex));

            // Assert
            Assert.AreEqual(
                "Provided index (7) cannot be greater than the length of the text (6).\r\nParameter name: stringIndex",
                exception.Message);
        }
Ejemplo n.º 12
0
        public static void Up(EditorViewController controller)
        {
            // Extract a number of useful variable for this method.
            IDisplayContext    displayContext = controller.DisplayContext;
            TextPosition       position       = displayContext.Caret.Position;
            EditorViewRenderer buffer         = displayContext.Renderer;

            // Figure out the layout and wrapped line we are currently on.
            Layout     layout;
            int        wrappedLineIndex;
            LayoutLine wrappedLine = position.GetWrappedLine(
                displayContext, out layout, out wrappedLineIndex);

            // Figure out the X coordinate of the line. If there is an action context,
            // use that. Otherwise, calculate it from the character index of the position.
            int lineX = GetLineX(controller, wrappedLine, position);

            // Figure out which wrapped line we'll be moving the caret to.
            LinePosition linePosition = position.LinePosition;
            int          lineIndex    = linePosition.GetLineIndex(buffer.LineBuffer);

            if (wrappedLineIndex == 0)
            {
                // If we are the last line in the buffer, just do nothing.
                if (linePosition == 0)
                {
                    return;
                }

                // Move to the next line.
                lineIndex--;
                layout           = buffer.GetLineLayout(lineIndex, LineContexts.None);
                wrappedLineIndex = layout.LineCount - 1;
                wrappedLine      = layout.Lines[wrappedLineIndex];
            }
            else
            {
                // Just move down in the layout.
                wrappedLineIndex--;
                wrappedLine = layout.Lines[wrappedLineIndex];
            }

            // Adjust the X coordinate for the current line.
            lineX -= GetLeftStylePaddingPango(controller, lineIndex);

            // The wrapped line has the current wrapped line, so use the lineX
            // to figure out which character to use.
            int trailing;
            int unicodeIndex;

            wrappedLine.XToIndex(lineX, out unicodeIndex, out trailing);

            // Calculate the character position, but we have to map UTF-8
            // characters because Pango uses that instead of C# strings.
            string lineText = controller.DisplayContext.LineBuffer.GetLineText(lineIndex);

            unicodeIndex = NormalizeEmptyStrings(lineText, unicodeIndex);
            int characterIndex = PangoUtility.TranslateStringToPangoIndex(
                lineText, unicodeIndex);

            if (lineText.Length > 0 &&
                trailing > 0)
            {
                characterIndex++;
            }

            // Draw the new location of the caret.
            var caretPosition = new TextPosition(lineIndex, characterIndex);

            displayContext.ScrollToCaret(caretPosition);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Converts the given line and character coordinates into pixel coordinates
        /// on the display.
        /// </summary>
        /// <param name="bufferPosition">The buffer position.</param>
        /// <param name="displayContext">The display context.</param>
        /// <param name="lineHeight">Will contains the height of the current line.</param>
        /// <returns></returns>
        public static PointD ToScreenCoordinates(
            this TextPosition bufferPosition,
            IDisplayContext displayContext,
            out int lineHeight)
        {
            // Get the line index, which needs to be a number in range.
            EditorViewRenderer buffer = displayContext.Renderer;
            int lineIndex             =
                bufferPosition.LinePosition.GetLineIndex(displayContext.LineBuffer);

            // Pull out some of the common things we'll be using in this method.
            int    bufferLineIndex = buffer.LineBuffer.NormalizeLineIndex(lineIndex);
            Layout layout          = buffer.GetLineLayout(
                bufferLineIndex, LineContexts.Unformatted);
            LineBlockStyle style = buffer.GetLineStyle(
                bufferLineIndex, LineContexts.Unformatted);

            // Figure out the top of the current line in relation to the entire
            // buffer and view. For lines beyond the first, we use
            // GetLineLayoutHeight because it also takes into account the line
            // spacing and borders which we would have to calculate otherwise.
            double y = bufferLineIndex == 0
                                ? 0
                                : buffer.GetLineLayoutHeight(0, bufferLineIndex - 1);

            // Add the style offset for the top-padding.
            y += style.Top;

            // The cursor position code uses Unicode instead of C# character
            // positions. This means we have to advance more than just one
            // value to calculate it. This actually uses UTF-8 encoding to
            // calculate the indexes.
            string lineText       = displayContext.LineBuffer.GetLineText(lineIndex);
            int    characterIndex =
                bufferPosition.GetCharacterIndex(displayContext.LineBuffer);
            int unicodeCharacter = PangoUtility.TranslateStringToPangoIndex(
                lineText, characterIndex);

            // We need to figure out the relative position. If the position equals
            // the length of the string, we want to put the caret at the end of the
            // character. Otherwise, we put it on the front of the character to
            // indicate insert point.
            bool trailing   = false;
            int  lineLength = buffer.LineBuffer.GetLineLength(
                bufferLineIndex, LineContexts.Unformatted);

            if (unicodeCharacter == lineLength)
            {
                // Shift back one character to calculate the position and put
                // the cursor at the end of the character.
                unicodeCharacter--;
                trailing = true;
            }

            // Figure out which wrapped line we are actually on and the position
            // inside that line. If the character equals the length of the string,
            // then we want to move to the end of it.
            int wrappedLineIndex;
            int layoutX;

            layout.IndexToLineX(
                unicodeCharacter, trailing, out wrappedLineIndex, out layoutX);

            // Get the relative offset into the wrapped lines.
            Rectangle layoutPoint = layout.IndexToPos(unicodeCharacter);

            y += Units.ToPixels(layoutPoint.Y);

            // Get the height of the wrapped line.
            Rectangle ink     = Rectangle.Zero;
            Rectangle logical = Rectangle.Zero;

            layout.Lines[wrappedLineIndex].GetPixelExtents(ref ink, ref logical);
            lineHeight = logical.Height;

            // Return the results.
            return(new PointD(Units.ToPixels(layoutX), y));
        }