浏览代码

Merge pull request #560 from BDisp/focus-mouse-events-handlers

Focus and mouse events handlers enhanced. Closes #517
Charlie Kindel 5 年之前
父节点
当前提交
4253bc0bd0
共有 5 个文件被更改,包括 114 次插入28 次删除
  1. 4 4
      Designer/Program.cs
  2. 2 2
      Terminal.Gui/Core/Application.cs
  3. 94 18
      Terminal.Gui/Core/View.cs
  4. 12 2
      Terminal.Gui/Views/ComboBox.cs
  5. 2 2
      Terminal.Gui/Views/ScrollView.cs

+ 4 - 4
Designer/Program.cs

@@ -118,14 +118,14 @@ namespace Designer {
 			((TextField)sender).Text = $"Entering in: {sender}";
 		}
 
-		private static void LoginText_MouseLeave (object sender, MouseEvent e)
+		private static void LoginText_MouseLeave (object sender, View.MouseEventEventArgs e)
 		{
-			((TextField)sender).Text = $"Mouse leave at X: {e.X}; Y: {e.Y} HasFocus: {e.View.HasFocus}";
+			((TextField)sender).Text = $"Mouse leave at X: {e.MouseEvent.X}; Y: {e.MouseEvent.Y} HasFocus: {e.MouseEvent.View.HasFocus}";
 		}
 
-		private static void LoginText_MouseEnter (object sender, MouseEvent e)
+		private static void LoginText_MouseEnter (object sender, View.MouseEventEventArgs e)
 		{
-			((TextField)sender).Text = $"Mouse enter at X: {e.X}; Y: {e.Y} HasFocus: {e.View.HasFocus}";
+			((TextField)sender).Text = $"Mouse enter at X: {e.MouseEvent.X}; Y: {e.MouseEvent.Y} HasFocus: {e.MouseEvent.View.HasFocus}";
 		}
 	}
 }

+ 2 - 2
Terminal.Gui/Core/Application.cs

@@ -354,7 +354,7 @@ namespace Terminal.Gui {
 				if (OutsideFrame (new Point (nme.X, nme.Y), mouseGrabView.Frame))
 					lastMouseOwnerView.OnMouseLeave (me);
 				if (mouseGrabView != null) {
-					mouseGrabView.MouseEvent (nme);
+					mouseGrabView.OnMouseEvent (nme);
 					return;
 				}
 			}
@@ -387,7 +387,7 @@ namespace Terminal.Gui {
 					wantContinuousButtonPressedView = null;
 
 				// Should we bubbled up the event, if it is not handled?
-				view.MouseEvent (nme);
+				view.OnMouseEvent (nme);
 			}
 		}
 

+ 94 - 18
Terminal.Gui/Core/View.cs

