Browse Source

Move folding code to separate namespace ICSharpCode.AvalonEdit.Folding.

Add TextEditor.ShowLineNumbers property to show/hide the line numbers (they now are hidden by default).
Add TextEditor.Options.ShowEndOfLine property to allow easily enabling end-of-line markers.
Changed AbstractMargin so that it automatically detects the TextView it is attached to.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4906 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 16 years ago
parent
commit
867dab1f32
  1. 4
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs
  2. 4
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ParserFoldingStrategy.cs
  3. 30
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/AbstractMargin.cs
  4. 1
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/CaretWeakEventHandler.cs
  5. 49
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/DottedLineMargin.cs
  6. 39
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/LineNumberMargin.cs
  7. 28
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextArea.cs
  8. 2
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingElementGenerator.cs
  9. 14
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingManager.cs
  10. 6
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingMargin.cs
  11. 2
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingMarginMarker.cs
  12. 2
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingSection.cs
  13. 20
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
  14. 4
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/ColorizingTransformer.cs
  15. 8
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/SingleCharacterElementGenerator.cs
  16. 21
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs
  17. 70
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/TextEditor.cs
  18. 25
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/TextEditorOptions.cs

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

@ -170,6 +170,7 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -170,6 +170,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
textEditor.Background = Brushes.White;
textEditor.FontFamily = new FontFamily("Consolas");
textEditor.FontSize = 13;
textEditor.ShowLineNumbers = true;
textEditor.TextArea.TextEntering += TextAreaTextEntering;
textEditor.TextArea.TextEntered += TextAreaTextEntered;
textEditor.TextArea.Caret.PositionChanged += TextAreaCaretPositionChanged;
@ -181,8 +182,7 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -181,8 +182,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
textView.Services.AddService(typeof(ITextMarkerService), textMarkerService);
textView.Services.AddService(typeof(IBookmarkMargin), iconBarManager);
var iconBarMargin = new IconBarMargin(iconBarManager) { TextView = textView };
textEditor.TextArea.LeftMargins.Insert(0, iconBarMargin);
textEditor.TextArea.LeftMargins.Insert(0, new IconBarMargin(iconBarManager));
textView.Services.AddService(typeof(ParserFoldingStrategy), new ParserFoldingStrategy(textEditor.TextArea));

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

@ -11,7 +11,7 @@ using System.Diagnostics; @@ -11,7 +11,7 @@ using System.Diagnostics;
using System.Linq;
using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.SharpDevelop;
using ICSharpCode.AvalonEdit.Folding;
using ICSharpCode.SharpDevelop.Dom;
namespace ICSharpCode.AvalonEdit.AddIn
@ -32,7 +32,7 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -32,7 +32,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
this.textArea = textArea;
foldingManager = new FoldingManager(textArea.TextView, textArea.Document);
foldingManager.ExpandFoldingsWhenCaretIsMovedIntoThem(textArea.Caret);
margin = new FoldingMargin() { FoldingManager = foldingManager, TextView = textArea.TextView };
margin = new FoldingMargin() { FoldingManager = foldingManager };
generator = new FoldingElementGenerator() { FoldingManager = foldingManager };
textArea.LeftMargins.Add(margin);
textArea.TextView.ElementGenerators.Add(generator);

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

