Browse Source

Extended AvalonEdit.Sample + article.

Fixed FxCop issues in AvalonEdit.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5040 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 16 years ago
parent
commit
c78ea89993
  1. 3
      samples/AvalonEdit.Sample/AvalonEdit.Sample.csproj
  2. BIN
      samples/AvalonEdit.Sample/AvalonEdit/folding.png
  3. 105
      samples/AvalonEdit.Sample/ImageElementGenerator.cs
  4. BIN
      samples/AvalonEdit.Sample/RenderingPipeline.pptx
  5. 27
      samples/AvalonEdit.Sample/Window1.xaml
  6. 80
      samples/AvalonEdit.Sample/Window1.xaml.cs
  7. 128
      samples/AvalonEdit.Sample/article.html
  8. BIN
      samples/AvalonEdit.Sample/renderingPipeline.png
  9. 7
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/DocumentLine.cs
  10. 1
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/LineNode.cs
  11. 4
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextUtilities.cs
  12. 8
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/XmlFoldingStrategy.cs
  13. 1
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightingBrush.cs
  14. 6
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightingManager.cs
  15. 2
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Resources/CPP-Mode.xshd
  16. 2
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Resources/Resources.cs
  17. 2
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Xshd/V2Loader.cs
  18. 2
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
  19. 3
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/LinkElementGenerator.cs
  20. 4
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/TextEditorOptions.cs

3
samples/AvalonEdit.Sample/AvalonEdit.Sample.csproj

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<Project ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<PropertyGroup>
<ProjectGuid>{13A5B497-BA12-45AE-9033-22620C3153FB}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@ -71,6 +71,7 @@ @@ -71,6 +71,7 @@
<SubType>Code</SubType>
<DependentUpon>Window1.xaml</DependentUpon>
</Compile>
<Compile Include="ImageElementGenerator.cs" />
</ItemGroup>
<ItemGroup>
<Page Include="Window1.xaml" />

BIN
samples/AvalonEdit.Sample/AvalonEdit/folding.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

105
samples/AvalonEdit.Sample/ImageElementGenerator.cs

@ -0,0 +1,105 @@ @@ -0,0 +1,105 @@
// Copyright (c) 2009 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Rendering;
namespace AvalonEdit.Sample
{
/// <summary>
/// This class can be used to embed images inside AvalonEdit like this: <img src="Images/Save.png"/>
/// </summary>
public class ImageElementGenerator : VisualLineElementGenerator
{
readonly static Regex imageRegex = new Regex(@"<img src=""([\.\/\w\d]+)""/?>", RegexOptions.IgnoreCase);
readonly string basePath;
public ImageElementGenerator(string basePath)
{
if (basePath == null)
throw new ArgumentNullException("basePath");
this.basePath = basePath;
}
Match FindMatch(int startOffset)
{
// fetch the end offset of the VisualLine being generated
int endOffset = CurrentContext.VisualLine.LastDocumentLine.EndOffset;
string relevantText = CurrentContext.Document.GetText(startOffset, endOffset - startOffset);
return imageRegex.Match(relevantText);
}
/// <summary>
/// Gets the first offset >= startOffset where the generator wants to construct an element.
/// Return -1 to signal no interest.
/// </summary>
public override int GetFirstInterestedOffset(int startOffset)
{
Match m = FindMatch(startOffset);
return m.Success ? (startOffset + m.Index) : -1;
}
/// <summary>
/// Constructs an element at the specified offset.
/// May return null if no element should be constructed.
/// </summary>
public override VisualLineElement ConstructElement(int offset)
{
Match m = FindMatch(offset);
// check whether there's a match exactly at offset
if (m.Success && m.Index == 0) {
BitmapImage bitmap = LoadBitmap(m.Groups[1].Value);
if (bitmap != null) {
Image image = new Image();
image.Source = bitmap;
image.Width = bitmap.PixelWidth;
image.Height = bitmap.PixelHeight;
// Pass the length of the match to the 'documentLength' parameter of InlineObjectElement.
return new InlineObjectElement(m.Length, image);
}
}
return null;
}
BitmapImage LoadBitmap(string fileName)
{
// TODO: add some kind of cache to avoid reloading the image whenever the VisualLine is reconstructed
try {
string fullFileName = Path.Combine(basePath, fileName);
if (File.Exists(fullFileName)) {
BitmapImage bitmap = new BitmapImage(new Uri(fullFileName));
bitmap.Freeze();
return bitmap;
}
} catch (ArgumentException) {
// invalid filename syntax
} catch (IOException) {
// other IO error
}
return null;
}
}
}

