예제 #1
0
 internal void Redraw(FoldingSection fs)
 {
     foreach (TextView textView in textViews)
     {
         textView.Redraw(fs);
     }
 }
        /// <inheritdoc/>
        public override VisualLineElement ConstructElement(int offset)
        {
            if (foldingManager == null)
            {
                return(null);
            }
            int            foldedUntil    = -1;
            FoldingSection foldingSection = null;

            foreach (FoldingSection fs in foldingManager.GetFoldingsContaining(offset))
            {
                if (fs.IsFolded)
                {
                    if (fs.EndOffset > foldedUntil)
                    {
                        foldedUntil    = fs.EndOffset;
                        foldingSection = fs;
                    }
                }
            }
            if (foldedUntil > offset && foldingSection != null)
            {
                // Handle overlapping foldings: if there's another folded folding
                // (starting within the foldingSection) that continues after the end of the folded section,
                // then we'll extend our fold element to cover that overlapping folding.
                bool foundOverlappingFolding;
                do
                {
                    foundOverlappingFolding = false;
                    foreach (FoldingSection fs in FoldingManager.GetFoldingsContaining(foldedUntil))
                    {
                        if (fs.IsFolded && fs.EndOffset > foldedUntil)
                        {
                            foldedUntil             = fs.EndOffset;
                            foundOverlappingFolding = true;
                        }
                    }
                } while (foundOverlappingFolding);

                string title = foldingSection.Title;
                if (string.IsNullOrEmpty(title))
                {
                    title = "...";
                }
                var p = new VisualLineElementTextRunProperties(CurrentContext.GlobalTextRunProperties);
                p.SetForegroundBrush(textBrush);
                var textFormatter = TextFormatterFactory.Create(CurrentContext.TextView);
                var text          = FormattedTextElement.PrepareText(textFormatter, title, p);
                return(new FoldingLineElement(foldingSection, text, foldedUntil - offset)
                {
                    textBrush = textBrush
                });
            }
            else
            {
                return(null);
            }
        }
예제 #3
0
        /// <summary>
        /// Gets the first offset greater or equal to <paramref name="startOffset"/> where a folded folding starts.
        /// Returns -1 if there are no foldings after <paramref name="startOffset"/>.
        /// </summary>
        public int GetNextFoldedFoldingStart(int startOffset)
        {
            FoldingSection fs = foldings.FindFirstSegmentWithStartAfter(startOffset);

            while (fs != null && !fs.IsFolded)
            {
                fs = foldings.GetNextSegment(fs);
            }
            return(fs != null ? fs.StartOffset : -1);
        }
예제 #4
0
 /// <summary>
 /// Removes a folding section from this manager.
 /// </summary>
 public void RemoveFolding(FoldingSection fs)
 {
     if (fs == null)
     {
         throw new ArgumentNullException("fs");
     }
     fs.IsFolded = false;
     foldings.Remove(fs);
     Redraw(fs);
 }
예제 #5
0
        /// <summary>
        /// Gets all foldings that start exactly at <paramref name="startOffset"/>.
        /// </summary>
        public ReadOnlyCollection <FoldingSection> GetFoldingsAt(int startOffset)
        {
            List <FoldingSection> result = new List <FoldingSection>();
            FoldingSection        fs     = foldings.FindFirstSegmentWithStartAfter(startOffset);

            while (fs != null && fs.StartOffset == startOffset)
            {
                result.Add(fs);
                fs = foldings.GetNextSegment(fs);
            }
            return(result.AsReadOnly());
        }
예제 #6
0
        /// <summary>
        /// Creates a folding for the specified text section.
        /// </summary>
        public FoldingSection CreateFolding(int startOffset, int endOffset)
        {
            if (startOffset >= endOffset)
            {
                throw new ArgumentException("startOffset must be less than endOffset");
            }
            if (startOffset < 0 || endOffset > document.TextLength)
            {
                throw new ArgumentException("Folding must be within document boundary");
            }
            FoldingSection fs = new FoldingSection(this, startOffset, endOffset);

            foldings.Add(fs);
            Redraw(fs);
            return(fs);
        }
예제 #7
0
        void TextViewVisualLinesChanged(object sender, EventArgs e)
        {
            foreach (FoldingMarginMarker m in markers)
            {
                RemoveVisualChild(m);
            }
            markers.Clear();
            InvalidateVisual();
            if (TextView != null && FoldingManager != null && TextView.VisualLinesValid)
            {
                foreach (VisualLine line in TextView.VisualLines)
                {
                    FoldingSection fs = FoldingManager.GetNextFolding(line.FirstDocumentLine.Offset);
                    if (fs == null)
                    {
                        continue;
                    }
                    if (fs.StartOffset <= line.LastDocumentLine.Offset + line.LastDocumentLine.Length)
                    {
                        FoldingMarginMarker m = new FoldingMarginMarker {
                            IsExpanded     = !fs.IsFolded,
                            VisualLine     = line,
                            FoldingSection = fs
                        };

                        markers.Add(m);
                        AddVisualChild(m);

                        m.IsMouseDirectlyOverChanged += delegate { InvalidateVisual(); };

                        InvalidateMeasure();
                        continue;
                    }
                }
            }
        }
예제 #8
0
        /// <summary>
        /// Updates the foldings in this <see cref="FoldingManager"/> using the given new foldings.
        /// This method will try to detect which new foldings correspond to which existing foldings; and will keep the state
        /// (<see cref="FoldingSection.IsFolded"/>) for existing foldings.
        /// </summary>
        /// <param name="newFoldings">The new set of foldings. These must be sorted by starting offset.</param>
        /// <param name="firstErrorOffset">The first position of a parse error. Existing foldings starting after
        /// this offset will be kept even if they don't appear in <paramref name="newFoldings"/>.
        /// Use -1 for this parameter if there were no parse errors.</param>
        public void UpdateFoldings(IEnumerable <NewFolding> newFoldings, int firstErrorOffset)
        {
            if (newFoldings == null)
            {
                throw new ArgumentNullException("newFoldings");
            }

            if (firstErrorOffset < 0)
            {
                firstErrorOffset = int.MaxValue;
            }

            var oldFoldings         = this.AllFoldings.ToArray();
            int oldFoldingIndex     = 0;
            int previousStartOffset = 0;

            // merge new foldings into old foldings so that sections keep being collapsed
            // both oldFoldings and newFoldings are sorted by start offset
            foreach (NewFolding newFolding in newFoldings)
            {
                // ensure newFoldings are sorted correctly
                if (newFolding.StartOffset < previousStartOffset)
                {
                    throw new ArgumentException("newFoldings must be sorted by start offset");
                }
                previousStartOffset = newFolding.StartOffset;

                int startOffset = newFolding.StartOffset.CoerceValue(0, document.TextLength);
                int endOffset   = newFolding.EndOffset.CoerceValue(0, document.TextLength);

                if (newFolding.StartOffset == newFolding.EndOffset)
                {
                    continue;                     // ignore zero-length foldings
                }
                // remove old foldings that were skipped
                while (oldFoldingIndex < oldFoldings.Length && newFolding.StartOffset > oldFoldings[oldFoldingIndex].StartOffset)
                {
                    this.RemoveFolding(oldFoldings[oldFoldingIndex++]);
                }
                FoldingSection section;
                // reuse current folding if its matching:
                if (oldFoldingIndex < oldFoldings.Length && newFolding.StartOffset == oldFoldings[oldFoldingIndex].StartOffset)
                {
                    section        = oldFoldings[oldFoldingIndex++];
                    section.Length = newFolding.EndOffset - newFolding.StartOffset;
                }
                else
                {
                    // no matching current folding; create a new one:
                    section = this.CreateFolding(newFolding.StartOffset, newFolding.EndOffset);
                    // auto-close #regions only when opening the document
                    if (isFirstUpdate)
                    {
                        section.IsFolded = newFolding.DefaultClosed;
                    }
                    section.Tag = newFolding;
                }
                section.Title = newFolding.Name;
            }
            isFirstUpdate = false;
            // remove all outstanding old foldings:
            while (oldFoldingIndex < oldFoldings.Length)
            {
                FoldingSection oldSection = oldFoldings[oldFoldingIndex++];
                if (oldSection.StartOffset >= firstErrorOffset)
                {
                    break;
                }
                this.RemoveFolding(oldSection);
            }
        }
 public FoldingLineElement(FoldingSection fs, TextLine text, int documentLength) : base(text, documentLength)
 {
     this.fs = fs;
 }