Browse Source

Merge commit '0513c24aafa0504ba6bd04fcb825ef5def83996a'

pull/1/head
Daniel Grunwald 15 years ago
parent
commit
16a4c73b1f
  1. 1
      AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
  2. 15
      AvalonEdit/ICSharpCode.AvalonEdit/Rendering/InlineObjectRun.cs
  3. 102
      AvalonEdit/ICSharpCode.AvalonEdit/Rendering/MouseHoverLogic.cs
  4. 89
      AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextLayer.cs
  5. 244
      AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs
  6. 1
      AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLine.cs
  7. 3
      AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLineTextSource.cs

1
AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj

@ -255,6 +255,7 @@
<DependentUpon>TextView.cs</DependentUpon> <DependentUpon>TextView.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Rendering\LinkElementGenerator.cs" /> <Compile Include="Rendering\LinkElementGenerator.cs" />
<Compile Include="Rendering\MouseHoverLogic.cs" />
<Compile Include="Rendering\NewLineElementGenerator.cs" /> <Compile Include="Rendering\NewLineElementGenerator.cs" />
<Compile Include="Rendering\SimpleTextSource.cs"> <Compile Include="Rendering\SimpleTextSource.cs">
<DependentUpon>FormattedTextElement.cs</DependentUpon> <DependentUpon>FormattedTextElement.cs</DependentUpon>

15
AvalonEdit/ICSharpCode.AvalonEdit/Rendering/InlineObjectRun.cs

@ -38,11 +38,6 @@ namespace ICSharpCode.AvalonEdit.Rendering
if (context == null) if (context == null)
throw new ArgumentNullException("context"); 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); return new InlineObjectRun(1, this.TextRunProperties, this.Element);
} }
} }
@ -55,6 +50,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
UIElement element; UIElement element;
int length; int length;
TextRunProperties properties; TextRunProperties properties;
internal Size desiredSize;
/// <summary> /// <summary>
/// Creates a new InlineObjectRun instance. /// Creates a new InlineObjectRun instance.
@ -122,11 +118,10 @@ namespace ICSharpCode.AvalonEdit.Rendering
/// <inheritdoc/> /// <inheritdoc/>
public override TextEmbeddedObjectMetrics Format(double remainingParagraphWidth) public override TextEmbeddedObjectMetrics Format(double remainingParagraphWidth)
{ {
Size size = element.DesiredSize;
double baseline = TextBlock.GetBaselineOffset(element); double baseline = TextBlock.GetBaselineOffset(element);
if (double.IsNaN(baseline)) if (double.IsNaN(baseline))
baseline = size.Height; baseline = desiredSize.Height;
return new TextEmbeddedObjectMetrics(size.Width, size.Height, baseline); return new TextEmbeddedObjectMetrics(desiredSize.Width, desiredSize.Height, baseline);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -135,8 +130,8 @@ namespace ICSharpCode.AvalonEdit.Rendering
if (this.element.IsArrangeValid) { if (this.element.IsArrangeValid) {
double baseline = TextBlock.GetBaselineOffset(element); double baseline = TextBlock.GetBaselineOffset(element);
if (double.IsNaN(baseline)) if (double.IsNaN(baseline))
baseline = element.DesiredSize.Height; baseline = desiredSize.Height;
return new Rect(new Point(0, -baseline), element.DesiredSize); return new Rect(new Point(0, -baseline), desiredSize);
} else { } else {
return Rect.Empty; return Rect.Empty;
} }

102
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<MouseEventArgs> MouseHover;
protected virtual void OnMouseHover(MouseEventArgs e)
{
if (MouseHover != null) {
MouseHover(this, e);
}
}
public event EventHandler<MouseEventArgs> 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;
}
}
}

89
AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextLayer.cs

