aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/SideChains/ICSharpCode.AvalonEdit/Rendering/MouseHoverLogic.cs
blob: 25d025b249af27237a75e943bc7d669b908cf687 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// 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
{
	/// <summary>
	/// Encapsulates and adds MouseHover support to UIElements.
	/// </summary>
	public class MouseHoverLogic : IDisposable
	{
		UIElement target;
		
		DispatcherTimer mouseHoverTimer;
		Point mouseHoverStartPoint;
		MouseEventArgs mouseHoverLastEventArgs;
		bool mouseHovering;
		
		/// <summary>
		/// Creates a new instance and attaches itself to the <paramref name="target" /> UIElement.
		/// </summary>
		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);
		}
		
		/// <summary>
		/// Occurs when the mouse starts hovering over a certain location.
		/// </summary>
		public event EventHandler<MouseEventArgs> MouseHover;
		
		/// <summary>
		/// Raises the <see cref="MouseHover"/> event.
		/// </summary>
		protected virtual void OnMouseHover(MouseEventArgs e)
		{
			if (MouseHover != null) {
				MouseHover(this, e);
			}
		}
		
		/// <summary>
		/// Occurs when the mouse stops hovering over a certain location.
		/// </summary>
		public event EventHandler<MouseEventArgs> MouseHoverStopped;
		
		/// <summary>
		/// Raises the <see cref="MouseHoverStopped"/> event.
		/// </summary>
		protected virtual void OnMouseHoverStopped(MouseEventArgs e)
		{
			if (MouseHoverStopped != null) {
				MouseHoverStopped(this, e);
			}
		}
		
		bool disposed;
		
		/// <summary>
		/// Removes the MouseHover support from the target UIElement.
		/// </summary>
		public void Dispose()
		{
			if (!disposed) {
				this.target.MouseLeave -= MouseHoverLogicMouseLeave;
				this.target.MouseMove -= MouseHoverLogicMouseMove;
				this.target.MouseEnter -= MouseHoverLogicMouseEnter;
			}
			disposed = true;
		}
	}
}