Browse Source

Reimplemented the ParserFoldingStrategy for AvalonEdit.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4829 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 16 years ago
parent
commit
012b77e96a
  1. 1
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj
  2. 3
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditViewContent.cs
  3. 18
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs
  4. 134
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ParserFoldingStrategy.cs
  5. 20
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextDocument.cs
  6. 30
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/FoldingManager.cs
  7. 26
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/FoldingSection.cs

1
src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj

@ -70,6 +70,7 @@ @@ -70,6 +70,7 @@
<Compile Include="Src\CustomCommands.cs" />
<Compile Include="Src\IconBarManager.cs" />
<Compile Include="Src\IconBarMargin.cs" />
<Compile Include="Src\ParserFoldingStrategy.cs" />
<Compile Include="Src\QuickClassBrowser.cs">
<SubType>Code</SubType>
</Compile>

3
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditViewContent.cs

@ -66,11 +66,12 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -66,11 +66,12 @@ namespace ICSharpCode.AvalonEdit.AddIn
isLoading = true;
try {
BookmarksDetach();
codeEditor.FileName = file.FileName;
codeEditor.PrimaryTextEditor.SyntaxHighlighting =
HighlightingManager.Instance.GetDefinitionByExtension(Path.GetExtension(file.FileName));
codeEditor.Load(stream);
// we set the file name after loading because this will place the fold markers etc.
codeEditor.FileName = file.FileName;
BookmarksAttach();
} finally {
isLoading = false;

18
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs

@ -185,6 +185,8 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -185,6 +185,8 @@ namespace ICSharpCode.AvalonEdit.AddIn
var iconBarMargin = new IconBarMargin(iconBarManager) { TextView = textView };
textEditor.TextArea.LeftMargins.Insert(0, iconBarMargin);
textView.Services.AddService(typeof(ParserFoldingStrategy), new ParserFoldingStrategy(textEditor.TextArea));
textView.Services.AddService(typeof(ISyntaxHighlighter), new AvalonEditSyntaxHighlighterAdapter(textView));
textEditor.TextArea.TextView.MouseRightButtonDown += textEditor_TextArea_TextView_MouseRightButtonDown;
@ -657,6 +659,22 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -657,6 +659,22 @@ namespace ICSharpCode.AvalonEdit.AddIn
}
}
iconBarManager.UpdateClassMemberBookmarks(parseInfo);
UpdateFolding(primaryTextEditorAdapter, parseInfo);
UpdateFolding(secondaryTextEditorAdapter, parseInfo);
}
void UpdateFolding(ITextEditor editor, ParseInformation parseInfo)
{
if (editor != null) {
ParserFoldingStrategy folding = editor.GetService(typeof(ParserFoldingStrategy)) as ParserFoldingStrategy;
if (folding != null) {
if (parseInfo != null)
folding.Attach();
else
folding.Detach();
folding.UpdateFoldings(parseInfo);
}
}
}
public void Dispose()

134
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ParserFoldingStrategy.cs

@ -0,0 +1,134 @@ @@ -0,0 +1,134 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <author name="Daniel Grunwald"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
namespace ICSharpCode.AvalonEdit.AddIn
{
/// <summary>
/// Uses SharpDevelop.Dom to create parsing information.
/// </summary>
public class ParserFoldingStrategy
{
readonly FoldingManager foldingManager;
TextArea textArea;
FoldingMargin margin;
FoldingElementGenerator generator;
public ParserFoldingStrategy(TextArea textArea)
{
this.textArea = textArea;
foldingManager = new FoldingManager(textArea.TextView, textArea.Document);
margin = new FoldingMargin() { FoldingManager = foldingManager, TextView = textArea.TextView };
generator = new FoldingElementGenerator() { FoldingManager = foldingManager };
}
public bool IsAttached {
get { return textArea.TextView.ElementGenerators.Contains(generator); }
}
public void Attach()
{
if (!IsAttached) {
textArea.LeftMargins.Add(margin);
textArea.TextView.ElementGenerators.Add(generator);
}
}
public void Detach()
{
textArea.LeftMargins.Remove(margin);
textArea.TextView.ElementGenerators.Remove(generator);
}
public void UpdateFoldings(ParseInformation parseInfo)
{
var oldFoldings = foldingManager.AllFoldings.ToArray();
IEnumerable<NewFolding> newFoldings = GetNewFoldings(parseInfo);
int oldFoldingIndex = 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) {
// remove old foldings that were skipped
while (oldFoldingIndex < oldFoldings.Length && newFolding.StartOffset > oldFoldings[oldFoldingIndex].StartOffset) {
foldingManager.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 = foldingManager.CreateFolding(newFolding.StartOffset, newFolding.EndOffset);
}
}
// remove all outstanding old foldings:
while (oldFoldingIndex < oldFoldings.Length) {
foldingManager.RemoveFolding(oldFoldings[oldFoldingIndex++]);
}
}
IEnumerable<NewFolding> GetNewFoldings(ParseInformation parseInfo)
{
List<NewFolding> newFoldMarkers = new List<NewFolding>();
if (parseInfo != null) {
foreach (IClass c in parseInfo.CompilationUnit.Classes) {
AddClassMembers(c, newFoldMarkers);
}
foreach (FoldingRegion foldingRegion in parseInfo.CompilationUnit.FoldingRegions) {
newFoldMarkers.Add(new NewFolding(textArea.Document.GetOffset(foldingRegion.Region.BeginLine, foldingRegion.Region.BeginColumn),
textArea.Document.GetOffset(foldingRegion.Region.EndLine, foldingRegion.Region.EndColumn)));
}
}
return newFoldMarkers.Where(f => f.EndOffset > f.StartOffset).OrderBy(f=>f.StartOffset);
}
void AddClassMembers(IClass c, List<NewFolding> newFoldMarkers)
{
if (c.ClassType == ClassType.Delegate) {
return;
}
DomRegion cRegion = c.BodyRegion;
if (cRegion.IsEmpty)
cRegion = c.Region;
if (cRegion.BeginLine < cRegion.EndLine) {
newFoldMarkers.Add(new NewFolding(textArea.Document.GetOffset(cRegion.BeginLine, cRegion.BeginColumn),
textArea.Document.GetOffset(cRegion.EndLine, cRegion.EndColumn)));
}
foreach (IClass innerClass in c.InnerClasses) {
AddClassMembers(innerClass, newFoldMarkers);
}
foreach (IMember m in c.AllMembers) {
if (m.Region.EndLine < m.BodyRegion.EndLine) {
newFoldMarkers.Add(new NewFolding(textArea.Document.GetOffset(m.Region.EndLine, m.Region.EndColumn),
textArea.Document.GetOffset(m.BodyRegion.EndLine, m.BodyRegion.EndColumn)));
}
}
}
struct NewFolding
{
public readonly int StartOffset, EndOffset;
public NewFolding(int start, int end)
{
Debug.Assert(start < end);
this.StartOffset = start;
this.EndOffset = end;
}
}
}
}