@ -6,7 +6,9 @@ @@ -6,7 +6,9 @@
// </file>
using System;
using System.Diagnostics;
using System.Windows;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Rendering;
@ -19,7 +21,7 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -19,7 +21,7 @@ namespace ICSharpCode.AvalonEdit.Editing
/// AbstractMargin derives from FrameworkElement, so if you don't want to handle visual children and rendering
/// on your own, choose another base class for your margin!
/// </summary>
public abstract class AbstractMargin : FrameworkElement
public abstract class AbstractMargin : FrameworkElement, ITextViewConnect
{
/// <summary>
/// TextView property.
@ -31,6 +33,7 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -31,6 +33,7 @@ namespace ICSharpCode.AvalonEdit.Editing
/// <summary>
/// Gets/sets the text view for which line numbers are displayed.
/// </summary>
/// <remarks>Adding a margin to <see cref="TextArea.LeftMargins"/> will automatically set this property to the text area's TextView.</remarks>
public TextView TextView {
get { return (TextView)GetValue(TextViewProperty); }
set { SetValue(TextViewProperty, value); }
@ -38,7 +41,30 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -38,7 +41,30 @@ namespace ICSharpCode.AvalonEdit.Editing
static void OnTextViewChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
{
((AbstractMargin)dp).OnTextViewChanged((TextView)e.OldValue, (TextView)e.NewValue);
AbstractMargin margin = (AbstractMargin)dp;
margin.wasAutoAddedToTextView = false;
margin.OnTextViewChanged((TextView)e.OldValue, (TextView)e.NewValue);
}
// automatically set/unset TextView property using ITextViewConnect
bool wasAutoAddedToTextView;
void ITextViewConnect.AddToTextView(TextView textView)
{
if (this.TextView == null) {
this.TextView = textView;
wasAutoAddedToTextView = true;
} else if (this.TextView != textView) {
throw new InvalidOperationException("This margin belongs to a different TextView.");
}
}
void ITextViewConnect.RemoveFromTextView(TextView textView)
{
if (wasAutoAddedToTextView && this.TextView == textView) {
this.TextView = null;
Debug.Assert(!wasAutoAddedToTextView); // setting this.TextView should have unset this flag
}
}
TextDocument document;

1
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/CaretWeakEventHandler.cs

@ -19,6 +19,7 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -19,6 +19,7 @@ namespace ICSharpCode.AvalonEdit.Editing
/// <summary>
/// Handles the Caret.PositionChanged event.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
public sealed class PositionChanged : WeakEventManagerBase<PositionChanged, Caret>
{
/// <inheritdoc/>

49
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/DottedLineMargin.cs

@ -0,0 +1,49 @@ @@ -0,0 +1,49 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
namespace ICSharpCode.AvalonEdit.Editing
{
/// <summary>
/// Margin for use with the text area.
/// A vertical dotted line to separate the line numbers from the text view.
/// </summary>
public static class DottedLineMargin
{
static readonly object tag = new object();
/// <summary>
/// Creates a vertical dotted line to separate the line numbers from the text view.
/// </summary>
public static UIElement Create()
{
return new Line {
X1 = 0, Y1 = 0, X2 = 0, Y2 = 1,
StrokeDashArray = { 0, 2 },
Stretch = Stretch.Fill,
Stroke = Brushes.Gray,
StrokeThickness = 1,
StrokeDashCap = PenLineCap.Round,
Margin = new Thickness(2, 0, 2, 0),
Tag = tag
};
}
/// <summary>
/// Gets whether the specified UIElement is the result of a DottedLineMargin.Create call.
/// </summary>
public static bool IsDottedLineMargin(UIElement element)
{
Line l = element as Line;
return l != null && l.Tag == tag;
}
}
}

39
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/LineNumberMargin.cs

@ -30,19 +30,7 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -30,19 +30,7 @@ namespace ICSharpCode.AvalonEdit.Editing
new FrameworkPropertyMetadata(typeof(LineNumberMargin)));
}
/// <summary>
/// TextArea property.
/// </summary>
public static readonly DependencyProperty TextAreaProperty =
DependencyProperty.Register("TextArea", typeof(TextArea), typeof(LineNumberMargin));
/// <summary>
/// Gets/sets the text area in which text should be selected.
/// </summary>
public TextArea TextArea {
get { return (TextArea)GetValue(TextAreaProperty); }
set { SetValue(TextAreaProperty, value); }
}
TextArea textArea;
Typeface typeface;
double emSize;
@ -94,6 +82,11 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -94,6 +82,11 @@ namespace ICSharpCode.AvalonEdit.Editing
base.OnTextViewChanged(oldTextView, newTextView);
if (newTextView != null) {
newTextView.VisualLinesChanged += TextViewVisualLinesChanged;
// find the text area belonging to the new text view
textArea = newTextView.Services.GetService(typeof(TextArea)) as TextArea;
} else {
textArea = null;
}
InvalidateVisual();
}
@ -156,23 +149,23 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -156,23 +149,23 @@ namespace ICSharpCode.AvalonEdit.Editing
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
if (!e.Handled && TextView != null && TextArea != null) {
if (!e.Handled && TextView != null && textArea != null) {
e.Handled = true;
TextArea.Focus();
textArea.Focus();
SimpleSegment currentSeg = GetTextLineSegment(e);
if (currentSeg == SimpleSegment.Invalid)
return;
TextArea.Caret.Offset = currentSeg.Offset + currentSeg.Length;
textArea.Caret.Offset = currentSeg.Offset + currentSeg.Length;
if (CaptureMouse()) {
selecting = true;
selectionStart = new AnchorSegment(Document, currentSeg.Offset, currentSeg.Length);
if ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift) {
SimpleSelection simpleSelection = TextArea.Selection as SimpleSelection;
SimpleSelection simpleSelection = textArea.Selection as SimpleSelection;
if (simpleSelection != null)
selectionStart = new AnchorSegment(Document, simpleSelection);
}
TextArea.Selection = new SimpleSelection(selectionStart);
textArea.Selection = new SimpleSelection(selectionStart);
if ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift) {
ExtendSelection(currentSeg);
}
@ -202,18 +195,18 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -202,18 +195,18 @@ namespace ICSharpCode.AvalonEdit.Editing
void ExtendSelection(SimpleSegment currentSeg)
{
if (currentSeg.Offset < selectionStart.Offset) {
TextArea.Caret.Offset = currentSeg.Offset;
TextArea.Selection = new SimpleSelection(currentSeg.Offset, selectionStart.Offset + selectionStart.Length);
textArea.Caret.Offset = currentSeg.Offset;
textArea.Selection = new SimpleSelection(currentSeg.Offset, selectionStart.Offset + selectionStart.Length);
} else {
TextArea.Caret.Offset = currentSeg.Offset + currentSeg.Length;
TextArea.Selection = new SimpleSelection(selectionStart.Offset, currentSeg.Offset + currentSeg.Length);
textArea.Caret.Offset = currentSeg.Offset + currentSeg.Length;
textArea.Selection = new SimpleSelection(selectionStart.Offset, currentSeg.Offset + currentSeg.Length);
}
}
/// <inheritdoc/>
protected override void OnMouseMove(MouseEventArgs e)
{
if (selecting && TextArea != null && TextView != null) {
if (selecting && textArea != null && TextView != null) {
e.Handled = true;
SimpleSegment currentSeg = GetTextLineSegment(e);
if (currentSeg == SimpleSegment.Invalid)

28
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextArea.cs

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
@ -65,23 +66,14 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -65,23 +66,14 @@ namespace ICSharpCode.AvalonEdit.Editing
textView.Services.AddService(typeof(TextArea), this);
leftMargins.Add(new LineNumberMargin { TextView = textView, TextArea = this } );
leftMargins.Add(new Line {
X1 = 0, Y1 = 0, X2 = 0, Y2 = 1,
StrokeDashArray = { 0, 2 },
Stretch = Stretch.Fill,
Stroke = Brushes.Gray,
StrokeThickness = 1,
StrokeDashCap = PenLineCap.Round,
Margin = new Thickness(2, 0, 2, 0)
});
textView.LineTransformers.Add(new SelectionColorizer(this));
textView.InsertLayer(new SelectionLayer(this), KnownLayer.Selection, LayerInsertionPosition.Replace);
caret = new Caret(this);
caret.PositionChanged += (sender, e) => RequestSelectionValidation();
leftMargins.CollectionChanged += leftMargins_CollectionChanged;
this.DefaultInputHandler = new TextAreaDefaultInputHandler(this);
this.ActiveInputHandler = this.DefaultInputHandler;
}
@ -411,6 +403,20 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -411,6 +403,20 @@ namespace ICSharpCode.AvalonEdit.Editing
}
}
void leftMargins_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.OldItems != null) {
foreach (ITextViewConnect c in e.OldItems.OfType<ITextViewConnect>()) {
c.RemoveFromTextView(textView);
}
}
if (e.NewItems != null) {
foreach (ITextViewConnect c in e.NewItems.OfType<ITextViewConnect>()) {
c.AddToTextView(textView);
}
}
}
IReadOnlySectionProvider readOnlySectionProvider = NoReadOnlySections.Instance;
/// <summary>

