Skip to content

Commit

Permalink
Merge pull request #3281 from tig/v2_2579_mouseevent
Browse files Browse the repository at this point in the history
Fixes #2579. `MouseEvent/OnMouseEvent` are stoopid
  • Loading branch information
tig authored Mar 2, 2024
2 parents 0b8ffb4 + 9117039 commit eeced7e
Show file tree
Hide file tree
Showing 56 changed files with 372 additions and 467 deletions.
29 changes: 0 additions & 29 deletions Terminal.Gui/Input/Responder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,6 @@ public void Dispose ()
/// <summary>Event raised when <see cref="Dispose()"/> has been called to signal that this object is being disposed.</summary>
public event EventHandler Disposing;

/// <summary>Method invoked when a mouse event is generated</summary>
/// <remarks>
/// The coordinates are relative to <see cref="View.Bounds"/>.
/// </remarks>
/// <returns><c>true</c>, if the event was handled, <c>false</c> otherwise.</returns>
/// <param name="mouseEvent">Contains the details about the mouse event.</param>
public virtual bool MouseEvent (MouseEvent mouseEvent) { return false; }

/// <summary>Method invoked when the <see cref="CanFocus"/> property from a view is changed.</summary>
public virtual void OnCanFocusChanged () { }

Expand All @@ -80,27 +72,6 @@ public virtual void OnEnabledChanged () { }
/// <returns><c>true</c>, if the event was handled, <c>false</c> otherwise.</returns>
public virtual bool OnLeave (View view) { return false; }

/// <summary>
/// Called when the mouse first enters the view; the view will now receives mouse events until the mouse leaves
/// the view. At which time, <see cref="OnMouseLeave(Gui.MouseEvent)"/> will be called.
/// </summary>
/// <remarks>
/// The coordinates are relative to <see cref="View.Bounds"/>.
/// </remarks>
/// <param name="mouseEvent"></param>
/// <returns><c>true</c>, if the event was handled, <c>false</c> otherwise.</returns>
public virtual bool OnMouseEnter (MouseEvent mouseEvent) { return false; }

/// <summary>
/// Called when the mouse has moved outside of the view; the view will no longer receive mouse events (until the
/// mouse moves within the view again and <see cref="OnMouseEnter(Gui.MouseEvent)"/> is called).
/// </summary>
/// <remarks>
/// The coordinates are relative to <see cref="View.Bounds"/>.
/// </remarks>
/// <param name="mouseEvent"></param>
/// <returns><c>true</c>, if the event was handled, <c>false</c> otherwise.</returns>
public virtual bool OnMouseLeave (MouseEvent mouseEvent) { return false; }

/// <summary>Method invoked when the <see cref="Visible"/> property from a view is changed.</summary>
public virtual void OnVisibleChanged () { }
Expand Down
2 changes: 1 addition & 1 deletion Terminal.Gui/Text/Autocomplete/AppendAutocomplete.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public override void GenerateSuggestions (AutocompleteContext context)
}

/// <inheritdoc/>
public override bool MouseEvent (MouseEvent me, bool fromHost = false) { return false; }
public override bool OnMouseEvent (MouseEvent me, bool fromHost = false) { return false; }

/// <inheritdoc/>
public override bool ProcessKey (Key a)
Expand Down
2 changes: 1 addition & 1 deletion Terminal.Gui/Text/Autocomplete/AutocompleteBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public abstract class AutocompleteBase : IAutocomplete
public virtual AutocompleteContext Context { get; set; }

/// <inheritdoc/>
public abstract bool MouseEvent (MouseEvent me, bool fromHost = false);
public abstract bool OnMouseEvent (MouseEvent me, bool fromHost = false);

/// <inheritdoc/>
public abstract bool ProcessKey (Key a);
Expand Down
2 changes: 1 addition & 1 deletion Terminal.Gui/Text/Autocomplete/IAutocomplete.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public interface IAutocomplete
/// <param name="me">The mouse event.</param>
/// <param name="fromHost">If was called from the popup or from the host.</param>
/// <returns><c>true</c>if the mouse can be handled <c>false</c>otherwise.</returns>
bool MouseEvent (MouseEvent me, bool fromHost = false);
bool OnMouseEvent (MouseEvent me, bool fromHost = false);

/// <summary>
/// Handle key events before <see cref="HostControl"/> e.g. to make key events like up/down apply to the
Expand Down
2 changes: 1 addition & 1 deletion Terminal.Gui/Text/Autocomplete/PopupAutocomplete.PopUp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public Popup (PopupAutocomplete autoComplete)
WantMousePositionReports = true;
}

public override bool MouseEvent (MouseEvent mouseEvent) { return _autoComplete.MouseEvent (mouseEvent); }
protected internal override bool OnMouseEvent (MouseEvent mouseEvent) { return _autoComplete.OnMouseEvent (mouseEvent); }

