Merge branch 'master' into newNR
This commit is contained in:
Коммит
21c98c93c5
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче