Browse Source

move MouseHover logic from TextView to separate class and make it reusable

pull/15/head
Siegfried Pammer 15 years ago
parent
commit
f59c66ba3d
  1. 18
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ChangeMarkerMargin.cs
  2. 1
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
  3. 102
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/MouseHoverLogic.cs
  4. 65
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs

18
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ChangeMarkerMargin.cs

@ -33,10 +33,8 @@ namespace ICSharpCode.AvalonEdit.AddIn
public ChangeMarkerMargin(IChangeWatcher changeWatcher) public ChangeMarkerMargin(IChangeWatcher changeWatcher)
{ {
this.changeWatcher = changeWatcher; this.changeWatcher = changeWatcher;
this.delayTimer = new DispatcherTimer() { this.hoverLogic = new MouseHoverLogic(this);
Interval = SystemParameters.MouseHoverTime this.hoverLogic.MouseHover += delegate { DisplayTooltip(); };
};
delayTimer.Tick += delegate { DisplayTooltip(); };
changeWatcher.ChangeOccurred += ChangeOccurred; changeWatcher.ChangeOccurred += ChangeOccurred;
} }
@ -128,19 +126,10 @@ namespace ICSharpCode.AvalonEdit.AddIn
Popup tooltip = new Popup() { StaysOpen = false }; Popup tooltip = new Popup() { StaysOpen = false };
ITextMarker marker; ITextMarker marker;
ITextMarkerService markerService; ITextMarkerService markerService;
DispatcherTimer delayTimer; MouseHoverLogic hoverLogic;
protected override void OnMouseEnter(MouseEventArgs e)
{
delayTimer.Start();
base.OnMouseEnter(e);
}
void DisplayTooltip() void DisplayTooltip()
{ {
delayTimer.Stop();
int line = GetLineFromMousePosition(); int line = GetLineFromMousePosition();
if (line == 0) if (line == 0)
@ -239,7 +228,6 @@ namespace ICSharpCode.AvalonEdit.AddIn
protected override void OnMouseLeave(MouseEventArgs e) protected override void OnMouseLeave(MouseEventArgs e)
{ {
delayTimer.Stop();
if (marker != null && !tooltip.IsOpen) if (marker != null && !tooltip.IsOpen)
markerService.Remove(marker); markerService.Remove(marker);
base.OnMouseLeave(e); base.OnMouseLeave(e);

1
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj

@ -257,6 +257,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>

102
src/Libraries/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;
}
}
}

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

@ -55,6 +55,10 @@ namespace ICSharpCode.AvalonEdit.Rendering
layers = new UIElementCollection(this, this); layers = new UIElementCollection(this, 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
@ -1566,63 +1570,12 @@ namespace ICSharpCode.AvalonEdit.Rendering
remove { RemoveHandler(MouseHoverStoppedEvent, value); } remove { RemoveHandler(MouseHoverStoppedEvent, value); }
} }
DispatcherTimer mouseHoverTimer; MouseHoverLogic hoverLogic;
Point mouseHoverStartPoint;
MouseEventArgs mouseHoverLastEventArgs;
bool mouseHovering;
/// <inheritdoc/>
protected override void OnMouseMove(MouseEventArgs e)
{
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
}
/// <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) void RaiseHoverEventPair(MouseEventArgs e, RoutedEvent tunnelingEvent, RoutedEvent bubblingEvent)
{ {
mouseHoverTimer.Stop(); var mouseDevice = e.MouseDevice;
mouseHoverTimer = null; var stylusDevice = e.StylusDevice;
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 +1589,6 @@ namespace ICSharpCode.AvalonEdit.Rendering
}; };
RaiseEvent(args2); RaiseEvent(args2);
} }
#endregion #endregion
/// <summary> /// <summary>

Loading…
Cancel
Save