Browse Source

Add VisualLine.ReplaceElement method.

pull/27/merge
Daniel Grunwald 14 years ago
parent
commit
db6d2d3e01
  1. 43
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/DefaultTextRunTypographyProperties.cs
  2. 5
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs
  3. 90
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLine.cs

43
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/DefaultTextRunTypographyProperties.cs

@ -12,115 +12,158 @@ namespace ICSharpCode.AvalonEdit.Rendering
/// </summary> /// </summary>
public class DefaultTextRunTypographyProperties : TextRunTypographyProperties public class DefaultTextRunTypographyProperties : TextRunTypographyProperties
{ {
/// <inheritdoc/>
public override FontVariants Variants { public override FontVariants Variants {
get { return FontVariants.Normal; } get { return FontVariants.Normal; }
} }
/// <inheritdoc/>
public override bool StylisticSet1 { get { return false; } } public override bool StylisticSet1 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet2 { get { return false; } } public override bool StylisticSet2 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet3 { get { return false; } } public override bool StylisticSet3 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet4 { get { return false; } } public override bool StylisticSet4 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet5 { get { return false; } } public override bool StylisticSet5 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet6 { get { return false; } } public override bool StylisticSet6 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet7 { get { return false; } } public override bool StylisticSet7 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet8 { get { return false; } } public override bool StylisticSet8 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet9 { get { return false; } } public override bool StylisticSet9 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet10 { get { return false; } } public override bool StylisticSet10 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet11 { get { return false; } } public override bool StylisticSet11 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet12 { get { return false; } } public override bool StylisticSet12 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet13 { get { return false; } } public override bool StylisticSet13 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet14 { get { return false; } } public override bool StylisticSet14 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet15 { get { return false; } } public override bool StylisticSet15 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet16 { get { return false; } } public override bool StylisticSet16 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet17 { get { return false; } } public override bool StylisticSet17 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet18 { get { return false; } } public override bool StylisticSet18 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet19 { get { return false; } } public override bool StylisticSet19 { get { return false; } }
/// <inheritdoc/>
public override bool StylisticSet20 { get { return false; } } public override bool StylisticSet20 { get { return false; } }
/// <inheritdoc/>
public override int StylisticAlternates { public override int StylisticAlternates {
get { return 0; } get { return 0; }
} }
/// <inheritdoc/>
public override int StandardSwashes { public override int StandardSwashes {
get { return 0; } get { return 0; }
} }
/// <inheritdoc/>
public override bool StandardLigatures { public override bool StandardLigatures {
get { return true; } get { return true; }
} }
/// <inheritdoc/>
public override bool SlashedZero { public override bool SlashedZero {
get { return false; } get { return false; }
} }
/// <inheritdoc/>
public override FontNumeralStyle NumeralStyle { public override FontNumeralStyle NumeralStyle {
get { return FontNumeralStyle.Normal; } get { return FontNumeralStyle.Normal; }
} }
/// <inheritdoc/>
public override FontNumeralAlignment NumeralAlignment { public override FontNumeralAlignment NumeralAlignment {
get { return FontNumeralAlignment.Normal; } get { return FontNumeralAlignment.Normal; }
} }
/// <inheritdoc/>
public override bool MathematicalGreek { public override bool MathematicalGreek {
get { return false; } get { return false; }
} }
/// <inheritdoc/>
public override bool Kerning { public override bool Kerning {
get { return true; } get { return true; }
} }
/// <inheritdoc/>
public override bool HistoricalLigatures { public override bool HistoricalLigatures {
get { return false; } get { return false; }
} }
/// <inheritdoc/>
public override bool HistoricalForms { public override bool HistoricalForms {
get { return false; } get { return false; }
} }
/// <inheritdoc/>
public override FontFraction Fraction { public override FontFraction Fraction {
get { return FontFraction.Normal; } get { return FontFraction.Normal; }
} }
/// <inheritdoc/>
public override FontEastAsianWidths EastAsianWidths { public override FontEastAsianWidths EastAsianWidths {
get { return FontEastAsianWidths.Normal; } get { return FontEastAsianWidths.Normal; }
} }
/// <inheritdoc/>
public override FontEastAsianLanguage EastAsianLanguage { public override FontEastAsianLanguage EastAsianLanguage {
get { return FontEastAsianLanguage.Normal; } get { return FontEastAsianLanguage.Normal; }
} }
/// <inheritdoc/>
public override bool EastAsianExpertForms { public override bool EastAsianExpertForms {
get { return false; } get { return false; }
} }
/// <inheritdoc/>
public override bool DiscretionaryLigatures { public override bool DiscretionaryLigatures {
get { return false; } get { return false; }
} }
/// <inheritdoc/>
public override int ContextualSwashes { public override int ContextualSwashes {
get { return 0; } get { return 0; }
} }
/// <inheritdoc/>
public override bool ContextualLigatures { public override bool ContextualLigatures {
get { return true; } get { return true; }
} }
/// <inheritdoc/>
public override bool ContextualAlternates { public override bool ContextualAlternates {
get { return true; } get { return true; }
} }
/// <inheritdoc/>
public override bool CaseSensitiveForms { public override bool CaseSensitiveForms {
get { return false; } get { return false; }
} }
/// <inheritdoc/>
public override bool CapitalSpacing { public override bool CapitalSpacing {
get { return false; } get { return false; }
} }
/// <inheritdoc/>
public override FontCapitals Capitals { public override FontCapitals Capitals {
get { return FontCapitals.Normal; } get { return FontCapitals.Normal; }
} }
/// <inheritdoc/>
public override int AnnotationAlternates { public override int AnnotationAlternates {
get { return 0; } get { return 0; }
} }

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

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

90
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLine.cs

@ -23,9 +23,18 @@ namespace ICSharpCode.AvalonEdit.Rendering
/// </summary> /// </summary>
public sealed class VisualLine public sealed class VisualLine
{ {
enum LifetimePhase : byte
{
Generating,
Transforming,
Live,
Disposed
}
TextView textView; TextView textView;
List<VisualLineElement> elements; List<VisualLineElement> elements;
internal bool hasInlineObjects; internal bool hasInlineObjects;
LifetimePhase phase;
/// <summary> /// <summary>
/// Gets the document to which this VisualLine belongs. /// Gets the document to which this VisualLine belongs.
@ -47,10 +56,18 @@ namespace ICSharpCode.AvalonEdit.Rendering
/// </summary> /// </summary>
public ReadOnlyCollection<VisualLineElement> Elements { get; private set; } public ReadOnlyCollection<VisualLineElement> Elements { get; private set; }
ReadOnlyCollection<TextLine> textLines;
/// <summary> /// <summary>
/// Gets a read-only collection of text lines. /// Gets a read-only collection of text lines.
/// </summary> /// </summary>
public ReadOnlyCollection<TextLine> TextLines { get; private set; } public ReadOnlyCollection<TextLine> TextLines {
get {
if (phase < LifetimePhase.Live)
throw new InvalidOperationException();
return textLines;
}
}
/// <summary> /// <summary>
/// Gets the start offset of the VisualLine inside the document. /// Gets the start offset of the VisualLine inside the document.
@ -99,6 +116,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
internal void ConstructVisualElements(ITextRunConstructionContext context, VisualLineElementGenerator[] generators) internal void ConstructVisualElements(ITextRunConstructionContext context, VisualLineElementGenerator[] generators)
{ {
Debug.Assert(phase == LifetimePhase.Generating);
foreach (VisualLineElementGenerator g in generators) { foreach (VisualLineElementGenerator g in generators) {
g.StartGeneration(context); g.StartGeneration(context);
} }
@ -108,8 +126,13 @@ namespace ICSharpCode.AvalonEdit.Rendering
g.FinishGeneration(); g.FinishGeneration();
} }
var globalTextRunProperties = context.GlobalTextRunProperties;
foreach (var element in elements) {
element.SetTextRunProperties(new VisualLineElementTextRunProperties(globalTextRunProperties));
}
this.Elements = elements.AsReadOnly(); this.Elements = elements.AsReadOnly();
CalculateOffsets(context.GlobalTextRunProperties); CalculateOffsets();
phase = LifetimePhase.Transforming;
} }
void PerformVisualElementConstruction(VisualLineElementGenerator[] generators) void PerformVisualElementConstruction(VisualLineElementGenerator[] generators)
@ -168,14 +191,13 @@ namespace ICSharpCode.AvalonEdit.Rendering
} }
} }
void CalculateOffsets(TextRunProperties globalTextRunProperties) void CalculateOffsets()
{ {
int visualOffset = 0; int visualOffset = 0;
int textOffset = 0; int textOffset = 0;
foreach (VisualLineElement element in Elements) { foreach (VisualLineElement element in elements) {
element.VisualColumn = visualOffset; element.VisualColumn = visualOffset;
element.RelativeTextOffset = textOffset; element.RelativeTextOffset = textOffset;
element.SetTextRunProperties(new VisualLineElementTextRunProperties(globalTextRunProperties));
visualOffset += element.VisualLength; visualOffset += element.VisualLength;
textOffset += element.DocumentLength; textOffset += element.DocumentLength;
} }
@ -185,6 +207,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
internal void RunTransformers(ITextRunConstructionContext context, IVisualLineTransformer[] transformers) internal void RunTransformers(ITextRunConstructionContext context, IVisualLineTransformer[] transformers)
{ {
Debug.Assert(phase == LifetimePhase.Transforming);
foreach (IVisualLineTransformer transformer in transformers) { foreach (IVisualLineTransformer transformer in transformers) {
transformer.Transform(context, elements); transformer.Transform(context, elements);
} }
@ -197,11 +220,50 @@ namespace ICSharpCode.AvalonEdit.Rendering
} }
} }
} }
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) internal void SetTextLines(List<TextLine> textLines)
{ {
this.TextLines = textLines.AsReadOnly(); this.textLines = textLines.AsReadOnly();
Height = 0; Height = 0;
foreach (TextLine line in textLines) foreach (TextLine line in textLines)
Height += line.Height; Height += line.Height;
@ -456,7 +518,20 @@ namespace ICSharpCode.AvalonEdit.Rendering
/// <summary> /// <summary>
/// Gets whether the visual line was disposed. /// Gets whether the visual line was disposed.
/// </summary> /// </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> /// <summary>
/// Gets the next possible caret position after visualColumn, or -1 if there is no caret position. /// Gets the next possible caret position after visualColumn, or -1 if there is no caret position.
@ -567,6 +642,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
internal VisualLineDrawingVisual Render() internal VisualLineDrawingVisual Render()
{ {
Debug.Assert(phase == LifetimePhase.Live);
if (visual == null) if (visual == null)
visual = new VisualLineDrawingVisual(this); visual = new VisualLineDrawingVisual(this);
return visual; return visual;

Loading…
Cancel
Save