Пример #1
0
        private Selection CalculateStartAndEndOfSelection(string actualText, XmlCursor cursor)
        {
            var result = new Selection {
                Start = -1, Length = 0
            };

            if (cursor.StartPos.ActualNode == this.XmlNode) // The start of the selection is on this node
            {
                switch (cursor.StartPos.PosOnNode)
                {
                case XmlCursorPositions.CursorOnNodeStartTag:     // The node itself is selected as start node
                case XmlCursorPositions.CursorOnNodeEndTag:
                    throw new ArgumentOutOfRangeException($"{nameof(cursor.StartPos.PosOnNode)}:{cursor.StartPos.PosOnNode.ToString()} not possible on a text node");
                // result.Start = 0;
                // result.Length = actualText.Length;
                // break;

                case XmlCursorPositions.CursorBehindTheNode:
                case XmlCursorPositions.CursorInsideTheEmptyNode:
                    // Since the cursor position arrives sorted, the EndPos can only lie behind the node
                    result.Start  = -1;
                    result.Length = 0;
                    break;

                case XmlCursorPositions.CursorInFrontOfNode:
                case XmlCursorPositions.CursorInsideTextNode:

                    if (cursor.StartPos.PosOnNode == XmlCursorPositions.CursorInsideTextNode)
                    {
                        result.Start = Math.Max(0, cursor.StartPos.PosInTextNode);     // inside text node
                    }
                    else
                    {
                        result.Start = 0;     // in front of the node
                    }

                    if (cursor.EndPos.ActualNode == this.XmlNode)     // If the end of the selection also is inside this node
                    {
                        switch (cursor.EndPos.PosOnNode)
                        {
                        case XmlCursorPositions.CursorOnNodeStartTag:         // start node is in front of the node, end node behind: everything is selected
                        case XmlCursorPositions.CursorOnNodeEndTag:
                        case XmlCursorPositions.CursorBehindTheNode:
                            result.Length = Math.Max(0, actualText.Length - result.Start);
                            break;

                        case XmlCursorPositions.CursorInsideTheEmptyNode:
                            result.Start  = -1;
                            result.Length = 0;
                            break;

                        case XmlCursorPositions.CursorInsideTextNode:          // till the marker in the text
                            result.Length = Math.Max(0, cursor.EndPos.PosInTextNode - result.Start);
                            break;

                        case XmlCursorPositions.CursorInFrontOfNode:
                            result.Length = 0;
                            break;

                        default:
                            throw new ApplicationException("unknown cursor.EndPos.PosOnNode '" + cursor.EndPos.PosOnNode + "'B");
                        }
                    }
                    else                                                                                  // The end of the selection is not inside this node
                    {
                        if (cursor.EndPos.ActualNode.ParentNode == cursor.StartPos.ActualNode.ParentNode) // If start and end are different, but directly in the same parent
                        {
                            result.Length = Math.Max(0, actualText.Length - result.Start);                // Select only the selected part
                        }
                        else                                                                              // Start and end are different and have different parents
                        {
                            result.Start  = 0;
                            result.Length = actualText.Length;       // select whole text node
                        }
                    }
                    break;

                default:
                    throw new ApplicationException("unknown cursor.StartPos.PosOnNode '" + cursor.StartPos.PosOnNode + "'A");
                }
            }
            else // The start of the selection is not on this node
            {
                if (cursor.EndPos.ActualNode == this.XmlNode) // But the end of the selection is
                {
                    switch (cursor.EndPos.PosOnNode)
                    {
                    case XmlCursorPositions.CursorOnNodeStartTag:       // The node itself is selected as End-Node
                    case XmlCursorPositions.CursorOnNodeEndTag:         // start node is in front of the node, end node behind: everything is selected
                    case XmlCursorPositions.CursorBehindTheNode:
                        result.Start  = 0;
                        result.Length = actualText.Length;
                        break;

                    case XmlCursorPositions.CursorInsideTheEmptyNode:
                        result.Start  = -1;
                        result.Length = 0;
                        break;

                    case XmlCursorPositions.CursorInsideTextNode:                                         // Start node is in front of the node, end node in the middle, so select from front to middle
                        if (cursor.EndPos.ActualNode.ParentNode == cursor.StartPos.ActualNode.ParentNode) // If start and end are different, but directly in the same parent
                        {
                            result.Start  = 0;
                            result.Length = Math.Max(0, cursor.EndPos.PosInTextNode); // Select only the selected front part
                        }
                        else                                                          // Start and end different and different parents
                        {
                            result.Start  = 0;
                            result.Length = actualText.Length;       // select whole text node
                        }
                        break;

                    case XmlCursorPositions.CursorInFrontOfNode:     // Start node is in front of the node, end node also
                        result.Start  = -1;
                        result.Length = 0;
                        break;

                    default:
                        throw new ApplicationException("unknown cursor.EndPos.PosOnNode '" + cursor.EndPos.PosOnNode + "'X");
                    }
                }
                else // Neither the start nor the end of the selection lies exactly on this node
                {
                    if (XmlCursorSelectionHelper.IsThisNodeInsideSelection(EditorState.CursorOptimized, this.XmlNode))
                    {
                        result.Start  = 0;
                        result.Length = actualText.Length;   // Select entire text node
                    }
                }
            }
            return(result);
        }
Пример #2
0
        protected override async Task <PaintContext> PaintInternal(PaintContext paintContext, bool cursorBlinkOn, XmlCursor cursor, IGraphics gfx, PaintModes paintMode, int depth)
        {
            this.nodeDimensions.Update();
            var isSelected = cursor?.StartPos != null && cursor?.EndPos != null && XmlCursorSelectionHelper.IsThisNodeInsideSelection(cursor, this.XmlNode);

            this.CreateChildElementsIfNeeded(gfx);

            Point newCursorPaintPos = null;

            bool alreadyUnpainted = false;

            switch (paintMode)
            {
            case PaintModes.ForcePaintNoUnPaintNeeded:
                alreadyUnpainted = true;
                break;

            case PaintModes.ForcePaintAndUnpaintBefore:
                this.UnPaint(gfx);
                alreadyUnpainted = true;
                break;

            case PaintModes.OnlyPaintWhenChanged:
                break;
            }

            // If the cursor is inside the empty node, then draw the cursor there
            if (cursor.StartPos.ActualNode == this.XmlNode)
            {
                if (cursor.StartPos.PosOnNode == XmlCursorPositions.CursorInFrontOfNode)
                {
                    // remember position for cursor line
                    newCursorPaintPos = new Point(paintContext.PaintPosX, paintContext.PaintPosY);
                }
            }

            var cursorIsOnThisNode = cursor.StartPos.ActualNode == this.XmlNode || cursor.EndPos.ActualNode == this.XmlNode;

            paintContext = await this.startTag.Paint(paintContext, cursorIsOnThisNode, cursorBlinkOn, alreadyUnpainted, isSelected, gfx);

            // If the cursor is inside the empty node, then draw the cursor there
            if (cursor.StartPos.ActualNode == this.XmlNode)
            {
                if (cursor.StartPos.PosOnNode == XmlCursorPositions.CursorInsideTheEmptyNode)
                {
                    // set position for cursor line
                    newCursorPaintPos = new Point(paintContext.PaintPosX - 1, paintContext.PaintPosY);
                }
            }

            paintContext = await this.PaintSubNodes(paintContext, cursorBlinkOn, cursor, gfx, paintMode, depth);

            if (this.endTag != null)
            {
                paintContext = await this.endTag.Paint(paintContext, cursorIsOnThisNode, cursorBlinkOn, alreadyUnpainted, isSelected, gfx);
            }

            // If the cursor is behind the node, then also draw the cursor there
            if (cursor.StartPos.ActualNode == this.XmlNode)
            {
                if (cursor.StartPos.PosOnNode == XmlCursorPositions.CursorBehindTheNode)
                {
                    newCursorPaintPos = new Point(paintContext.PaintPosX - 1, paintContext.PaintPosY);
                }
            }

            this.cursorPaintPos = newCursorPaintPos;
            return(paintContext.Clone());
        }