public override void OnDrawContent (Rectangle contentArea)
{
Expand Down
2 changes: 1 addition & 1 deletion Terminal.Gui/Text/Autocomplete/PopupAutocomplete.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public override void EnsureSelectedIdxIsValid ()
/// <param name="me">The mouse event.</param>
/// <param name="fromHost">If was called from the popup or from the host.</param>
/// <returns><c>true</c>if the mouse can be handled <c>false</c>otherwise.</returns>
public override bool MouseEvent (MouseEvent me, bool fromHost = false)
public override bool OnMouseEvent (MouseEvent me, bool fromHost = false)
{
if (fromHost)
{
Expand Down
18 changes: 18 additions & 0 deletions Terminal.Gui/View/View.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,24 @@ public override bool Visible
/// <summary>Event fired when the <see cref="Visible"/> value is being changed.</summary>
public event EventHandler VisibleChanged;

/// <summary>
/// Cancelable event fired when the <see cref="Command.Accept"/> command is invoked. Set <see cref="CancelEventArgs.Cancel"/>
/// to cancel the event.
/// </summary>
public event EventHandler<CancelEventArgs> Accept;

/// <summary>
/// Called when the <see cref="Command.Accept"/> command is invoked. Fires the <see cref="Accept"/>
/// event.
/// </summary>
/// <returns>If <see langword="true"/> the event was canceled.</returns>
protected bool? OnAccept ()
{
var args = new CancelEventArgs ();
Accept?.Invoke (this, args);
return args.Cancel;
}

/// <inheritdoc/>
protected override void Dispose (bool disposing)
{
Expand Down
21 changes: 1 addition & 20 deletions Terminal.Gui/View/ViewKeyboard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,12 @@ private void AddCommands ()
if (CanFocus)
{
SetFocus ();

return true;
}

return false;
}

/// <summary>
/// Cancelable event fired when the <see cref="Command.Accept"/> command is invoked. Set <see cref="CancelEventArgs.Cancel"/>
/// to cancel the event.
/// </summary>
public event EventHandler<CancelEventArgs> Accept;

/// <summary>
/// Called when the <see cref="Command.Accept"/> command is invoked. Fires the <see cref="Accept"/>
/// event.
/// </summary>
/// <returns>If <see langword="true"/> the event was canceled.</returns>
public bool? OnAccept ()
{
var args = new CancelEventArgs ();
Accept?.Invoke (this, args);
return args.Cancel;
}

/// <summary>Invoked when the <see cref="HotKey"/> is changed.</summary>
public event EventHandler<KeyChangedEventArgs> HotKeyChanged;

Expand Down Expand Up @@ -505,7 +486,7 @@ public virtual bool OnProcessKeyDown (Key keyEvent)
}

/// <summary>
/// Invoked when the users presses a key, allowing subscribers to do things during key down events. Set
/// Invoked when the user presses a key, allowing subscribers to do things during key down events. Set
/// <see cref="Key.Handled"/> to true to stop the key from being processed by other views. Invoked after
/// <see cref="KeyDown"/> and before <see cref="InvokingKeyBindings"/>.
/// </summary>
Expand Down
113 changes: 71 additions & 42 deletions Terminal.Gui/View/ViewMouse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,35 @@ public partial class View
/// <value><see langword="true"/> if want mouse position reports; otherwise, <see langword="false"/>.</value>
public virtual bool WantMousePositionReports { get; set; }

/// <summary>Event fired when a mouse event is generated.</summary>
/// <summary>Event fired when a mouse click occurs.</summary>
/// <remarks>
/// <para>
/// Fired when the mouse is either clicked or double-clicked. Check
/// <see cref="MouseEvent.Flags"/> to see which button was clicked.
/// </para>
/// <para>
/// The coordinates are relative to <see cref="View.Bounds"/>.
/// </para>
/// </remarks>
public event EventHandler<MouseEventEventArgs> MouseClick;

/// <summary>Event fired when the view receives the mouse event for the first time.</summary>
/// <summary>Event fired when the mouse moves into the View's <see cref="Bounds"/>.</summary>
public event EventHandler<MouseEventEventArgs> MouseEnter;

/// <summary>Event fired when the view receives a mouse event for the last time.</summary>
/// <summary>Event fired when the mouse leaves the View's <see cref="Bounds"/>.</summary>
public event EventHandler<MouseEventEventArgs> MouseLeave;

/// <inheritdoc/>
public override bool OnMouseEnter (MouseEvent mouseEvent)
// TODO: OnMouseEnter should not be public virtual, but protected.
/// <summary>
/// Called when the mouse enters the View's <see cref="Bounds"/>. The view will now receive mouse events until the mouse leaves
/// the view. At which time, <see cref="OnMouseLeave(Gui.MouseEvent)"/> will be called.
/// </summary>
/// <remarks>
/// The coordinates are relative to <see cref="View.Bounds"/>.
/// </remarks>
/// <param name="mouseEvent"></param>
/// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
protected internal virtual bool OnMouseEnter (MouseEvent mouseEvent)
{
if (!Enabled)
{
Expand All @@ -34,13 +52,20 @@ public override bool OnMouseEnter (MouseEvent mouseEvent)
var args = new MouseEventEventArgs (mouseEvent);
MouseEnter?.Invoke (this, args);

return args.Handled || base.OnMouseEnter (mouseEvent);
return args.Handled;
}

/// <summary>Method invoked when a mouse event is generated</summary>
// TODO: OnMouseLeave should not be public virtual, but protected.
/// <summary>
/// Called when the mouse has moved out of the View's <see cref="Bounds"/>. The view will no longer receive mouse events (until the
/// mouse moves within the view again and <see cref="OnMouseEnter(Gui.MouseEvent)"/> is called).
/// </summary>
/// <remarks>
/// The coordinates are relative to <see cref="View.Bounds"/>.
/// </remarks>
/// <param name="mouseEvent"></param>
/// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
public virtual bool OnMouseEvent (MouseEvent mouseEvent)
protected internal virtual bool OnMouseLeave (MouseEvent mouseEvent)
{
if (!Enabled)
{
Expand All @@ -53,61 +78,61 @@ public virtual bool OnMouseEvent (MouseEvent mouseEvent)
}

var args = new MouseEventEventArgs (mouseEvent);
MouseLeave?.Invoke (this, args);

return args.Handled;
}

if (MouseEvent (mouseEvent))
// TODO: OnMouseEvent should not be public virtual, but protected.
/// <summary>Called when a mouse event occurs within the view's <see cref="Bounds"/>.</summary>
/// <remarks>
/// <para>
/// The coordinates are relative to <see cref="View.Bounds"/>.
/// </para>
/// </remarks>
/// <param name="mouseEvent"></param>
/// <returns><see langword="true"/>, if the event was handled, <see langword="false"/> otherwise.</returns>
protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent)
{
if (!Enabled)
{
return true;
}

if (mouseEvent.Flags == MouseFlags.Button1Clicked)
if (!CanBeVisible (this))
{
if (CanFocus && !HasFocus && SuperView is { })
{
SuperView.SetFocus (this);
SetNeedsDisplay ();
}

return OnMouseClick (args);
return false;
}

if (mouseEvent.Flags == MouseFlags.Button2Clicked)
{
return OnMouseClick (args);
}
var args = new MouseEventEventArgs (mouseEvent);

if (mouseEvent.Flags == MouseFlags.Button3Clicked)
// Clicked support for all buttons and single and double click
if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked)
|| mouseEvent.Flags.HasFlag (MouseFlags.Button2Clicked)
|| mouseEvent.Flags.HasFlag (MouseFlags.Button3Clicked)
|| mouseEvent.Flags.HasFlag (MouseFlags.Button4Clicked))
{
return OnMouseClick (args);
}

if (mouseEvent.Flags == MouseFlags.Button4Clicked)
if (mouseEvent.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
|| mouseEvent.Flags.HasFlag (MouseFlags.Button2DoubleClicked)
|| mouseEvent.Flags.HasFlag (MouseFlags.Button3DoubleClicked)
|| mouseEvent.Flags.HasFlag (MouseFlags.Button4DoubleClicked))
{
return OnMouseClick (args);
}

return false;
}

