Merge branch 'master' into newNR

This commit is contained in:
Daniel Grunwald 2012-07-30 19:23:28 +02:00
Родитель a03ce757f7 44ea560fe6
Коммит 21c98c93c5
8 изменённых файлов: 335 добавлений и 16 удалений

Просмотреть файл

@ -18,7 +18,7 @@ namespace ICSharpCode.AvalonEdit.Document
/// <summary>
/// Normal replace.
/// Anchors in front of the replaced region will stay in front, anchors after the replaced region will stay after.
/// Anchors in the middle of the removed region will be deleted. Ifthey survive deletion,
/// Anchors in the middle of the removed region will be deleted. If they survive deletion,
/// they move depending on their AnchorMovementType.
/// </summary>
/// <remarks>

Просмотреть файл

@ -163,9 +163,15 @@ namespace ICSharpCode.AvalonEdit.Editing
VisualLine vl = textView.GetVisualLine(pos.Line);
if (vl == null) return EMPTY_RECT;
TextLine line = vl.GetTextLine(pos.VisualColumn);
double offset = vl.GetTextLineVisualYPosition(line, VisualYPosition.LineTop) - textView.ScrollOffset.Y;
Rect r = line.GetTextBounds(pos.VisualColumn, 1).First().Rectangle;
r.Offset(-textView.ScrollOffset.X, offset);
double offset = vl.GetTextLineVisualYPosition(line, VisualYPosition.TextTop) - textView.ScrollOffset.Y;
Rect r;
if (pos.VisualColumn < vl.VisualLengthWithEndOfLineMarker) {
r = line.GetTextBounds(pos.VisualColumn, 1).First().Rectangle;
r.Offset(-textView.ScrollOffset.X, offset);
} else {
r = new Rect(vl.GetVisualPosition(pos.VisualColumn, VisualYPosition.TextTop), new Size(textView.WideSpaceWidth, textView.DefaultLineHeight));
r.Offset(-textView.ScrollOffset);
}
// this may happen during layout changes in AvalonDock, so we just return an empty rectangle
// in those cases. It should be refreshed immediately.
if (!source.RootVisual.IsAncestorOf(textView)) return EMPTY_RECT;

Просмотреть файл

@ -233,6 +233,7 @@
<DependentUpon>IVisualLineTransformer.cs</DependentUpon>
</Compile>
<Compile Include="Rendering\ColumnRulerRenderer.cs" />
<Compile Include="Rendering\DefaultTextRunTypographyProperties.cs" />
<Compile Include="Rendering\DocumentColorizingTransformer.cs">
<DependentUpon>IVisualLineTransformer.cs</DependentUpon>
</Compile>

Просмотреть файл

@ -0,0 +1,171 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Windows;
using System.Windows.Media.TextFormatting;
namespace ICSharpCode.AvalonEdit.Rendering
{
/// <summary>
/// Default implementation for TextRunTypographyProperties.
/// </summary>
public class DefaultTextRunTypographyProperties : TextRunTypographyProperties
{
/// <inheritdoc/>
public override FontVariants Variants {
get { return FontVariants.Normal; }
}
/// <inheritdoc/>
public override bool StylisticSet1 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet2 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet3 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet4 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet5 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet6 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet7 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet8 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet9 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet10 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet11 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet12 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet13 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet14 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet15 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet16 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet17 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet18 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet19 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet20 { get { return false; } }
/// <inheritdoc/>
public override int StylisticAlternates {
get { return 0; }
}
/// <inheritdoc/>
public override int StandardSwashes {
get { return 0; }
}
/// <inheritdoc/>
public override bool StandardLigatures {
get { return true; }
}
/// <inheritdoc/>
public override bool SlashedZero {
get { return false; }
}
/// <inheritdoc/>
public override FontNumeralStyle NumeralStyle {
get { return FontNumeralStyle.Normal; }
}
/// <inheritdoc/>
public override FontNumeralAlignment NumeralAlignment {
get { return FontNumeralAlignment.Normal; }
}
/// <inheritdoc/>
public override bool MathematicalGreek {
get { return false; }
}
/// <inheritdoc/>
public override bool Kerning {
get { return true; }
}
/// <inheritdoc/>
public override bool HistoricalLigatures {
get { return false; }
}
/// <inheritdoc/>
public override bool HistoricalForms {
get { return false; }
}
/// <inheritdoc/>
public override FontFraction Fraction {
get { return FontFraction.Normal; }
}
/// <inheritdoc/>
public override FontEastAsianWidths EastAsianWidths {
get { return FontEastAsianWidths.Normal; }
}
/// <inheritdoc/>
public override FontEastAsianLanguage EastAsianLanguage {
get { return FontEastAsianLanguage.Normal; }
}
/// <inheritdoc/>
public override bool EastAsianExpertForms {
get { return false; }
}
/// <inheritdoc/>
public override bool DiscretionaryLigatures {
get { return false; }
}
/// <inheritdoc/>
public override int ContextualSwashes {
get { return 0; }
}
/// <inheritdoc/>
public override bool ContextualLigatures {
get { return true; }
}
/// <inheritdoc/>
public override bool ContextualAlternates {
get { return true; }
}
/// <inheritdoc/>
public override bool CaseSensitiveForms {
get { return false; }
}
/// <inheritdoc/>
public override bool CapitalSpacing {
get { return false; }
}
/// <inheritdoc/>
public override FontCapitals Capitals {
get { return FontCapitals.Normal; }
}
/// <inheritdoc/>
public override int AnnotationAlternates {
get { return 0; }
}
}
}

