// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
namespace ICSharpCode.AvalonEdit.Rendering
{
///
/// Encapsulates and adds MouseHover support to UIElements.
///
public class MouseHoverLogic : IDisposable
{
UIElement target;
DispatcherTimer mouseHoverTimer;
Point mouseHoverStartPoint;
MouseEventArgs mouseHoverLastEventArgs;
bool mouseHovering;
///
/// Creates a new instance and attaches itself to the UIElement.
///
public MouseHoverLogic(UIElement target)
{
if (target == null)
throw new ArgumentNullException("target");
this.target = target;
this.target.MouseLeave += MouseHoverLogicMouseLeave;
this.target.MouseMove += MouseHoverLogicMouseMove;
this.target.MouseEnter += MouseHoverLogicMouseEnter;
}
void MouseHoverLogicMouseMove(object sender, MouseEventArgs e)
{
Vector mouseMovement = mouseHoverStartPoint - e.GetPosition(this.target);
if (Math.Abs(mouseMovement.X) > SystemParameters.MouseHoverWidth
|| Math.Abs(mouseMovement.Y) > SystemParameters.MouseHoverHeight)
{
StartHovering(e);
}
// do not set e.Handled - allow others to also handle MouseMove
}
void MouseHoverLogicMouseEnter(object sender, MouseEventArgs e)
{
StartHovering(e);
// do not set e.Handled - allow others to also handle MouseEnter
}
void StartHovering(MouseEventArgs e)
{
StopHovering();
mouseHoverStartPoint = e.GetPosition(this.target);
mouseHoverLastEventArgs = e;
mouseHoverTimer = new DispatcherTimer(SystemParameters.MouseHoverTime, DispatcherPriority.Background, OnMouseHoverTimerElapsed, this.target.Dispatcher);
mouseHoverTimer.Start();
}
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);
}
///
/// Occurs when the mouse starts hovering over a certain location.
///
public event EventHandler MouseHover;
///
/// Raises the event.
///
protected virtual void OnMouseHover(MouseEventArgs e)
{
if (MouseHover != null) {
MouseHover(this, e);
}
}
///
/// Occurs when the mouse stops hovering over a certain location.
///
public event EventHandler MouseHoverStopped;
///
/// Raises the event.
///
protected virtual void OnMouseHoverStopped(MouseEventArgs e)
{
if (MouseHoverStopped != null) {
MouseHoverStopped(this, e);
}
}
bool disposed;
///
/// Removes the MouseHover support from the target UIElement.
///
public void Dispose()
{
if (!disposed) {
this.target.MouseLeave -= MouseHoverLogicMouseLeave;
this.target.MouseMove -= MouseHoverLogicMouseMove;
this.target.MouseEnter -= MouseHoverLogicMouseEnter;
}
disposed = true;
}
}
}