BIN
samples/AvalonEdit.Sample/RenderingPipeline.pptx

Binary file not shown.

27
samples/AvalonEdit.Sample/Window1.xaml

@ -1,4 +1,23 @@ @@ -1,4 +1,23 @@
<Window x:Class="AvalonEdit.Sample.Window1"
<!--
Copyright (c) 2009 Daniel Grunwald
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
-->
<Window x:Class="AvalonEdit.Sample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit"
@ -38,7 +57,8 @@ @@ -38,7 +57,8 @@
</CheckBox>
<ComboBox Name="highlightingComboBox"
SelectedItem="{Binding SyntaxHighlighting, ElementName=textEditor}"
ItemsSource="{Binding Source={x:Static avalonEdit:HighlightingManager.Instance}, Path=Highlightings}"/>
ItemsSource="{Binding Source={x:Static avalonEdit:HighlightingManager.Instance}, Path=HighlightingDefinitions}"
SelectionChanged="HighlightingComboBox_SelectionChanged"/>
</ToolBar>
<Grid>
<Grid.ColumnDefinitions>
@ -49,8 +69,7 @@ @@ -49,8 +69,7 @@
Name="textEditor"
FontFamily="Consolas"
FontSize="10pt"
>
Initial Text
>This is AvalonEdit! Embedded image: &lt;img src="Images/Open.png"/&gt;
</avalonEdit:TextEditor>
<GridSplitter Grid.Column="1" Width="4" HorizontalAlignment="Left"/>
<DockPanel Grid.Column="1" Margin="4 0 0 0">

80
samples/AvalonEdit.Sample/Window1.xaml.cs

@ -1,9 +1,20 @@ @@ -1,9 +1,20 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald"/>
// <version>$Revision$</version>
// </file>
// Copyright (c) 2009 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
@ -15,7 +26,9 @@ using System.Windows.Data; @@ -15,7 +26,9 @@ using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using ICSharpCode.AvalonEdit.Folding;
using ICSharpCode.AvalonEdit.Highlighting;
using Microsoft.Win32;
@ -31,10 +44,15 @@ namespace AvalonEdit.Sample @@ -31,10 +44,15 @@ namespace AvalonEdit.Sample
InitializeComponent();
propertyGridComboBox.SelectedIndex = 2;
textEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinitionByExtension(".xml");
//textEditor.TextArea.TextView.ElementGenerators.Add(new WordFilterElementGenerator());
textEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition("C#");
textEditor.TextArea.TextView.ElementGenerators.Add(new ImageElementGenerator(Path.GetFullPath("../..")));
DispatcherTimer foldingUpdateTimer = new DispatcherTimer();
foldingUpdateTimer.Interval = TimeSpan.FromSeconds(2);
foldingUpdateTimer.Tick += foldingUpdateTimer_Tick;
foldingUpdateTimer.Start();
}
string currentFileName;
void openFileClick(object sender, RoutedEventArgs e)
@ -78,5 +96,49 @@ namespace AvalonEdit.Sample @@ -78,5 +96,49 @@ namespace AvalonEdit.Sample
break;
}
}
#region Folding
FoldingManager foldingManager;
AbstractFoldingStrategy foldingStrategy;
void HighlightingComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (textEditor.SyntaxHighlighting == null) {
foldingStrategy = null;
} else {
switch (textEditor.SyntaxHighlighting.Name) {
case "XML":
foldingStrategy = new XmlFoldingStrategy();
break;
case "C#":
case "C++":
case "PHP":
case "Java":
foldingStrategy = new BraceFoldingStrategy();
break;
default:
foldingStrategy = null;
break;
}
}
if (foldingStrategy != null) {
if (foldingManager == null)
foldingManager = FoldingManager.Install(textEditor.TextArea);
foldingStrategy.UpdateFoldings(foldingManager, textEditor.Document);
} else {
if (foldingManager != null) {
FoldingManager.Uninstall(foldingManager);
foldingManager = null;
}
}
}
void foldingUpdateTimer_Tick(object sender, EventArgs e)
{
if (foldingStrategy != null) {
foldingStrategy.UpdateFoldings(foldingManager, textEditor.Document);
}
}
#endregion
}
}