@@ -118,22 +118,27 @@ namespace Terminal.Gui {
 		/// <summary>
 		/// Event fired when the view get focus.
 		/// </summary>
-		public event EventHandler Enter;
+		public event EventHandler<FocusEventArgs> Enter;
 
 		/// <summary>
 		/// Event fired when the view lost focus.
 		/// </summary>
-		public event EventHandler Leave;
+		public event EventHandler<FocusEventArgs> Leave;
 
 		/// <summary>
 		/// Event fired when the view receives the mouse event for the first time.
 		/// </summary>
-		public event EventHandler<MouseEvent> MouseEnter;
+		public event EventHandler<MouseEventEventArgs> MouseEnter;
 
 		/// <summary>
 		/// Event fired when the view loses mouse event for the last time.
 		/// </summary>
-		public event EventHandler<MouseEvent> MouseLeave;
+		public event EventHandler<MouseEventEventArgs> MouseLeave;
+
+		/// <summary>
+		/// Event fired when a mouse event is generated.
+		/// </summary>
+		public event EventHandler<MouseEventEventArgs> MouseClick;
 
 		internal Direction FocusDirection {
 			get => SuperView?.FocusDirection ?? focusDirection;
@@ -758,18 +763,45 @@ namespace Terminal.Gui {
 			}
 		}
 
+		/// <summary>
+		/// Specifies the event arguments for <see cref="SetFocus(View)"/>
+		/// </summary>
+		public class FocusEventArgs : EventArgs {
+			/// <summary>
+			/// Constructs.
+			/// </summary>
+			public FocusEventArgs () { }
+			/// <summary>
+			/// Indicates if the current focus event has already been processed and the driver should stop notifying any other event subscriber.
+			/// Its important to set this value to true specially when updating any View's layout from inside the subscriber method.
+			/// </summary>
+			public bool Handled { get; set; }
+		}
+
 		/// <inheritdoc cref="OnEnter"/>
 		public override bool OnEnter ()
 		{
-			Enter?.Invoke (this, new EventArgs ());
-			return base.OnEnter ();
+			FocusEventArgs args = new FocusEventArgs ();
+			Enter?.Invoke (this, args);
+			if (args.Handled)
+				return true;
+			if (base.OnEnter ())
+				return true;
+
+			return false;
 		}
 
 		/// <inheritdoc cref="OnLeave"/>
 		public override bool OnLeave ()
 		{
-			Leave?.Invoke (this, new EventArgs ());
-			return base.OnLeave ();
+			FocusEventArgs args = new FocusEventArgs ();
+			Leave?.Invoke (this, args);
+			if (args.Handled)
+				return true;
+			if (base.OnLeave ())
+				return true;
+
+			return false;
 		}
 
 		/// <summary>
@@ -1288,24 +1320,68 @@ namespace Terminal.Gui {
 			return $"{GetType ().Name}({Id})({Frame})";
 		}
 
+		/// <summary>
+		/// Specifies the event arguments for <see cref="MouseEvent"/>
+		/// </summary>
+		public class MouseEventEventArgs : EventArgs {
+			/// <summary>
+			/// Constructs.
+			/// </summary>
+			/// <param name="me"></param>
+			public MouseEventEventArgs (MouseEvent me) => MouseEvent = me;
+			/// <summary>
+			/// The <see cref="MouseEvent"/> for the event.
+			/// </summary>
+			public MouseEvent MouseEvent { get; set; }
+			/// <summary>
+			/// Indicates if the current mouse event has already been processed and the driver should stop notifying any other event subscriber.
+			/// Its important to set this value to true specially when updating any View's layout from inside the subscriber method.
+			/// </summary>
+			public bool Handled { get; set; }
+		}
+
 		/// <inheritdoc cref="OnMouseEnter(Gui.MouseEvent)"/>
 		public override bool OnMouseEnter (MouseEvent mouseEvent)
 		{
-			if (!base.OnMouseEnter (mouseEvent)) {
-				MouseEnter?.Invoke (this, mouseEvent);
-				return false;
-			}
-			return true;
+			MouseEventEventArgs args = new MouseEventEventArgs (mouseEvent);
+			MouseEnter?.Invoke (this, args);
+			if (args.Handled)
+				return true;
+			if (base.OnMouseEnter (mouseEvent))
+				return true;
+
+			return false;
 		}
 
 		/// <inheritdoc cref="OnMouseLeave(Gui.MouseEvent)"/>
 		public override bool OnMouseLeave (MouseEvent mouseEvent)
 		{
-			if (!base.OnMouseLeave (mouseEvent)) {
-				MouseLeave?.Invoke (this, mouseEvent);
-				return false;
-			}
-			return true;
+			MouseEventEventArgs args = new MouseEventEventArgs (mouseEvent);
+			MouseLeave?.Invoke (this, args);
+			if (args.Handled)
+				return true;
+			if (base.OnMouseLeave (mouseEvent))
+				return true;
+
+			return false;
+		}
+
+
+		/// <summary>
+		/// Method invoked when a mouse event is generated
+		/// </summary>
+		/// <param name="mouseEvent"></param>
+		/// <returns><c>true</c>, if the event was handled, <c>false</c> otherwise.</returns>
+		public virtual bool OnMouseEvent (MouseEvent mouseEvent)
+		{
+			MouseEventEventArgs args = new MouseEventEventArgs (mouseEvent);
+			MouseClick?.Invoke (this, args);
+			if (args.Handled)
+				return true;
+			if (MouseEvent (mouseEvent))
+				return true;
+
+			return false;
 		}
 	}
 }

+ 12 - 2
Terminal.Gui/Views/ComboBox.cs

@@ -40,7 +40,7 @@ namespace Terminal.Gui {
 		/// <param name="y">The y coordinate</param>
 		/// <param name="w">The width</param>
 		/// <param name="h">The height</param>
-		/// <param name="source">Auto completetion source</param>
+		/// <param name="source">Auto completion source</param>
 		public ComboBox(int x, int y, int w, int h, IList<string> source)
 		{
 			listsource = new List<string>(source);
@@ -81,11 +81,21 @@ namespace Terminal.Gui {
 					search.ColorScheme = Colors.Menu;
 			};
 
+			search.MouseClick += Search_MouseClick;
+
 			this.Add(listview);
 			this.Add(search);
 			this.SetFocus(search);
 		}
 
+		private void Search_MouseClick (object sender, MouseEventEventArgs e)
+		{
+			if (e.MouseEvent.Flags != MouseFlags.Button1Clicked)
+				return;
+
+			SuperView.SetFocus (((View)sender));
+		}
+
 		///<inheritdoc cref="OnEnter"/>
 		public override bool OnEnter ()
 		{
@@ -156,7 +166,7 @@ namespace Terminal.Gui {
 		}
 
 		/// <summary>
-		/// The currenlty selected list item
+		/// The currently selected list item
 		/// </summary>
 		public ustring Text
 		{

+ 2 - 2
Terminal.Gui/Views/ScrollView.cs

@@ -327,12 +327,12 @@ namespace Terminal.Gui {
 			contentView.Add (view);
 		}
 
-		void View_MouseLeave (object sender, MouseEvent e)
+		void View_MouseLeave (object sender, MouseEventEventArgs e)
 		{
 			Application.UngrabMouse ();
 		}
 
-		void View_MouseEnter (object sender, MouseEvent e)
+		void View_MouseEnter (object sender, MouseEventEventArgs e)
 		{
 			Application.GrabMouse (this);
 		}