namespace Terminal.Gui;
public partial class View
{
///
/// Gets or sets whether the will highlight the view visually when the mouse button is pressed/released.
///
public bool HighlightOnPress { get; set; }
/// Gets or sets a value indicating whether this want continuous button pressed event.
public virtual bool WantContinuousButtonPressed { get; set; }
/// Gets or sets a value indicating whether this wants mouse position reports.
/// if want mouse position reports; otherwise, .
public virtual bool WantMousePositionReports { get; set; }
/// Event fired when a mouse event occurs.
///
///
/// The coordinates are relative to .
///
///
public event EventHandler MouseEvent;
/// Event fired when a mouse click occurs.
///
///
/// Fired when the mouse is either clicked or double-clicked. Check
/// to see which button was clicked.
///
///
/// The coordinates are relative to .
///
///
public event EventHandler MouseClick;
/// Event fired when the mouse moves into the View's .
public event EventHandler MouseEnter;
/// Event fired when the mouse leaves the View's .
public event EventHandler MouseLeave;
// TODO: OnMouseEnter should not be public virtual, but protected.
///
/// Called when the mouse enters the View's . The view will now receive mouse events until the mouse leaves
/// the view. At which time, will be called.
///
///
/// The coordinates are relative to .
///
///
/// , if the event was handled, otherwise.
protected internal virtual bool OnMouseEnter (MouseEvent mouseEvent)
{
if (!Enabled)
{
return true;
}
if (!CanBeVisible (this))
{
return false;
}
var args = new MouseEventEventArgs (mouseEvent);
MouseEnter?.Invoke (this, args);
return args.Handled;
}
// TODO: OnMouseLeave should not be public virtual, but protected.
///
/// Called when the mouse has moved out of the View's . The view will no longer receive mouse events (until the
/// mouse moves within the view again and is called).
///
///
/// The coordinates are relative to .
///
///
/// , if the event was handled, otherwise.
protected internal virtual 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;
}
[CanBeNull]
private ColorScheme _savedColorScheme;
// TODO: OnMouseEvent should not be public virtual, but protected.
/// Called when a mouse event occurs within the view's .
///
///
/// The coordinates are relative to .
///
///
///
/// , if the event was handled, otherwise.
protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent)
{
if (!Enabled)
{
// A disabled view should not eat mouse events
return false;
}
if (!CanBeVisible (this))
{
return false;
}
var args = new MouseEventEventArgs (mouseEvent);
// Default behavior is to invoke Accept (via HotKey) on clicked.
if ((!WantContinuousButtonPressed &&
Application.MouseGrabView != this &&
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.HasFlag (MouseFlags.Button1Pressed))
{
// If WantContinuousButtonPressed is true, and this is not the first pressed event,
// invoke Accept (via HotKey)
if (WantContinuousButtonPressed && Application.MouseGrabView == this)
{
return OnMouseClick (args);
}
// The first time we get pressed event, grab the mouse and invert the colors
if (Application.MouseGrabView != this)
{
Application.GrabMouse (this);
_savedColorScheme = ColorScheme;
if (HighlightOnPress && ColorScheme is { })
{
if (CanFocus)
{
// TODO: Make the inverted color configurable
var cs = new ColorScheme (ColorScheme)
{
Focus = new Attribute (ColorScheme.Normal.Foreground, ColorScheme.Focus.Background)
};
ColorScheme = cs;
}
else
{
var cs = new ColorScheme (ColorScheme)
{
Normal = new Attribute (ColorScheme.Focus.Background, ColorScheme.Normal.Foreground)
};
ColorScheme = cs;
}
}
if (CanFocus){
// Set the focus, but don't invoke Accept
SetFocus ();
}
}
}
if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Released))
{
// When the mouse is released, if WantContinuousButtonPressed is set, invoke Accept one last time.
if (WantContinuousButtonPressed)
{
OnMouseClick (args);
}
if (Application.MouseGrabView == this)
{
Application.UngrabMouse ();
if (HighlightOnPress && _savedColorScheme is { })
{
ColorScheme = _savedColorScheme;
_savedColorScheme = null;
}
}
}
//// 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))
//{
// OnMouseClick (args);
//}
//if (mouseEvent.Flags.HasFlag (MouseFlags.Button1DoubleClicked)
// || mouseEvent.Flags.HasFlag (MouseFlags.Button2DoubleClicked)
// || mouseEvent.Flags.HasFlag (MouseFlags.Button3DoubleClicked)
// || mouseEvent.Flags.HasFlag (MouseFlags.Button4DoubleClicked))
//{
// OnMouseClick (args);
//}
if (args.Handled != true)
{
MouseEvent?.Invoke (this, args);
}
return args.Handled == true;
}
/// Invokes the MouseClick event.
///
///
/// Called when the mouse is either clicked or double-clicked. Check
/// to see which button was clicked.
///
///
protected bool OnMouseClick (MouseEventEventArgs args)
{
if (!Enabled)
{
// QUESTION: Is this right? Should a disabled view eat mouse clicks?
args.Handled = true;
return true;
}
MouseClick?.Invoke (this, args);
if (args.Handled)
{
return true;
}
if (!HasFocus && CanFocus)
{
args.Handled = true;
SetFocus ();
}
return args.Handled;
}
}