128
samples/AvalonEdit.Sample/article.html

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!--------------------------------------------------------------------------->
<!------------------------------------------------------------>
<!-- INTRODUCTION
The Code Project article submission template (HTML version)
@ -15,7 +15,7 @@ That's all there is to it! All formatting will be done by our submission @@ -15,7 +15,7 @@ That's all there is to it! All formatting will be done by our submission
scripts and style sheets.
-->
<!--------------------------------------------------------------------------->
<!------------------------------------------------------------>
<!-- IGNORE THIS SECTION -->
<html>
<head>
@ -32,14 +32,14 @@ CODE { COLOR: #990000; FONT-FAMILY: "Courier New", Courier, mono; } @@ -32,14 +32,14 @@ CODE { COLOR: #990000; FONT-FAMILY: "Courier New", Courier, mono; }
<link rel="stylesheet" type="text/css" href="http://www.codeproject.com/App_Themes/NetCommunity/CodeProject.css">
</head>
<body bgcolor="#FFFFFF" color=#000000>
<!--------------------------------------------------------------------------->
<!------------------------------------------------------------>
<!------------------------------- STEP 1 --------------------------->
<!------------------------------------------------------------>
<!-- Fill in the details (CodeProject will reformat this section for you) -->
<!------------------------------- STEP 2 --------------------------->
<!------------------------------------------------------------>
<!-- Include download and sample image information. -->
<ul class=download>
@ -50,7 +50,7 @@ CODE { COLOR: #990000; FONT-FAMILY: "Courier New", Courier, mono; } @@ -50,7 +50,7 @@ CODE { COLOR: #990000; FONT-FAMILY: "Courier New", Courier, mono; }
<p><img src="Article.gif" alt="Sample Image - maximum width is 600 pixels" width=400 height=200></p>
<!------------------------------- STEP 3 --------------------------->
<!------------------------------------------------------------>
<!-- Add the article text. Please use simple formatting (<h2>, <p> etc) -->
@ -90,15 +90,17 @@ You can use it just similar to a normal WPF TextBox: @@ -90,15 +90,17 @@ You can use it just similar to a normal WPF TextBox:
<p>To enable syntax highlighting, use:
<pre lang="cs">textEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinitionByExtension(".cs");</pre>
<pre lang="cs">textEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition("C#");</pre>
AvalonEdit has syntax highlighting definitions built in for:
ASP.NET, Batch files, Boo, Coco/R grammars, C++, C#, HTML, Java, JavaScript, Patch files, PHP, TeX, VB.NET, XML
ASP.NET, Boo, Coco/R grammars, C++, C#, HTML, Java, JavaScript, Patch files, PHP, TeX, VB, XML
<p>If you need more of AvalonEdit than a simple text box with syntax highlighting, you will first have to learn more about the architecture of AvalonEdit.
<!------------------------------------------------------------>
<h2>Architecture</h2>
TODO: overview of the namespaces, insert graph from NDepend
<!------------------------------------------------------------>
<h2>Document (The Model)</h2>
<p>So, what is the model of a text editor that has support for complex features like syntax highlighting and folding?<br>
@ -243,7 +245,7 @@ The property <code>TextAnchor.MovementType</code> will be used to determine whic @@ -243,7 +245,7 @@ The property <code>TextAnchor.MovementType</code> will be used to determine whic
<h3>TextSegmentCollection</h3>
<p>Sometimes it is useful to store a list of segments and be able to efficiently find all segments overlapping with some other segment.<br>
Example: you might want to store a large number compiler warnings and render squiggly underlines only those that are in the visible region of the document.
Example: you might want to store a large number compiler warnings and render squiggly underlines only for those that are in the visible region of the document.
<p>The <code>TextSegmentCollection</code> serves this purpose. Connected to a document, it will automatically update the offsets of all TextSegment instances inside the collection;
but it also has the useful methods <code>FindOverlappingSegments</code> and <code>FindFirstSegmentWithStartAfter</code>.
@ -257,6 +259,7 @@ It returns an immutable snapshot of the document. The snapshot is thread-safe, s @@ -257,6 +259,7 @@ It returns an immutable snapshot of the document. The snapshot is thread-safe, s
The overload <code>CreateSnapshot(out ChangeTrackingCheckpoint)</code> also returns a <code>ChangeTrackingCheckpoint</code> for the document snapshot.
Once you have two checkpoints, you can call <code>GetChangesTo</code> to retrieve the complete list of document changes that happened between those versions of the document.
<!------------------------------------------------------------>
<h2>Rendering</h2>
Noticed how through the whole Document section, there was no mention of extensibility?
@ -268,11 +271,112 @@ It takes care of getting the document onto the screen. @@ -268,11 +271,112 @@ It takes care of getting the document onto the screen.
<p>To do this in an extensible way, the TextView uses its own kind of model: the <code>VisualLine</code>.
VisualLines are created only for the visible part of the document.
<p>The creation process looks like this:<br>
<img src="renderingPipeline.png" alt="rendering pipeline">
<img src="AvalonEdit/renderingPipeline.png" alt="rendering pipeline">
<h3>Lifetime of VisualLines</h3>
When the <code>TextView</code> needs to construct VisualLines (usually before rendering), it first
determines which <code>DocumentLine</code> is the top-most visible line in the currently viewed region.
From there, it starts to build <code>VisualLine</code>s and also immediately does the conversion to <code>TextLine</code> (word-wrapping).
The process stops once the viewed document region is filled.
<p>
The resulting <code>VisualLine</code>s (and <code>TextLine</code>s) will be cached and reused in future rendering passes.
When the user scrolls down, only the VisualLines coming into view are created, the rest is reused.
<p>
The <code>TextView.Redraw</code> methods are used to remove <code>VisualLine</code>s from the cache.
AvalonEdit calls <code>Redraw</code> automatically on the affected lines when the document is changed; and will invalidate the whole cache
when any editor options are changed. You will only have to call <code>Redraw</code> manually if you write extensions to the VisualLine creation process
that maintain their own data source. For example, the <code>FoldingManager</code> is calling <code>Redraw</code> when text sections are expanded or collapsed.
<p>
Calling <code>Redraw</code> does not cause immediate recreation of the lines.
They are just removed from the cache so that the next rendering step will recreate them.
All <code>Redraw</code> methods will trigger a new rendering step, but they will delay it using the WPF Dispatcher using a low priority.
<h3>Element Generators</h3>
You can extend the text view by registering a custom class deriving from <code>VisualLineElementGenerator</code> in the <code>TextView.ElementGenerators</code> collection.
This allows you to add custom VisualLineElements.
Using the <code>InlineObjectElement</code> class, you can even put interactive WPF controls into the text document.
<p>
For all document text not consumed by element generators, AvalonEdit will create <code>VisualLineText</code> elements.
<p>
Usually, the construction of the <code>VisualLine</code> will stop at the end of the <code>DocumentLine</code>. However, if some <code>VisualLineElementGenerator</code>
creates an element that's longer than the rest of the line, construction of the <code>VisualLine</code> may resume in another <code>DocumentLine</code>.
Currently, only the <code>FoldingElementGenerator</code> can cause one <code>VisualLine</code> to span multiple <code>DocumentLine</code>s.
<p>
<img src="AvalonEdit/folding.png" alt="Screenshot Folding and ImageElementGenerator">
<p>
Here is the full source code for a class that implements embedding images into AvalonEdit:
<pre lang="cs">public class ImageElementGenerator : VisualLineElementGenerator
{
readonly static Regex imageRegex = new Regex(@"&lt;img src=""([\.\/\w\d]+)""/?>", RegexOptions.IgnoreCase);
readonly string basePath;
public ImageElementGenerator(string basePath)
{
if (basePath == null)
throw new ArgumentNullException("basePath");
this.basePath = basePath;
}
Match FindMatch(int startOffset)
{
// fetch the end offset of the VisualLine being generated
int endOffset = CurrentContext.VisualLine.LastDocumentLine.EndOffset;
string relevantText = CurrentContext.Document.GetText(startOffset, endOffset - startOffset);
return imageRegex.Match(relevantText);
}
// Gets the first offset >= startOffset where the generator wants to construct an element.
// Return -1 to signal no interest.
public override int GetFirstInterestedOffset(int startOffset)
{
Match m = FindMatch(startOffset);
return m.Success ? (startOffset + m.Index) : -1;
}
// Constructs an element at the specified offset.
// May return null if no element should be constructed.
public override VisualLineElement ConstructElement(int offset)
{
Match m = FindMatch(offset);
// check whether there's a match exactly at offset
if (m.Success &amp;&amp; m.Index == 0) {
BitmapImage bitmap = LoadBitmap(m.Groups[1].Value);
if (bitmap != null) {
Image image = new Image();
image.Source = bitmap;
image.Width = bitmap.PixelWidth;
image.Height = bitmap.PixelHeight;
// Pass the length of the match to the 'documentLength' parameter of InlineObjectElement.
return new InlineObjectElement(m.Length, image);
}
}
return null;
}
BitmapImage LoadBitmap(string fileName)
{
// TODO: add some kind of cache to avoid reloading the image whenever the VisualLine is reconstructed
try {
string fullFileName = Path.Combine(basePath, fileName);
if (File.Exists(fullFileName)) {
BitmapImage bitmap = new BitmapImage(new Uri(fullFileName));
bitmap.Freeze();
return bitmap;
}
} catch (ArgumentException) {
// invalid filename syntax
} catch (IOException) {
// other IO error
}
return null;
}
}</pre>
<h2>Editing</h2>
TODO: write this section
The <code>TextArea</code> class is handling user input and executing the appropriate actions.
Both the caret and the selection are controlled by the <code>TextArea</code>.
<h2>Points of Interest</h2>
@ -283,7 +387,7 @@ do anything particularly clever or wild or zany? @@ -283,7 +387,7 @@ do anything particularly clever or wild or zany?
<p>Keep a running update of any changes or improvements you've made here.
<p><b>Note: although my sample code is provided under the BSD license, ICSharpCode.AvalonEdit itself is provided under the terms of the GNU LGPL.</b>
<p><b>Note: although my sample code is provided under the MIT license, ICSharpCode.AvalonEdit itself is provided under the terms of the GNU LGPL.</b>
<!------------------------------- That's it! --------------------------->
</body>

BIN
samples/AvalonEdit.Sample/renderingPipeline.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

7
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/DocumentLine.cs

@ -32,7 +32,8 @@ namespace ICSharpCode.AvalonEdit.Document @@ -32,7 +32,8 @@ namespace ICSharpCode.AvalonEdit.Document
/// Gets the text document that owns this DocumentLine. O(1).
/// </summary>
/// <remarks>This property is still available even if the line was deleted.</remarks>
[ObsoleteAttribute("Supporting this property causes DocumentLine to use more memory than otherwise necessary. It will be removed in a future AvalonEdit version.")]
[ObsoleteAttribute("Supporting this property causes DocumentLine to use more memory than otherwise necessary. " +
"It will be removed in a future AvalonEdit version.")]
public TextDocument Document {
get {
document.DebugVerifyAccess();
@ -45,7 +46,9 @@ namespace ICSharpCode.AvalonEdit.Document @@ -45,7 +46,9 @@ namespace ICSharpCode.AvalonEdit.Document
/// Gets the text on this line.
/// </summary>
/// <exception cref="InvalidOperationException">The line was deleted.</exception>
[ObsoleteAttribute("Supporting this property causes DocumentLine to use more memory than otherwise necessary. It will be removed in a future AvalonEdit version.")]
[ObsoleteAttribute("Supporting this property causes DocumentLine to use more memory than otherwise necessary. " +
"It will be removed in a future AvalonEdit version. " +
"Use 'document.GetText(documentLine)' instead.")]
public string Text {
get {
return document.GetText(this.Offset, this.Length);

1
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/LineNode.cs

@ -34,6 +34,7 @@ namespace ICSharpCode.AvalonEdit.Document @@ -34,6 +34,7 @@ namespace ICSharpCode.AvalonEdit.Document
// TODO: a possible optimization would be to combine 'totalLength' and the small fields into a single uint.
// delimiterSize takes only two bits, the two bools take another two bits; so there's still
// 28 bits left for totalLength. 268435455 characters per line should be enough for everyone :)
// TODO: remove the 'document' pointer in release builds
/// <summary>
/// Resets the line to enable its reuse after a document rebuild.

4
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextUtilities.cs

@ -136,6 +136,8 @@ namespace ICSharpCode.AvalonEdit.Document @@ -136,6 +136,8 @@ namespace ICSharpCode.AvalonEdit.Document
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "Whitespace",
Justification = "WPF uses 'Whitespace'")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters",
Justification = "Parameter cannot be ITextSource because it must belong to the DocumentLine")]
public static ISegment GetLeadingWhitespace(TextDocument document, DocumentLine documentLine)
{
if (documentLine == null)
@ -159,6 +161,8 @@ namespace ICSharpCode.AvalonEdit.Document @@ -159,6 +161,8 @@ namespace ICSharpCode.AvalonEdit.Document
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "Whitespace",
Justification = "WPF uses 'Whitespace'")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters",
Justification = "Parameter cannot be ITextSource because it must belong to the DocumentLine")]
public static ISegment GetTrailingWhitespace(TextDocument document, DocumentLine documentLine)
{
if (documentLine == null)

8
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/XmlFoldingStrategy.cs

@ -85,7 +85,7 @@ namespace ICSharpCode.AvalonEdit.Folding @@ -85,7 +85,7 @@ namespace ICSharpCode.AvalonEdit.Folding
return foldMarkers;
}
int GetOffset(TextDocument document, XmlReader reader)
static int GetOffset(TextDocument document, XmlReader reader)
{
IXmlLineInfo info = reader as IXmlLineInfo;
if (info != null && info.HasLineInfo()) {
@ -100,7 +100,7 @@ namespace ICSharpCode.AvalonEdit.Folding @@ -100,7 +100,7 @@ namespace ICSharpCode.AvalonEdit.Folding
/// </summary>
/// <remarks>The text displayed when the comment is folded is the first
/// line of the comment.</remarks>
void CreateCommentFold(TextDocument document, List<NewFolding> foldMarkers, XmlReader reader)
static void CreateCommentFold(TextDocument document, List<NewFolding> foldMarkers, XmlReader reader)
{
string comment = reader.Value;
if (comment != null) {
@ -148,7 +148,7 @@ namespace ICSharpCode.AvalonEdit.Folding @@ -148,7 +148,7 @@ namespace ICSharpCode.AvalonEdit.Folding
/// Create an element fold if the start and end tag are on
/// different lines.
/// </summary>
void CreateElementFold(TextDocument document, List<NewFolding> foldMarkers, XmlReader reader, XmlFoldStart foldStart)
static void CreateElementFold(TextDocument document, List<NewFolding> foldMarkers, XmlReader reader, XmlFoldStart foldStart)
{
IXmlLineInfo lineInfo = (IXmlLineInfo)reader;
int endLine = lineInfo.LineNumber;
@ -168,7 +168,7 @@ namespace ICSharpCode.AvalonEdit.Folding @@ -168,7 +168,7 @@ namespace ICSharpCode.AvalonEdit.Folding
/// line of the start tag. It does not cater for elements where attributes
/// are not on the same line as the start tag.
/// </remarks>
string GetAttributeFoldText(XmlReader reader)
static string GetAttributeFoldText(XmlReader reader)
{
StringBuilder text = new StringBuilder();

1
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightingBrush.cs

@ -92,6 +92,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting @@ -92,6 +92,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting
public SystemColorHighlightingBrush(PropertyInfo property)
{
Debug.Assert(property.ReflectedType == typeof(SystemColors));
Debug.Assert(typeof(Brush).IsAssignableFrom(property.PropertyType));
this.property = property;
}

6
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightingManager.cs

@ -47,6 +47,8 @@ namespace ICSharpCode.AvalonEdit.Highlighting @@ -47,6 +47,8 @@ namespace ICSharpCode.AvalonEdit.Highlighting
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
Justification = "The exception will be rethrown")]
IHighlightingDefinition GetDefinition()
{
Func<IHighlightingDefinition> func;
@ -125,7 +127,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting @@ -125,7 +127,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting
/// <summary>
/// Gets a copy of all highlightings.
/// </summary>
public ReadOnlyCollection<IHighlightingDefinition> Highlightings {
public ReadOnlyCollection<IHighlightingDefinition> HighlightingDefinitions {
get {
lock (lockObj) {
return Array.AsReadOnly(allHighlightings.ToArray());
@ -136,7 +138,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting @@ -136,7 +138,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting
/// <summary>
/// Gets the names of the registered highlightings.
/// </summary>
[ObsoleteAttribute("Use the Highlightings property instead.")]
[ObsoleteAttribute("Use the HighlightingDefinitions property instead.")]
public IEnumerable<string> HighlightingNames {
get {
lock (lockObj) {

2
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Resources/CPP-Mode.xshd

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
<!-- syntaxdefinition for C/C++ 2001 by Andrea Paatz and Mike Krueger
this should be rewritten to xshd v2.0 syntax to handle c++/cli keywords with whitespaces properly -->
<SyntaxDefinition name = "C++.NET" extensions = ".c;.h;.cc;.cpp;.hpp">
<SyntaxDefinition name = "C++" extensions = ".c;.h;.cc;.cpp;.hpp">
<Properties>
<Property name="LineComment" value="//"/>

2
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Resources/Resources.cs

@ -33,7 +33,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting @@ -33,7 +33,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting
hlm.RegisterHighlighting("Boo", new[] { ".boo" }, "Boo.xshd");
hlm.RegisterHighlighting("Coco", new[] { ".atg" }, "Coco-Mode.xshd");
hlm.RegisterHighlighting("C++.NET", new[] { ".c", ".h", ".cc", ".cpp" , ".hpp" }, "CPP-Mode.xshd");
hlm.RegisterHighlighting("C++", new[] { ".c", ".h", ".cc", ".cpp" , ".hpp" }, "CPP-Mode.xshd");
hlm.RegisterHighlighting("Java", new[] { ".java" }, "Java-Mode.xshd");
hlm.RegisterHighlighting("Patch", new[] { ".patch", ".diff" }, "Patch-Mode.xshd");
hlm.RegisterHighlighting("PHP", new[] { ".php" }, "PHP-Mode.xshd");

2
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Xshd/V2Loader.cs

@ -285,7 +285,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting.Xshd @@ -285,7 +285,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting.Xshd
{
Debug.Assert(name.StartsWith("SystemColors.", StringComparison.Ordinal));
string shortName = name.Substring(13);
var property = typeof(SystemColors).GetProperty(shortName + "BrushKey");
var property = typeof(SystemColors).GetProperty(shortName + "Brush");
if (property == null)
throw Error(lineInfo, "Cannot find '" + name + "'.");
return new SystemColorHighlightingBrush(property);

2
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>

3
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/LinkElementGenerator.cs

@ -71,8 +71,7 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -71,8 +71,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
Match GetMatch(int startOffset)
{
DocumentLine endLine = CurrentContext.VisualLine.LastDocumentLine;
int endOffset = endLine.Offset + endLine.Length;
int endOffset = CurrentContext.VisualLine.LastDocumentLine.EndOffset;
string relevantText = CurrentContext.Document.GetText(startOffset, endOffset - startOffset);
return linkRegex.Match(relevantText);
}

4
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/TextEditorOptions.cs

@ -183,6 +183,10 @@ namespace ICSharpCode.AvalonEdit @@ -183,6 +183,10 @@ namespace ICSharpCode.AvalonEdit
set {
if (value < 1)
throw new ArgumentOutOfRangeException("value", value, "value must be positive");
// sanity check; a too large value might cause WPF to crash internally much later
// (it only crashed in the hundred thousands for me; but might crash earlier with larger fonts)
if (value > 1000)
throw new ArgumentOutOfRangeException("value", value, "indentation size is too large");
if (_indentationSize != value) {
_indentationSize = value;
OnPropertyChanged("IndentationSize");

Loading…
Cancel
Save