2
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/FoldingElementGenerator.cs → src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingElementGenerator.cs

@ -12,7 +12,7 @@ using System.Windows.Media.TextFormatting; @@ -12,7 +12,7 @@ using System.Windows.Media.TextFormatting;
using ICSharpCode.AvalonEdit.Rendering;
namespace ICSharpCode.AvalonEdit.Editing
namespace ICSharpCode.AvalonEdit.Folding
{
/// <summary>
/// A <see cref="VisualLineElementGenerator"/> that produces line elements for folded <see cref="FoldingSection"/>s.

14
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/FoldingManager.cs → src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingManager.cs

@ -12,9 +12,11 @@ using System.Windows; @@ -12,9 +12,11 @@ using System.Windows;
using System.Windows.Threading;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.AvalonEdit.Utils;
namespace ICSharpCode.AvalonEdit.Editing
namespace ICSharpCode.AvalonEdit.Folding
{
/// <summary>
/// Stores a list of foldings for a specific TextView and TextDocument.
@ -26,6 +28,14 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -26,6 +28,14 @@ namespace ICSharpCode.AvalonEdit.Editing
readonly TextSegmentCollection<FoldingSection> foldings;
/// <summary>
/// Creates a new FoldingManager instance.
/// </summary>
public FoldingManager(TextView textView)
: this(textView, ThrowUtil.CheckNotNull(textView, "textView").Document)
{
}
/// <summary>
/// Creates a new FoldingManager instance.
/// </summary>
@ -40,6 +50,7 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -40,6 +50,7 @@ namespace ICSharpCode.AvalonEdit.Editing
this.foldings = new TextSegmentCollection<FoldingSection>(document);
}
#region ExpandFoldingsWhenCaretIsMovedIntoThem
// keep a reference to the helper as long as the folding manager exists
ExpandFoldingsWhenCaretIsMovedIntoThemHelper helper;
@ -78,6 +89,7 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -78,6 +89,7 @@ namespace ICSharpCode.AvalonEdit.Editing
return false;
}
}
#endregion
/// <summary>
/// Creates a folding for the specified text section.