@ -24,6 +24,11 @@ namespace ICSharpCode.AvalonEdit.Rendering
/// </remarks> /// </remarks>
sealed class TextLayer : Layer sealed class TextLayer : Layer
{ {
/// <summary>
/// the index of the text layer in the layers collection
/// </summary>
internal int index;
public TextLayer(TextView textView) : base(textView, KnownLayer.Text) public TextLayer(TextView textView) : base(textView, KnownLayer.Text)
{ {
} }
@ -33,89 +38,5 @@ namespace ICSharpCode.AvalonEdit.Rendering
base.OnRender(drawingContext); base.OnRender(drawingContext);
textView.RenderTextLayer(drawingContext); textView.RenderTextLayer(drawingContext);
} }
#region Inline object handling
internal List<InlineObjectRun> inlineObjects = new List<InlineObjectRun>();
/// <summary>
/// Adds a new inline object.
/// </summary>
internal void AddInlineObject(InlineObjectRun inlineObject)
{
inlineObjects.Add(inlineObject);
AddVisualChild(inlineObject.Element);
inlineObject.Element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
}
List<VisualLine> visualLinesWithOutstandingInlineObjects = new List<VisualLine>();
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);
}
/// <summary>
/// Removes the inline object that displays the specified UIElement.
/// </summary>
internal void RemoveInlineObject(UIElement element)
{
inlineObjects.RemoveAll(
ior => {
if (ior.Element == element) {
RemoveInlineObjectRun(ior);
return true;
}
return false;
});
}
/// <inheritdoc/>
protected override int VisualChildrenCount {
get { return inlineObjects.Count; }
}
/// <inheritdoc/>
protected override Visual GetVisualChild(int index)
{
return inlineObjects[index].Element;
}
#endregion
} }
} }

244
AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs

@ -53,8 +53,12 @@ namespace ICSharpCode.AvalonEdit.Rendering
this.Options = new TextEditorOptions(); this.Options = new TextEditorOptions();
Debug.Assert(singleCharacterElementGenerator != null); // assert that the option change created the builtin element generators 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); 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 #endregion
@ -294,7 +298,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
#region Layers #region Layers
internal readonly TextLayer textLayer; internal readonly TextLayer textLayer;
readonly UIElementCollection layers; readonly LayerCollection layers;
/// <summary> /// <summary>
/// Gets the list of layers displayed in the text view. /// Gets the list of layers displayed in the text view.
@ -303,6 +307,47 @@ namespace ICSharpCode.AvalonEdit.Rendering
get { return layers; } 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);
}
/// <summary> /// <summary>
/// Inserts a new layer at a position specified relative to an existing layer. /// Inserts a new layer at a position specified relative to an existing layer.
/// </summary> /// </summary>
@ -352,18 +397,128 @@ namespace ICSharpCode.AvalonEdit.Rendering
/// <inheritdoc/> /// <inheritdoc/>
protected override int VisualChildrenCount { protected override int VisualChildrenCount {
get { return layers.Count; } get { return layers.Count + inlineObjects.Count; }
} }
/// <inheritdoc/> /// <inheritdoc/>
protected override Visual GetVisualChild(int index) 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];
} }
/// <inheritdoc/> /// <inheritdoc/>
protected override System.Collections.IEnumerator LogicalChildren { protected override System.Collections.IEnumerator LogicalChildren {
get { return layers.GetEnumerator(); } get {
return inlineObjects.Select(io => io.Element).Concat(layers.Cast<UIElement>()).GetEnumerator();
}
}
#endregion
#region Inline object handling
List<InlineObjectRun> inlineObjects = new List<InlineObjectRun>();
/// <summary>
/// Adds a new inline object.
/// </summary>
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<VisualLine> visualLinesWithOutstandingInlineObjects = new List<VisualLine>();
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);
}
}
/// <summary>
/// Remove the inline objects that were marked for removal.
/// </summary>
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 #endregion
@ -410,7 +565,6 @@ namespace ICSharpCode.AvalonEdit.Rendering
{ {
VerifyAccess(); VerifyAccess();
if (allVisualLines.Remove(visualLine)) { if (allVisualLines.Remove(visualLine)) {
visibleVisualLines = null;
DisposeVisualLine(visualLine); DisposeVisualLine(visualLine);
InvalidateMeasure(redrawPriority); InvalidateMeasure(redrawPriority);
} }
@ -422,7 +576,6 @@ namespace ICSharpCode.AvalonEdit.Rendering
public void Redraw(int offset, int length, DispatcherPriority redrawPriority = DispatcherPriority.Normal) public void Redraw(int offset, int length, DispatcherPriority redrawPriority = DispatcherPriority.Normal)
{ {
VerifyAccess(); VerifyAccess();
bool removedLine = false;
bool changedSomethingBeforeOrInLine = false; bool changedSomethingBeforeOrInLine = false;
for (int i = 0; i < allVisualLines.Count; i++) { for (int i = 0; i < allVisualLines.Count; i++) {
VisualLine visualLine = allVisualLines[i]; VisualLine visualLine = allVisualLines[i];
@ -431,15 +584,11 @@ namespace ICSharpCode.AvalonEdit.Rendering
if (offset <= lineEnd) { if (offset <= lineEnd) {
changedSomethingBeforeOrInLine = true; changedSomethingBeforeOrInLine = true;
if (offset + length >= lineStart) { if (offset + length >= lineStart) {
removedLine = true;
allVisualLines.RemoveAt(i--); allVisualLines.RemoveAt(i--);
DisposeVisualLine(visualLine); DisposeVisualLine(visualLine);
} }
} }
} }
if (removedLine) {
visibleVisualLines = null;
}
if (changedSomethingBeforeOrInLine) { if (changedSomethingBeforeOrInLine) {
// Repaint not only when something in visible area was changed, but also when anything in front of it // 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. // 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)) { if (newVisualLines != null && newVisualLines.Contains(visualLine)) {
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;
visualLine.IsDisposed = true; visualLine.IsDisposed = true;
foreach (TextLine textLine in visualLine.TextLines) { foreach (TextLine textLine in visualLine.TextLines) {
textLine.Dispose(); textLine.Dispose();
} }
textLayer.RemoveInlineObjects(visualLine); RemoveInlineObjects(visualLine);
} }
#endregion #endregion
@ -677,11 +827,11 @@ namespace ICSharpCode.AvalonEdit.Rendering
ClearVisualLines(); ClearVisualLines();
lastAvailableSize = availableSize; lastAvailableSize = availableSize;
textLayer.RemoveInlineObjectsNow();
foreach (UIElement layer in layers) { foreach (UIElement layer in layers) {
layer.Measure(availableSize); layer.Measure(availableSize);
} }
MeasureInlineObjects();
InvalidateVisual(); // = InvalidateArrange+InvalidateRender InvalidateVisual(); // = InvalidateArrange+InvalidateRender
textLayer.InvalidateVisual(); 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; maxWidth += AdditionalHorizontalScrollAmount;
double heightTreeHeight = this.DocumentHeight; double heightTreeHeight = this.DocumentHeight;
@ -949,7 +1100,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
foreach (var span in textLine.GetTextRunSpans()) { foreach (var span in textLine.GetTextRunSpans()) {
InlineObjectRun inline = span.Value as InlineObjectRun; InlineObjectRun inline = span.Value as InlineObjectRun;
if (inline != null && inline.VisualLine != null) { 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)); double distance = textLine.GetDistanceFromCharacterHit(new CharacterHit(offset, 0));
inline.Element.Arrange(new Rect(new Point(pos.X + distance, pos.Y), inline.Element.DesiredSize)); 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); } remove { RemoveHandler(MouseHoverStoppedEvent, value); }
} }
DispatcherTimer mouseHoverTimer; MouseHoverLogic hoverLogic;
Point mouseHoverStartPoint;
MouseEventArgs mouseHoverLastEventArgs;
bool mouseHovering;
/// <inheritdoc/> void RaiseHoverEventPair(MouseEventArgs e, RoutedEvent tunnelingEvent, RoutedEvent bubblingEvent)
protected override void OnMouseMove(MouseEventArgs e)
{ {
base.OnMouseMove(e); var mouseDevice = e.MouseDevice;
Point newPosition = e.GetPosition(this); var stylusDevice = e.StylusDevice;
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
}
/// <inheritdoc/>
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;
int inputTime = Environment.TickCount; int inputTime = Environment.TickCount;
var args1 = new MouseEventArgs(mouseDevice, inputTime, stylusDevice) { var args1 = new MouseEventArgs(mouseDevice, inputTime, stylusDevice) {
RoutedEvent = tunnelingEvent, RoutedEvent = tunnelingEvent,
@ -1636,8 +1736,6 @@ namespace ICSharpCode.AvalonEdit.Rendering
}; };
RaiseEvent(args2); RaiseEvent(args2);
} }
#endregion #endregion
/// <summary> /// <summary>

1
AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLine.cs

@ -22,6 +22,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
{ {
TextView textView; TextView textView;
List<VisualLineElement> elements; List<VisualLineElement> elements;
internal bool hasInlineObjects;
/// <summary> /// <summary>
/// Gets the document to which this VisualLine belongs. /// Gets the document to which this VisualLine belongs.

3
AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLineTextSource.cs

@ -42,7 +42,8 @@ namespace ICSharpCode.AvalonEdit.Rendering
InlineObjectRun inlineRun = run as InlineObjectRun; InlineObjectRun inlineRun = run as InlineObjectRun;
if (inlineRun != null) { if (inlineRun != null) {
inlineRun.VisualLine = VisualLine; inlineRun.VisualLine = VisualLine;
TextView.textLayer.AddInlineObject(inlineRun); VisualLine.hasInlineObjects = true;
TextView.AddInlineObject(inlineRun);
} }
return run; return run;
} }

Loading…
Cancel
Save