/// <inheritdoc/>
public override bool OnMouseLeave (MouseEvent mouseEvent)
{
if (!Enabled)
{
return true;
}

if (!CanBeVisible (this))
{
return false;
}

var args = new MouseEventEventArgs (mouseEvent);
MouseLeave?.Invoke (this, args);

return args.Handled || base.OnMouseLeave (mouseEvent);
}

/// <summary>Invokes the MouseClick event.</summary>
/// <remarks>
/// <para>
/// Called when the mouse is either clicked or double-clicked. Check
/// <see cref="MouseEvent.Flags"/> to see which button was clicked.
/// </para>
/// </remarks>
protected bool OnMouseClick (MouseEventEventArgs args)
{
if (!Enabled)
Expand All @@ -116,6 +141,10 @@ protected bool OnMouseClick (MouseEventEventArgs args)
}

MouseClick?.Invoke (this, args);
if (args.Handled)
{
return true;
}

return args.Handled;
}
Expand Down
29 changes: 6 additions & 23 deletions Terminal.Gui/Views/Button.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ public Button ()
KeyBindings.Add (Key.Enter, Command.HotKey);

TitleChanged += Button_TitleChanged;
MouseClick += Button_MouseClick;
}

private void Button_MouseClick (object sender, MouseEventEventArgs e)
{
e.Handled = InvokeCommand (Command.Accept) == true;
}

private void Button_TitleChanged (object sender, StateEventArgs<string> e)
Expand Down Expand Up @@ -99,29 +105,6 @@ public bool IsDefault
/// <summary></summary>
public bool NoPadding { get; set; }

/// <inheritdoc/>
public override bool MouseEvent (MouseEvent me)
{
if (me.Flags == MouseFlags.Button1Clicked)
{
if (CanFocus && Enabled)
{
if (!HasFocus)
{
SetFocus ();
SetNeedsDisplay ();
Draw ();
}

OnAccept ();
}

return true;
}

return false;
}

/// <inheritdoc/>
public override bool OnEnter (View view)
{
Expand Down
Loading

0 comments on commit eeced7e

Please sign in to comment.