6
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/FoldingMargin.cs → src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingMargin.cs

@ -13,11 +13,11 @@ using System.Windows.Controls; @@ -13,11 +13,11 @@ using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.TextFormatting;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.AvalonEdit.Utils;
namespace ICSharpCode.AvalonEdit.Editing
namespace ICSharpCode.AvalonEdit.Folding
{
/// <summary>
/// A margin that shows markers for foldings and allows to expand/collapse the foldings.
@ -124,7 +124,7 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -124,7 +124,7 @@ namespace ICSharpCode.AvalonEdit.Editing
/// <inheritdoc/>
protected override void OnRender(DrawingContext drawingContext)
{
if (!TextView.VisualLinesValid)
if (TextView == null || !TextView.VisualLinesValid)
return;
if (TextView.VisualLines.Count == 0 || FoldingManager == null)
return;

2
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/FoldingMarginMarker.cs → src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingMarginMarker.cs

@ -13,7 +13,7 @@ using System.Windows.Media; @@ -13,7 +13,7 @@ using System.Windows.Media;
using ICSharpCode.AvalonEdit.Rendering;
namespace ICSharpCode.AvalonEdit.Editing
namespace ICSharpCode.AvalonEdit.Folding
{
sealed class FoldingMarginMarker : UIElement
{

2
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/FoldingSection.cs → src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingSection.cs

@ -10,7 +10,7 @@ using System.Windows.Threading; @@ -10,7 +10,7 @@ using System.Windows.Threading;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Rendering;
namespace ICSharpCode.AvalonEdit.Editing
namespace ICSharpCode.AvalonEdit.Folding
{
/// <summary>
/// A section that can be folded.

20
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj

@ -132,21 +132,14 @@ @@ -132,21 +132,14 @@
<Compile Include="Editing\CaretNavigationCommandHandler.cs">
</Compile>
<Compile Include="Editing\CaretWeakEventHandler.cs" />
<Compile Include="Editing\DottedLineMargin.cs" />
<Compile Include="Editing\DragDropException.cs" />
<Compile Include="Editing\EditingCommandHandler.cs" />
<Compile Include="Editing\FoldingElementGenerator.cs">
<DependentUpon>FoldingManager.cs</DependentUpon>
</Compile>
<Compile Include="Editing\FoldingManager.cs" />
<Compile Include="Editing\FoldingMargin.cs">
<DependentUpon>FoldingManager.cs</DependentUpon>
</Compile>
<Compile Include="Editing\FoldingMarginMarker.cs">
<DependentUpon>FoldingManager.cs</DependentUpon>
</Compile>
<Compile Include="Editing\FoldingSection.cs">
<DependentUpon>FoldingManager.cs</DependentUpon>
</Compile>
<Compile Include="Folding\FoldingElementGenerator.cs" />
<Compile Include="Folding\FoldingManager.cs" />
<Compile Include="Folding\FoldingMargin.cs" />
<Compile Include="Folding\FoldingMarginMarker.cs" />
<Compile Include="Folding\FoldingSection.cs" />
<Compile Include="Editing\IReadOnlySectionProvider.cs" />
<Compile Include="Editing\LineNumberMargin.cs" />
<Compile Include="Editing\NoReadOnlySections.cs">
@ -379,6 +372,7 @@ @@ -379,6 +372,7 @@
<ItemGroup>
<Folder Include="Document" />
<Folder Include="documentation" />
<Folder Include="Folding" />
<Folder Include="Highlighting" />
<Folder Include="Highlighting\Xshd" />
<Folder Include="Highlighting\Resources" />

4
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/ColorizingTransformer.cs

@ -78,13 +78,13 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -78,13 +78,13 @@ namespace ICSharpCode.AvalonEdit.Rendering
}
}
/// <summary>
/// <summary>
/// Called when added to a text view.
/// </summary>
protected virtual void OnAddToTextView(TextView textView)
{
}
/// <summary>
/// Called when removed from a text view.
/// </summary>

8
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/SingleCharacterElementGenerator.cs

@ -17,8 +17,12 @@ using ICSharpCode.AvalonEdit.Utils; @@ -17,8 +17,12 @@ using ICSharpCode.AvalonEdit.Utils;
namespace ICSharpCode.AvalonEdit.Rendering
{
/// <summary>
/// Element generator that displays · for spaces and » for tabs and a box for control characeters.
/// Element generator that displays · for spaces and » for tabs and a box for control characters.
/// </summary>
/// <remarks>
/// This element generator is present in every TextView by default; the enabled features can be configured using the
/// <see cref="TextEditorOptions"/>.
/// </remarks>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "Whitespace")]
public class SingleCharacterElementGenerator : VisualLineElementGenerator, IWeakEventListener
{
@ -38,7 +42,7 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -38,7 +42,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
public bool ShowBoxForControlCharacters { get; set; }
/// <summary>
/// Creates a new WhitespaceElementGenerator instance.
/// Creates a new SingleCharacterElementGenerator instance.
/// </summary>
public SingleCharacterElementGenerator()
{

21
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs

@ -172,6 +172,7 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -172,6 +172,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
if (OptionChanged != null) {
OptionChanged(this, e);
}
UpdateNewlineVisibilityFromOptions();
Redraw();
}
@ -234,6 +235,22 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -234,6 +235,22 @@ namespace ICSharpCode.AvalonEdit.Rendering
DisconnectFromTextView(lineTransformer);
Redraw();
}
NewLineElementGenerator newLineElementGenerator;
void UpdateNewlineVisibilityFromOptions()
{
bool hasNewlineGenerator = newLineElementGenerator != null;
if (hasNewlineGenerator != Options.ShowEndOfLine) {
if (Options.ShowEndOfLine) {
newLineElementGenerator = new NewLineElementGenerator();
this.ElementGenerators.Add(newLineElementGenerator);
} else {
this.ElementGenerators.Remove(newLineElementGenerator);
newLineElementGenerator = null;
}
}
}
#endregion
#region Layers
@ -371,6 +388,8 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -371,6 +388,8 @@ namespace ICSharpCode.AvalonEdit.Rendering
/// This method does not invalidate visual lines;
/// use the <see cref="Redraw()"/> method to do that.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "knownLayer",
Justification="This method is meant to invalidate only a specific layer - I just haven't figured out how to do that, yet.")]
public void InvalidateLayer(KnownLayer knownLayer)
{
InvalidateMeasure(DispatcherPriority.Normal);
@ -1448,7 +1467,7 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -1448,7 +1467,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
/// <see cref="VisualLineElementGenerator"/>s that cause <see cref="VisualLine"/>s to span
/// multiple <see cref="DocumentLine"/>s. Do not call it without providing a corresponding
/// <see cref="VisualLineElementGenerator"/>.
/// If you want to create collapsible text sections, see <see cref="Editing.FoldingManager"/>.
/// If you want to create collapsible text sections, see <see cref="Folding.FoldingManager"/>.
/// </summary>
public CollapsedLineSection CollapseLines(DocumentLine start, DocumentLine end)
{

70
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/TextEditor.cs

@ -31,6 +31,7 @@ namespace ICSharpCode.AvalonEdit @@ -31,6 +31,7 @@ namespace ICSharpCode.AvalonEdit
[Localizability(LocalizationCategory.Text), ContentProperty("Text")]
public class TextEditor : Control, ITextEditorComponent, IServiceProvider, IWeakEventListener
{
#region Constructors
static TextEditor()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(TextEditor),
@ -62,6 +63,7 @@ namespace ICSharpCode.AvalonEdit @@ -62,6 +63,7 @@ namespace ICSharpCode.AvalonEdit
textArea.SetBinding(TextArea.DocumentProperty, new Binding(DocumentProperty.Name) { Source = this });
textArea.SetBinding(TextArea.OptionsProperty, new Binding(OptionsProperty.Name) { Source = this });
}
#endregion
/// <inheritdoc/>
protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer()
@ -69,7 +71,7 @@ namespace ICSharpCode.AvalonEdit @@ -69,7 +71,7 @@ namespace ICSharpCode.AvalonEdit
return new TextEditorAutomationPeer(this);
}
// Forward focus to TextArea.
/// Forward focus to TextArea.
/// <inheritdoc/>
protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
{
@ -195,6 +197,7 @@ namespace ICSharpCode.AvalonEdit @@ -195,6 +197,7 @@ namespace ICSharpCode.AvalonEdit
}
#endregion
#region Text property
/// <summary>
/// Gets/Sets the text of the current document.
/// </summary>
@ -238,7 +241,9 @@ namespace ICSharpCode.AvalonEdit @@ -238,7 +241,9 @@ namespace ICSharpCode.AvalonEdit
TextChanged(this, e);
}
}
#endregion
#region TextArea / ScrollViewer properties
readonly TextArea textArea;
ScrollViewer scrollViewer;
@ -283,6 +288,7 @@ namespace ICSharpCode.AvalonEdit @@ -283,6 +288,7 @@ namespace ICSharpCode.AvalonEdit
if (textArea != null)
command.Execute(null, textArea);
}
#endregion
#region Syntax highlighting
IHighlightingDefinition syntaxHighlighting;
@ -355,6 +361,38 @@ namespace ICSharpCode.AvalonEdit @@ -355,6 +361,38 @@ namespace ICSharpCode.AvalonEdit
}
#endregion
#region ShowLineNumbers
/// <summary>
/// IsReadOnly dependency property.
/// </summary>
public static readonly DependencyProperty ShowLineNumbersProperty =
DependencyProperty.Register("ShowLineNumbers", typeof(bool), typeof(TextEditor),
new FrameworkPropertyMetadata(Boxes.False, OnShowLineNumbersChanged));
/// <summary>
/// Specifies whether line numbers are shown on the left to the text view.
/// </summary>
public bool ShowLineNumbers {
get { return (bool)GetValue(ShowLineNumbersProperty); }
set { SetValue(ShowLineNumbersProperty, Boxes.Box(value)); }
}
static void OnShowLineNumbersChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TextEditor editor = (TextEditor)d;
var leftMargins = editor.TextArea.LeftMargins;
if ((bool)e.NewValue) {
leftMargins.Insert(0, new LineNumberMargin());
leftMargins.Insert(1, DottedLineMargin.Create());
} else {
for (int i = 0; i < leftMargins.Count; i++) {
if (leftMargins[i] is LineNumberMargin || DottedLineMargin.IsDottedLineMargin(leftMargins[i]))
leftMargins.RemoveAt(i--);
}
}
}
#endregion
#region TextBoxBase-like methods
/// <summary>
/// Appends text to the end of the document.
@ -805,20 +843,7 @@ namespace ICSharpCode.AvalonEdit @@ -805,20 +843,7 @@ namespace ICSharpCode.AvalonEdit
}
#endregion
/// <summary>
/// Gets the text view position from a point inside the editor.
/// </summary>
/// <param name="point">The position, relative to top left
/// corner of TextEditor control</param>
/// <returns>The text view position, or null if the point is outside the document.</returns>
public TextViewPosition? GetPositionFromPoint(Point point)
{
if (this.Document == null)
return null;
TextView textView = this.TextArea.TextView;
return textView.GetPosition(TranslatePoint(point, textView) + textView.ScrollOffset);
}
#region MouseHover events
/// <summary>
/// The PreviewMouseHover event.
/// </summary>
@ -876,12 +901,27 @@ namespace ICSharpCode.AvalonEdit @@ -876,12 +901,27 @@ namespace ICSharpCode.AvalonEdit
add { AddHandler(MouseHoverStoppedEvent, value); }
remove { RemoveHandler(MouseHoverStoppedEvent, value); }
}
#endregion
object IServiceProvider.GetService(Type serviceType)
{
return textArea.GetService(serviceType);
}
/// <summary>
/// Gets the text view position from a point inside the editor.
/// </summary>
/// <param name="point">The position, relative to top left
/// corner of TextEditor control</param>
/// <returns>The text view position, or null if the point is outside the document.</returns>
public TextViewPosition? GetPositionFromPoint(Point point)
{
if (this.Document == null)
return null;
TextView textView = this.TextArea.TextView;
return textView.GetPosition(TranslatePoint(point, textView) + textView.ScrollOffset);
}
/// <summary>
/// Scrolls to the specified line/column.
/// This method requires that the TextEditor was already assigned a size (WPF layout must have run prior).

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