Просмотреть файл

@ -696,10 +696,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
throw new ArgumentException("Cannot dispose visual line because it is in construction!");
}
visibleVisualLines = null;
visualLine.IsDisposed = true;
foreach (TextLine textLine in visualLine.TextLines) {
textLine.Dispose();
}
visualLine.Dispose();
RemoveInlineObjects(visualLine);
}
#endregion

Просмотреть файл

@ -1,6 +1,7 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System.Linq;
using System.Windows.Controls;
using System.Windows.Media;
using ICSharpCode.AvalonEdit.Utils;
@ -22,9 +23,18 @@ namespace ICSharpCode.AvalonEdit.Rendering
/// </summary>
public sealed class VisualLine
{
enum LifetimePhase : byte
{
Generating,
Transforming,
Live,
Disposed
}
TextView textView;
List<VisualLineElement> elements;
internal bool hasInlineObjects;
LifetimePhase phase;
/// <summary>
/// Gets the document to which this VisualLine belongs.
@ -46,10 +56,18 @@ namespace ICSharpCode.AvalonEdit.Rendering
/// </summary>
public ReadOnlyCollection<VisualLineElement> Elements { get; private set; }
ReadOnlyCollection<TextLine> textLines;
/// <summary>
/// Gets a read-only collection of text lines.
/// </summary>
public ReadOnlyCollection<TextLine> TextLines { get; private set; }
public ReadOnlyCollection<TextLine> TextLines {
get {
if (phase < LifetimePhase.Live)
throw new InvalidOperationException();
return textLines;
}
}
/// <summary>
/// Gets the start offset of the VisualLine inside the document.
@ -98,6 +116,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
internal void ConstructVisualElements(ITextRunConstructionContext context, VisualLineElementGenerator[] generators)
{
Debug.Assert(phase == LifetimePhase.Generating);
foreach (VisualLineElementGenerator g in generators) {
g.StartGeneration(context);
}
@ -107,8 +126,13 @@ namespace ICSharpCode.AvalonEdit.Rendering
g.FinishGeneration();
}
var globalTextRunProperties = context.GlobalTextRunProperties;
foreach (var element in elements) {
element.SetTextRunProperties(new VisualLineElementTextRunProperties(globalTextRunProperties));
}
this.Elements = elements.AsReadOnly();
CalculateOffsets(context.GlobalTextRunProperties);
CalculateOffsets();
phase = LifetimePhase.Transforming;
}
void PerformVisualElementConstruction(VisualLineElementGenerator[] generators)
@ -167,14 +191,13 @@ namespace ICSharpCode.AvalonEdit.Rendering
}
}
void CalculateOffsets(TextRunProperties globalTextRunProperties)
void CalculateOffsets()
{
int visualOffset = 0;
int textOffset = 0;
foreach (VisualLineElement element in Elements) {
foreach (VisualLineElement element in elements) {
element.VisualColumn = visualOffset;
element.RelativeTextOffset = textOffset;
element.SetTextRunProperties(new VisualLineElementTextRunProperties(globalTextRunProperties));
visualOffset += element.VisualLength;
textOffset += element.DocumentLength;
}
@ -184,14 +207,63 @@ namespace ICSharpCode.AvalonEdit.Rendering
internal void RunTransformers(ITextRunConstructionContext context, IVisualLineTransformer[] transformers)
{
Debug.Assert(phase == LifetimePhase.Transforming);
foreach (IVisualLineTransformer transformer in transformers) {
transformer.Transform(context, elements);
}
// For some strange reason, WPF requires that either all or none of the typography properties are set.
if (elements.Any(e => e.TextRunProperties.TypographyProperties != null)) {
// Fix typographic properties
foreach (VisualLineElement element in elements) {
if (element.TextRunProperties.TypographyProperties == null) {
element.TextRunProperties.SetTypographyProperties(new DefaultTextRunTypographyProperties());
}
}
}
phase = LifetimePhase.Live;
}
/// <summary>
/// Replaces the single element at <paramref name="elementIndex"/> with the specified elements.
/// The replacement operation must preserve the document length, but may change the visual length.
/// </summary>
/// <remarks>
/// This method may only be called by line transformers.
/// </remarks>
public void ReplaceElement(int elementIndex, params VisualLineElement[] newElements)
{
ReplaceElement(elementIndex, 1, newElements);
}
/// <summary>
/// Replaces <paramref name="count"/> elements starting at <paramref name="elementIndex"/> with the specified elements.
/// The replacement operation must preserve the document length, but may change the visual length.
/// </summary>
/// <remarks>
/// This method may only be called by line transformers.
/// </remarks>
public void ReplaceElement(int elementIndex, int count, params VisualLineElement[] newElements)
{
if (phase != LifetimePhase.Transforming)
throw new InvalidOperationException("This method may only be called by line transformers.");
int oldDocumentLength = 0;
for (int i = elementIndex; i < elementIndex + count; i++) {
oldDocumentLength += elements[i].DocumentLength;
}
int newDocumentLength = 0;
foreach (var newElement in newElements) {
newDocumentLength += newElement.DocumentLength;
}
if (oldDocumentLength != newDocumentLength)
throw new InvalidOperationException("Old elements have document length " + oldDocumentLength + ", but new elements have length " + newDocumentLength);
elements.RemoveRange(elementIndex, count);
elements.InsertRange(elementIndex, newElements);
CalculateOffsets();
}
internal void SetTextLines(List<TextLine> textLines)
{
this.TextLines = textLines.AsReadOnly();
this.textLines = textLines.AsReadOnly();
Height = 0;
foreach (TextLine line in textLines)
Height += line.Height;
@ -446,7 +518,20 @@ namespace ICSharpCode.AvalonEdit.Rendering
/// <summary>
/// Gets whether the visual line was disposed.
/// </summary>
public bool IsDisposed { get; internal set; }
public bool IsDisposed {
get { return phase == LifetimePhase.Disposed; }
}
internal void Dispose()
{
if (phase == LifetimePhase.Disposed)
return;
Debug.Assert(phase == LifetimePhase.Live);
phase = LifetimePhase.Disposed;
foreach (TextLine textLine in TextLines) {
textLine.Dispose();
}
}
/// <summary>
/// Gets the next possible caret position after visualColumn, or -1 if there is no caret position.
@ -557,6 +642,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
internal VisualLineDrawingVisual Render()
{
Debug.Assert(phase == LifetimePhase.Live);
if (visual == null)
visual = new VisualLineDrawingVisual(this);
return visual;

Просмотреть файл

@ -26,6 +26,8 @@ namespace ICSharpCode.AvalonEdit.Rendering
Typeface typeface;
TextDecorationCollection textDecorations;
TextEffectCollection textEffects;
TextRunTypographyProperties typographyProperties;
NumberSubstitution numberSubstitution;
/// <summary>
/// Creates a new VisualLineElementTextRunProperties instance that copies its values
@ -52,6 +54,8 @@ namespace ICSharpCode.AvalonEdit.Rendering
if (textEffects != null && !textEffects.IsFrozen) {
textEffects = textEffects.Clone();
}
typographyProperties = textRunProperties.TypographyProperties;
numberSubstitution = textRunProperties.NumberSubstitution;
}
/// <summary>
@ -203,5 +207,35 @@ namespace ICSharpCode.AvalonEdit.Rendering
ExtensionMethods.CheckIsFrozen(value);
textEffects = value;
}
/// <summary>
/// Gets the typography properties for the text run.
/// </summary>
public override TextRunTypographyProperties TypographyProperties {
get { return typographyProperties; }
}
/// <summary>
/// Sets the <see cref="TypographyProperties"/>.
/// </summary>
public void SetTypographyProperties(TextRunTypographyProperties value)
{
typographyProperties = value;
}
/// <summary>
/// Gets the number substitution settings for the text run.
/// </summary>
public override NumberSubstitution NumberSubstitution {
get { return numberSubstitution; }
}
/// <summary>
/// Sets the <see cref="NumberSubstitution"/>.
/// </summary>
public void SetNumberSubstitution(NumberSubstitution value)
{
numberSubstitution = value;
}
}
}

Просмотреть файл

@ -2,6 +2,8 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Runtime.Serialization;
using System.Windows.Input;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.NRefactory.Editor;
@ -13,10 +15,32 @@ namespace ICSharpCode.AvalonEdit.Snippets
[Serializable]
public class SnippetCaretElement : SnippetElement
{
[OptionalField]
bool setCaretOnlyIfTextIsSelected;
/// <summary>
/// Creates a new SnippetCaretElement.
/// </summary>
public SnippetCaretElement()
{
}
/// <summary>
/// Creates a new SnippetCaretElement.
/// </summary>
/// <param name="setCaretOnlyIfSelectionExists">
/// If set to true, the caret is set only when some text was selected.
/// This is useful
/// </param>
public SnippetCaretElement(bool setCaretOnlyIfTextIsSelected)
{
this.setCaretOnlyIfTextIsSelected = setCaretOnlyIfTextIsSelected;
}
/// <inheritdoc/>
public override void Insert(InsertionContext context)
{
if (!string.IsNullOrEmpty(context.SelectedText))
if (!setCaretOnlyIfTextIsSelected || !string.IsNullOrEmpty(context.SelectedText))
SetCaret(context);
}