diff --git a/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj b/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
index dc000bbf5..05f481a78 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
+++ b/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
@@ -255,6 +255,7 @@
TextView.cs
+
FormattedTextElement.cs
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/InlineObjectRun.cs b/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/InlineObjectRun.cs
index b3c76914e..70e940ed0 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/InlineObjectRun.cs
+++ b/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/InlineObjectRun.cs
@@ -38,11 +38,6 @@ namespace ICSharpCode.AvalonEdit.Rendering
if (context == null)
throw new ArgumentNullException("context");
- // remove inline object if its already added, can happen e.g. when recreating textrun for word-wrapping
- // TODO: certainly the text view should handle this internally? external code might want to use InlineObjectRun,
- // but doesn't have access to textLayer.RemoveInlineObject
- context.TextView.textLayer.RemoveInlineObject(this.Element);
-
return new InlineObjectRun(1, this.TextRunProperties, this.Element);
}
}
@@ -55,6 +50,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
UIElement element;
int length;
TextRunProperties properties;
+ internal Size desiredSize;
///
/// Creates a new InlineObjectRun instance.
@@ -122,11 +118,10 @@ namespace ICSharpCode.AvalonEdit.Rendering
///
public override TextEmbeddedObjectMetrics Format(double remainingParagraphWidth)
{
- Size size = element.DesiredSize;
double baseline = TextBlock.GetBaselineOffset(element);
if (double.IsNaN(baseline))
- baseline = size.Height;
- return new TextEmbeddedObjectMetrics(size.Width, size.Height, baseline);
+ baseline = desiredSize.Height;
+ return new TextEmbeddedObjectMetrics(desiredSize.Width, desiredSize.Height, baseline);
}
///
@@ -135,8 +130,8 @@ namespace ICSharpCode.AvalonEdit.Rendering
if (this.element.IsArrangeValid) {
double baseline = TextBlock.GetBaselineOffset(element);
if (double.IsNaN(baseline))
- baseline = element.DesiredSize.Height;
- return new Rect(new Point(0, -baseline), element.DesiredSize);
+ baseline = desiredSize.Height;
+ return new Rect(new Point(0, -baseline), desiredSize);
} else {
return Rect.Empty;
}
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/MouseHoverLogic.cs b/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/MouseHoverLogic.cs
new file mode 100644
index 000000000..3c3a70c48
--- /dev/null
+++ b/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/MouseHoverLogic.cs
@@ -0,0 +1,102 @@
+// 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.Input;
+using System.Windows.Threading;
+
+namespace ICSharpCode.AvalonEdit.Rendering
+{
+ public class MouseHoverLogic : IDisposable
+ {
+ UIElement target;
+
+ DispatcherTimer mouseHoverTimer;
+ Point mouseHoverStartPoint;
+ MouseEventArgs mouseHoverLastEventArgs;
+ bool mouseHovering;
+
+ public MouseHoverLogic(UIElement target)
+ {
+ if (target == null)
+ throw new ArgumentNullException("target");
+ this.target = target;
+ this.target.MouseLeave += MouseHoverLogicMouseLeave;
+ this.target.MouseMove += MouseHoverLogicMouseMove;
+ }
+
+ void MouseHoverLogicMouseMove(object sender, MouseEventArgs e)
+ {
+ Point newPosition = e.GetPosition(this.target);
+ Vector mouseMovement = mouseHoverStartPoint - newPosition;
+ if (Math.Abs(mouseMovement.X) > SystemParameters.MouseHoverWidth
+ || Math.Abs(mouseMovement.Y) > SystemParameters.MouseHoverHeight)
+ {
+ StopHovering();
+ mouseHoverStartPoint = newPosition;
+ mouseHoverLastEventArgs = e;
+ mouseHoverTimer = new DispatcherTimer(SystemParameters.MouseHoverTime, DispatcherPriority.Background,
+ OnMouseHoverTimerElapsed, this.target.Dispatcher);
+ mouseHoverTimer.Start();
+ }
+ // do not set e.Handled - allow others to also handle MouseMove
+ }
+
+ void MouseHoverLogicMouseLeave(object sender, MouseEventArgs e)
+ {
+ StopHovering();
+ // do not set e.Handled - allow others to also handle MouseLeave
+ }
+
+ void StopHovering()
+ {
+ if (mouseHoverTimer != null) {
+ mouseHoverTimer.Stop();
+ mouseHoverTimer = null;
+ }
+ if (mouseHovering) {
+ mouseHovering = false;
+ OnMouseHoverStopped(mouseHoverLastEventArgs);
+ }
+ }
+
+ void OnMouseHoverTimerElapsed(object sender, EventArgs e)
+ {
+ mouseHoverTimer.Stop();
+ mouseHoverTimer = null;
+
+ mouseHovering = true;
+ OnMouseHover(mouseHoverLastEventArgs);
+ }
+
+ public event EventHandler MouseHover;
+
+ protected virtual void OnMouseHover(MouseEventArgs e)
+ {
+ if (MouseHover != null) {
+ MouseHover(this, e);
+ }
+ }
+
+ public event EventHandler MouseHoverStopped;
+
+ protected virtual void OnMouseHoverStopped(MouseEventArgs e)
+ {
+ if (MouseHoverStopped != null) {
+ MouseHoverStopped(this, e);
+ }
+ }
+
+ bool disposed;
+
+ public void Dispose()
+ {
+ if (!disposed) {
+ this.target.MouseLeave -= MouseHoverLogicMouseLeave;
+ this.target.MouseMove -= MouseHoverLogicMouseMove;
+ }
+ disposed = true;
+ }
+ }
+}
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextLayer.cs b/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextLayer.cs
index beae3ba49..e2b06e337 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextLayer.cs
+++ b/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextLayer.cs
@@ -24,6 +24,11 @@ namespace ICSharpCode.AvalonEdit.Rendering
///
sealed class TextLayer : Layer
{
+ ///
+ /// the index of the text layer in the layers collection
+ ///
+ internal int index;
+
public TextLayer(TextView textView) : base(textView, KnownLayer.Text)
{
}
@@ -33,89 +38,5 @@ namespace ICSharpCode.AvalonEdit.Rendering
base.OnRender(drawingContext);
textView.RenderTextLayer(drawingContext);
}
-
- #region Inline object handling
- internal List inlineObjects = new List();
-
- ///
- /// Adds a new inline object.
- ///
- internal void AddInlineObject(InlineObjectRun inlineObject)
- {
- inlineObjects.Add(inlineObject);
- AddVisualChild(inlineObject.Element);
- inlineObject.Element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
- }
-
- List visualLinesWithOutstandingInlineObjects = new List();
-
- internal void RemoveInlineObjects(VisualLine visualLine)
- {
- // Delay removing inline objects:
- // A document change immediately invalidates affected visual lines, but it does not
- // cause an immediate redraw.
- // To prevent inline objects from flickering when they are recreated, we delay removing
- // inline objects until the next redraw.
- visualLinesWithOutstandingInlineObjects.Add(visualLine);
- }
-
- internal void RemoveInlineObjectsNow()
- {
- inlineObjects.RemoveAll(
- ior => {
- if (visualLinesWithOutstandingInlineObjects.Contains(ior.VisualLine)) {
- RemoveInlineObjectRun(ior);
- return true;
- }
- return false;
- });
- visualLinesWithOutstandingInlineObjects.Clear();
- }
-
- // Remove InlineObjectRun.Element from TextLayer.
- // Caller of RemoveInlineObjectRun will remove it from inlineObjects collection.
- void RemoveInlineObjectRun(InlineObjectRun ior)
- {
- if (ior.Element.IsKeyboardFocusWithin) {
- // When the inline element that has the focus is removed, WPF will reset the
- // focus to the main window without raising appropriate LostKeyboardFocus events.
- // To work around this, we manually set focus to the next focusable parent.
- UIElement element = textView;
- while (element != null && !element.Focusable) {
- element = VisualTreeHelper.GetParent(element) as UIElement;
- }
- if (element != null)
- Keyboard.Focus(element);
- }
- ior.VisualLine = null;
- RemoveVisualChild(ior.Element);
- }
-
- ///
- /// Removes the inline object that displays the specified UIElement.
- ///
- internal void RemoveInlineObject(UIElement element)
- {
- inlineObjects.RemoveAll(
- ior => {
- if (ior.Element == element) {
- RemoveInlineObjectRun(ior);
- return true;
- }
- return false;
- });
- }
-
- ///
- protected override int VisualChildrenCount {
- get { return inlineObjects.Count; }
- }
-
- ///
- protected override Visual GetVisualChild(int index)
- {
- return inlineObjects[index].Element;
- }
- #endregion
}
}
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs b/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs
index 1a67c34bd..6fdaa077a 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs
+++ b/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs
@@ -53,8 +53,12 @@ namespace ICSharpCode.AvalonEdit.Rendering
this.Options = new TextEditorOptions();
Debug.Assert(singleCharacterElementGenerator != null); // assert that the option change created the builtin element generators
- layers = new UIElementCollection(this, this);
+ layers = new LayerCollection(this);
InsertLayer(textLayer, KnownLayer.Text, LayerInsertionPosition.Replace);
+
+ this.hoverLogic = new MouseHoverLogic(this);
+ this.hoverLogic.MouseHover += (sender, e) => RaiseHoverEventPair(e, PreviewMouseHoverEvent, MouseHoverEvent);
+ this.hoverLogic.MouseHoverStopped += (sender, e) => RaiseHoverEventPair(e, PreviewMouseHoverStoppedEvent, MouseHoverStoppedEvent);
}
#endregion
@@ -294,7 +298,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
#region Layers
internal readonly TextLayer textLayer;
- readonly UIElementCollection layers;
+ readonly LayerCollection layers;
///
/// Gets the list of layers displayed in the text view.
@@ -303,6 +307,47 @@ namespace ICSharpCode.AvalonEdit.Rendering
get { return layers; }
}
+ sealed class LayerCollection : UIElementCollection
+ {
+ readonly TextView textView;
+
+ public LayerCollection(TextView textView)
+ : base(textView, textView)
+ {
+ this.textView = textView;
+ }
+
+ public override void Clear()
+ {
+ base.Clear();
+ textView.LayersChanged();
+ }
+
+ public override int Add(UIElement element)
+ {
+ int r = base.Add(element);
+ textView.LayersChanged();
+ return r;
+ }
+
+ public override void RemoveAt(int index)
+ {
+ base.RemoveAt(index);
+ textView.LayersChanged();
+ }
+
+ public override void RemoveRange(int index, int count)
+ {
+ base.RemoveRange(index, count);
+ textView.LayersChanged();
+ }
+ }
+
+ void LayersChanged()
+ {
+ textLayer.index = layers.IndexOf(textLayer);
+ }
+
///
/// Inserts a new layer at a position specified relative to an existing layer.
///
@@ -352,18 +397,128 @@ namespace ICSharpCode.AvalonEdit.Rendering
///
protected override int VisualChildrenCount {
- get { return layers.Count; }
+ get { return layers.Count + inlineObjects.Count; }
}
///
protected override Visual GetVisualChild(int index)
{
- return layers[index];
+ int cut = textLayer.index + 1;
+ if (index < cut)
+ return layers[index];
+ else if (index < cut + inlineObjects.Count)
+ return inlineObjects[index - cut].Element;
+ else
+ return layers[index - inlineObjects.Count];
}
///
protected override System.Collections.IEnumerator LogicalChildren {
- get { return layers.GetEnumerator(); }
+ get {
+ return inlineObjects.Select(io => io.Element).Concat(layers.Cast()).GetEnumerator();
+ }
+ }
+ #endregion
+
+ #region Inline object handling
+ List inlineObjects = new List();
+
+ ///
+ /// Adds a new inline object.
+ ///
+ internal void AddInlineObject(InlineObjectRun inlineObject)
+ {
+ Debug.Assert(inlineObject.VisualLine != null);
+
+ // Remove inline object if its already added, can happen e.g. when recreating textrun for word-wrapping
+ bool alreadyAdded = false;
+ for (int i = 0; i < inlineObjects.Count; i++) {
+ if (inlineObjects[i].Element == inlineObject.Element) {
+ RemoveInlineObjectRun(inlineObjects[i], true);
+ inlineObjects.RemoveAt(i);
+ alreadyAdded = true;
+ break;
+ }
+ }
+
+ inlineObjects.Add(inlineObject);
+ if (!alreadyAdded) {
+ AddVisualChild(inlineObject.Element);
+ }
+ inlineObject.Element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
+ inlineObject.desiredSize = inlineObject.Element.DesiredSize;
+ }
+
+ void MeasureInlineObjects()
+ {
+ // As part of MeasureOverride(), re-measure the inline objects
+ foreach (InlineObjectRun inlineObject in inlineObjects) {
+ if (inlineObject.VisualLine.IsDisposed) {
+ // Don't re-measure inline objects that are going to be removed anyways.
+ // If the inline object will be reused in a different VisualLine, we'll measure it in the AddInlineObject() call.
+ continue;
+ }
+ inlineObject.Element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
+ if (!inlineObject.Element.DesiredSize.IsClose(inlineObject.desiredSize)) {
+ // the element changed size -> recreate its parent visual line
+ inlineObject.desiredSize = inlineObject.Element.DesiredSize;
+ if (allVisualLines.Remove(inlineObject.VisualLine)) {
+ DisposeVisualLine(inlineObject.VisualLine);
+ }
+ }
+ }
+ }
+
+ List visualLinesWithOutstandingInlineObjects = new List();
+
+ void RemoveInlineObjects(VisualLine visualLine)
+ {
+ // Delay removing inline objects:
+ // A document change immediately invalidates affected visual lines, but it does not
+ // cause an immediate redraw.
+ // To prevent inline objects from flickering when they are recreated, we delay removing
+ // inline objects until the next redraw.
+ if (visualLine.hasInlineObjects) {
+ visualLinesWithOutstandingInlineObjects.Add(visualLine);
+ }
+ }
+
+ ///
+ /// Remove the inline objects that were marked for removal.
+ ///
+ void RemoveInlineObjectsNow()
+ {
+ if (visualLinesWithOutstandingInlineObjects.Count == 0)
+ return;
+ inlineObjects.RemoveAll(
+ ior => {
+ if (visualLinesWithOutstandingInlineObjects.Contains(ior.VisualLine)) {
+ RemoveInlineObjectRun(ior, false);
+ return true;
+ }
+ return false;
+ });
+ visualLinesWithOutstandingInlineObjects.Clear();
+ }
+
+ // Remove InlineObjectRun.Element from TextLayer.
+ // Caller of RemoveInlineObjectRun will remove it from inlineObjects collection.
+ void RemoveInlineObjectRun(InlineObjectRun ior, bool keepElement)
+ {
+ if (!keepElement && ior.Element.IsKeyboardFocusWithin) {
+ // When the inline element that has the focus is removed, WPF will reset the
+ // focus to the main window without raising appropriate LostKeyboardFocus events.
+ // To work around this, we manually set focus to the next focusable parent.
+ UIElement element = this;
+ while (element != null && !element.Focusable) {
+ element = VisualTreeHelper.GetParent(element) as UIElement;
+ }
+ if (element != null)
+ Keyboard.Focus(element);
+ }
+ ior.VisualLine = null;
+ if (!keepElement)
+ RemoveVisualChild(ior.Element);
}
#endregion
@@ -410,7 +565,6 @@ namespace ICSharpCode.AvalonEdit.Rendering
{
VerifyAccess();
if (allVisualLines.Remove(visualLine)) {
- visibleVisualLines = null;
DisposeVisualLine(visualLine);
InvalidateMeasure(redrawPriority);
}
@@ -422,7 +576,6 @@ namespace ICSharpCode.AvalonEdit.Rendering
public void Redraw(int offset, int length, DispatcherPriority redrawPriority = DispatcherPriority.Normal)
{
VerifyAccess();
- bool removedLine = false;
bool changedSomethingBeforeOrInLine = false;
for (int i = 0; i < allVisualLines.Count; i++) {
VisualLine visualLine = allVisualLines[i];
@@ -431,15 +584,11 @@ namespace ICSharpCode.AvalonEdit.Rendering
if (offset <= lineEnd) {
changedSomethingBeforeOrInLine = true;
if (offset + length >= lineStart) {
- removedLine = true;
allVisualLines.RemoveAt(i--);
DisposeVisualLine(visualLine);
}
}
}
- if (removedLine) {
- visibleVisualLines = null;
- }
if (changedSomethingBeforeOrInLine) {
// Repaint not only when something in visible area was changed, but also when anything in front of it
// was changed. We might have to redraw the line number margin. Or the highlighting changed.
@@ -492,11 +641,12 @@ namespace ICSharpCode.AvalonEdit.Rendering
if (newVisualLines != null && newVisualLines.Contains(visualLine)) {
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();
}
- textLayer.RemoveInlineObjects(visualLine);
+ RemoveInlineObjects(visualLine);
}
#endregion
@@ -677,11 +827,11 @@ namespace ICSharpCode.AvalonEdit.Rendering
ClearVisualLines();
lastAvailableSize = availableSize;
- textLayer.RemoveInlineObjectsNow();
-
foreach (UIElement layer in layers) {
layer.Measure(availableSize);
}
+ MeasureInlineObjects();
+
InvalidateVisual(); // = InvalidateArrange+InvalidateRender
textLayer.InvalidateVisual();
@@ -700,7 +850,8 @@ namespace ICSharpCode.AvalonEdit.Rendering
}
}
- textLayer.RemoveInlineObjectsNow();
+ // remove inline objects only at the end, so that inline objects that were re-used are not removed from the editor
+ RemoveInlineObjectsNow();
maxWidth += AdditionalHorizontalScrollAmount;
double heightTreeHeight = this.DocumentHeight;
@@ -949,7 +1100,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
foreach (var span in textLine.GetTextRunSpans()) {
InlineObjectRun inline = span.Value as InlineObjectRun;
if (inline != null && inline.VisualLine != null) {
- Debug.Assert(textLayer.inlineObjects.Contains(inline));
+ Debug.Assert(inlineObjects.Contains(inline));
double distance = textLine.GetDistanceFromCharacterHit(new CharacterHit(offset, 0));
inline.Element.Arrange(new Rect(new Point(pos.X + distance, pos.Y), inline.Element.DesiredSize));
}
@@ -1566,63 +1717,12 @@ namespace ICSharpCode.AvalonEdit.Rendering
remove { RemoveHandler(MouseHoverStoppedEvent, value); }
}
- DispatcherTimer mouseHoverTimer;
- Point mouseHoverStartPoint;
- MouseEventArgs mouseHoverLastEventArgs;
- bool mouseHovering;
+ MouseHoverLogic hoverLogic;
- ///
- protected override void OnMouseMove(MouseEventArgs e)
+ void RaiseHoverEventPair(MouseEventArgs e, RoutedEvent tunnelingEvent, RoutedEvent bubblingEvent)
{
- base.OnMouseMove(e);
- Point newPosition = e.GetPosition(this);
- Vector mouseMovement = mouseHoverStartPoint - newPosition;
- if (Math.Abs(mouseMovement.X) > SystemParameters.MouseHoverWidth
- || Math.Abs(mouseMovement.Y) > SystemParameters.MouseHoverHeight)
- {
- StopHovering();
- mouseHoverStartPoint = newPosition;
- mouseHoverLastEventArgs = e;
- mouseHoverTimer = new DispatcherTimer(SystemParameters.MouseHoverTime, DispatcherPriority.Background,
- OnMouseHoverTimerElapsed, this.Dispatcher);
- mouseHoverTimer.Start();
- }
- // do not set e.Handled - allow others to also handle MouseMove
- }
-
- ///
- protected override void OnMouseLeave(MouseEventArgs e)
- {
- base.OnMouseLeave(e);
- StopHovering();
- // do not set e.Handled - allow others to also handle MouseLeave
- }
-
- void StopHovering()
- {
- if (mouseHoverTimer != null) {
- mouseHoverTimer.Stop();
- mouseHoverTimer = null;
- }
- if (mouseHovering) {
- mouseHovering = false;
- RaiseHoverEventPair(PreviewMouseHoverStoppedEvent, MouseHoverStoppedEvent);
- }
- }
-
- void OnMouseHoverTimerElapsed(object sender, EventArgs e)
- {
- mouseHoverTimer.Stop();
- mouseHoverTimer = null;
-
- mouseHovering = true;
- RaiseHoverEventPair(PreviewMouseHoverEvent, MouseHoverEvent);
- }
-
- void RaiseHoverEventPair(RoutedEvent tunnelingEvent, RoutedEvent bubblingEvent)
- {
- var mouseDevice = mouseHoverLastEventArgs.MouseDevice;
- var stylusDevice = mouseHoverLastEventArgs.StylusDevice;
+ var mouseDevice = e.MouseDevice;
+ var stylusDevice = e.StylusDevice;
int inputTime = Environment.TickCount;
var args1 = new MouseEventArgs(mouseDevice, inputTime, stylusDevice) {
RoutedEvent = tunnelingEvent,
@@ -1636,8 +1736,6 @@ namespace ICSharpCode.AvalonEdit.Rendering
};
RaiseEvent(args2);
}
-
-
#endregion
///
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLine.cs b/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLine.cs
index 29ff6c162..47744a594 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLine.cs
+++ b/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLine.cs
@@ -22,6 +22,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
{
TextView textView;
List elements;
+ internal bool hasInlineObjects;
///
/// Gets the document to which this VisualLine belongs.
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLineTextSource.cs b/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLineTextSource.cs
index fa6fa6f1c..eea016446 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLineTextSource.cs
+++ b/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLineTextSource.cs
@@ -42,7 +42,8 @@ namespace ICSharpCode.AvalonEdit.Rendering
InlineObjectRun inlineRun = run as InlineObjectRun;
if (inlineRun != null) {
inlineRun.VisualLine = VisualLine;
- TextView.textLayer.AddInlineObject(inlineRun);
+ VisualLine.hasInlineObjects = true;
+ TextView.AddInlineObject(inlineRun);
}
return run;
}