20
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextDocument.cs

@ -610,12 +610,20 @@ namespace ICSharpCode.AvalonEdit.Document @@ -610,12 +610,20 @@ namespace ICSharpCode.AvalonEdit.Document
/// </summary>
public int GetOffset(TextLocation location)
{
DocumentLine line = GetLineByNumber(location.Line);
if (location.Column < 0)
return line.Offset;
if (location.Column > line.Length)
return line.EndOffset;
return line.Offset + location.Column - 1;
return GetOffset(location.Line, location.Column);
}
/// <summary>
/// Gets the offset from a text location.
/// </summary>
public int GetOffset(int line, int column)
{
DocumentLine docLine = GetLineByNumber(line);
if (column < 0)
return docLine.Offset;
if (column > docLine.Length)
return docLine.EndOffset;
return docLine.Offset + column - 1;
}
/// <summary>

30
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/FoldingManager.cs

@ -11,6 +11,7 @@ using System.Collections.ObjectModel; @@ -11,6 +11,7 @@ using System.Collections.ObjectModel;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Rendering;
using System.Windows.Threading;
namespace ICSharpCode.AvalonEdit.Editing
{
@ -51,13 +52,40 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -51,13 +52,40 @@ namespace ICSharpCode.AvalonEdit.Editing
return fs;
}
internal void RemoveFolding(FoldingSection fs)
/// <summary>
/// Removes a folding section from this manager.
/// </summary>
public void RemoveFolding(FoldingSection fs)
{
if (fs == null)
throw new ArgumentNullException("fs");
document.VerifyAccess();
fs.IsFolded = false;
foldings.Remove(fs);
textView.Redraw(fs, DispatcherPriority.Normal);
}
/// <summary>
/// Removes all folding sections.
/// </summary>
public void Clear()
{
document.VerifyAccess();
foreach (FoldingSection s in foldings)
s.IsFolded = false;
foldings.Clear();
textView.Redraw();
}
/// <summary>
/// Gets all foldings in this manager.
/// The foldings are returned sorted by start offset;
/// for multiple foldings at the same offset the order is undefined.
/// </summary>
public IEnumerable<FoldingSection> AllFoldings {
get { return foldings; }
}
/// <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"/>.

26
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/FoldingSection.cs

@ -30,11 +30,13 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -30,11 +30,13 @@ namespace ICSharpCode.AvalonEdit.Editing
if (isFolded != value) {
isFolded = value;
if (value) {
DocumentLine startLine = manager.document.GetLineByOffset(StartOffset);
DocumentLine endLine = manager.document.GetLineByOffset(EndOffset);
if (startLine != endLine) {
DocumentLine startLinePlusOne = startLine.NextLine;
collapsedSection = manager.textView.CollapseLines(startLinePlusOne, endLine);
if (manager != null) {
DocumentLine startLine = manager.document.GetLineByOffset(StartOffset);
DocumentLine endLine = manager.document.GetLineByOffset(EndOffset);
if (startLine != endLine) {
DocumentLine startLinePlusOne = startLine.NextLine;
collapsedSection = manager.textView.CollapseLines(startLinePlusOne, endLine);
}
}
} else {
if (collapsedSection != null) {
@ -42,7 +44,8 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -42,7 +44,8 @@ namespace ICSharpCode.AvalonEdit.Editing
collapsedSection = null;
}
}
manager.textView.Redraw(this, DispatcherPriority.Normal);
if (manager != null)
manager.textView.Redraw(this, DispatcherPriority.Normal);
}
}
}
@ -54,12 +57,13 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -54,12 +57,13 @@ namespace ICSharpCode.AvalonEdit.Editing
this.Length = endOffset - startOffset;
}
/// <summary>
/// Deletes the folding section.
/// </summary>
public void Remove()
internal void Removed()
{
manager.RemoveFolding(this);
if (collapsedSection != null) {
collapsedSection.Uncollapse();
collapsedSection = null;
}
manager = null;
}
}
}

Loading…
Cancel
Save