@ -41,7 +41,7 @@ namespace ICSharpCode.AvalonEdit @@ -41,7 +41,7 @@ namespace ICSharpCode.AvalonEdit
}
#endregion
#region ShowSpaces / ShowTabs / ShowBoxForControlCharacters
#region ShowSpaces / ShowTabs / ShowEndOfLine / ShowBoxForControlCharacters
bool showSpaces;
/// <summary>
@ -76,6 +76,23 @@ namespace ICSharpCode.AvalonEdit @@ -76,6 +76,23 @@ namespace ICSharpCode.AvalonEdit
}
}
bool showEndOfLine;
/// <summary>
/// Gets/Sets whether to show ¶ at the end of lines.
/// </summary>
/// <remarks>The default value is <c>false</c>.</remarks>
[DefaultValue(false)]
public virtual bool ShowEndOfLine {
get { return showEndOfLine; }
set {
if (showEndOfLine != value) {
showEndOfLine = value;
OnPropertyChanged("ShowEndOfLine");
}
}
}
bool showBoxForControlCharacters = true;
/// <summary>
@ -168,8 +185,10 @@ namespace ICSharpCode.AvalonEdit @@ -168,8 +185,10 @@ namespace ICSharpCode.AvalonEdit
public virtual bool CutCopyWholeLine {
get { return cutCopyWholeLine; }
set {
cutCopyWholeLine = value;
OnPropertyChanged("CutCopyWholeLine");
if (cutCopyWholeLine != value) {
cutCopyWholeLine = value;
OnPropertyChanged("CutCopyWholeLine");
}
}
}
}

Loading…
Cancel
Save