Skip to content

Commit 966e2f7

Browse files
committed
Atttempting to merge gui-cs#4173
2 parents c25a4d5 + 6515d88 commit 966e2f7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+1434
-996
lines changed

Examples/UICatalog/Scenarios/Threading.cs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@ public class Threading : Scenario
1919
private ListView _logJob;
2020
private Action _sync;
2121

22+
private LogarithmicTimeout _logarithmicTimeout;
23+
private NumericUpDown _numberLog;
24+
private Button _btnLogarithmic;
25+
private object _timeoutObj;
26+
27+
private SmoothAcceleratingTimeout _smoothTimeout;
28+
private NumericUpDown _numberSmooth;
29+
private Button _btnSmooth;
30+
private object _timeoutObjSmooth;
31+
2232
public override void Main ()
2333
{
2434
Application.Init ();
@@ -82,6 +92,35 @@ public override void Main ()
8292

8393
var text = new TextField { X = 1, Y = 3, Width = 100, Text = "Type anything after press the button" };
8494

95+
_btnLogarithmic = new Button ()
96+
{
97+
X = 50,
98+
Y = 4,
99+
Text = "Start Log Counter"
100+
};
101+
_btnLogarithmic.Accepting += StartStopLogTimeout;
102+
103+
_numberLog = new NumericUpDown ()
104+
{
105+
X = Pos.Right (_btnLogarithmic),
106+
Y = 4,
107+
};
108+
109+
_btnSmooth = new Button ()
110+
{
111+
X = Pos.Right (_numberLog),
112+
Y = 4,
113+
Text = "Start Smooth Counter"
114+
};
115+
_btnSmooth.Accepting += StartStopSmoothTimeout;
116+
117+
_numberSmooth = new NumericUpDown ()
118+
{
119+
X = Pos.Right (_btnSmooth),
120+
Y = 4,
121+
};
122+
123+
85124
var btnAction = new Button { X = 80, Y = 10, Text = "Load Data Action" };
86125
btnAction.Accepting += (s, e) => _action.Invoke ();
87126
var btnLambda = new Button { X = 80, Y = 12, Text = "Load Data Lambda" };
@@ -107,6 +146,10 @@ public override void Main ()
107146
_btnActionCancel,
108147
_logJob,
109148
text,
149+
_btnLogarithmic,
150+
_numberLog,
151+
_btnSmooth,
152+
_numberSmooth,
110153
btnAction,
111154
btnLambda,
112155
btnHandler,
@@ -129,6 +172,51 @@ void Win_Loaded (object sender, EventArgs args)
129172
Application.Shutdown ();
130173
}
131174

175+
private bool LogTimeout ()
176+
{
177+
_numberLog.Value++;
178+
_logarithmicTimeout.AdvanceStage ();
179+
return true;
180+
}
181+
private bool SmoothTimeout ()
182+
{
183+
_numberSmooth.Value++;
184+
_smoothTimeout.AdvanceStage ();
185+
return true;
186+
}
187+
188+
private void StartStopLogTimeout (object sender, CommandEventArgs e)
189+
{
190+
if (_timeoutObj != null)
191+
{
192+
_btnLogarithmic.Text = "Start Log Counter";
193+
Application.TimedEvents.Remove (_timeoutObj);
194+
_timeoutObj = null;
195+
}
196+
else
197+
{
198+
_btnLogarithmic.Text = "Stop Log Counter";
199+
_logarithmicTimeout = new LogarithmicTimeout (TimeSpan.FromMilliseconds (500), LogTimeout);
200+
_timeoutObj = Application.TimedEvents.Add (_logarithmicTimeout);
201+
}
202+
}
203+
204+
private void StartStopSmoothTimeout (object sender, CommandEventArgs e)
205+
{
206+
if (_timeoutObjSmooth != null)
207+
{
208+
_btnSmooth.Text = "Start Smooth Counter";
209+
Application.TimedEvents.Remove (_timeoutObjSmooth);
210+
_timeoutObjSmooth = null;
211+
}
212+
else
213+
{
214+
_btnSmooth.Text = "Stop Smooth Counter";
215+
_smoothTimeout = new SmoothAcceleratingTimeout (TimeSpan.FromMilliseconds (500), TimeSpan.FromMilliseconds (50), 0.5, SmoothTimeout);
216+
_timeoutObjSmooth = Application.TimedEvents.Add (_smoothTimeout);
217+
}
218+
}
219+
132220
private async void CallLoadItemsAsync ()
133221
{
134222
_cancellationTokenSource = new CancellationTokenSource ();

Terminal.Gui/App/Application.Mouse.cs

Lines changed: 33 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -19,122 +19,16 @@ public static partial class Application // Mouse handling
1919
[ConfigurationProperty (Scope = typeof (SettingsScope))]
2020
public static bool IsMouseDisabled { get; set; }
2121

22-
/// <summary>Gets <see cref="View"/> that has registered to get continuous mouse button pressed events.</summary>
23-
public static View? WantContinuousButtonPressedView { get; internal set; }
24-
25-
/// <summary>
26-
/// Gets the view that grabbed the mouse (e.g. for dragging). When this is set, all mouse events will be routed to
27-
/// this view until the view calls <see cref="UngrabMouse"/> or the mouse is released.
28-
/// </summary>
29-
public static View? MouseGrabView { get; private set; }
30-
31-
/// <summary>Invoked when a view wants to grab the mouse; can be canceled.</summary>
32-
public static event EventHandler<GrabMouseEventArgs>? GrabbingMouse;
33-
34-
/// <summary>Invoked when a view wants un-grab the mouse; can be canceled.</summary>
35-
public static event EventHandler<GrabMouseEventArgs>? UnGrabbingMouse;
36-
37-
/// <summary>Invoked after a view has grabbed the mouse.</summary>
38-
public static event EventHandler<ViewEventArgs>? GrabbedMouse;
39-
40-
/// <summary>Invoked after a view has un-grabbed the mouse.</summary>
41-
public static event EventHandler<ViewEventArgs>? UnGrabbedMouse;
42-
4322
/// <summary>
44-
/// Grabs the mouse, forcing all mouse events to be routed to the specified view until <see cref="UngrabMouse"/>
45-
/// is called.
23+
/// Static reference to the current <see cref="IApplication"/> <see cref="IMouseGrabHandler"/>.
4624
/// </summary>
47-
/// <param name="view">View that will receive all mouse events until <see cref="UngrabMouse"/> is invoked.</param>
48-
public static void GrabMouse (View? view)
25+
public static IMouseGrabHandler MouseGrabHandler
4926
{
50-
if (view is null || RaiseGrabbingMouseEvent (view))
51-
{
52-
return;
53-
}
54-
55-
RaiseGrabbedMouseEvent (view);
56-
57-
if (Initialized)
58-
{
59-
// MouseGrabView is a static; only set if the application is initialized.
60-
MouseGrabView = view;
61-
}
27+
get => ApplicationImpl.Instance.MouseGrabHandler;
28+
set => ApplicationImpl.Instance.MouseGrabHandler = value ??
29+
throw new ArgumentNullException (nameof (value));
6230
}
6331

64-
/// <summary>Releases the mouse grab, so mouse events will be routed to the view on which the mouse is.</summary>
65-
public static void UngrabMouse ()
66-
{
67-
if (MouseGrabView is null)
68-
{
69-
return;
70-
}
71-
72-
#if DEBUG_IDISPOSABLE
73-
if (View.EnableDebugIDisposableAsserts)
74-
{
75-
ObjectDisposedException.ThrowIf (MouseGrabView.WasDisposed, MouseGrabView);
76-
}
77-
#endif
78-
79-
if (!RaiseUnGrabbingMouseEvent (MouseGrabView))
80-
{
81-
View view = MouseGrabView;
82-
MouseGrabView = null;
83-
RaiseUnGrabbedMouseEvent (view);
84-
}
85-
}
86-
87-
/// <exception cref="Exception">A delegate callback throws an exception.</exception>
88-
private static bool RaiseGrabbingMouseEvent (View? view)
89-
{
90-
if (view is null)
91-
{
92-
return false;
93-
}
94-
95-
var evArgs = new GrabMouseEventArgs (view);
96-
GrabbingMouse?.Invoke (view, evArgs);
97-
98-
return evArgs.Cancel;
99-
}
100-
101-
/// <exception cref="Exception">A delegate callback throws an exception.</exception>
102-
private static bool RaiseUnGrabbingMouseEvent (View? view)
103-
{
104-
if (view is null)
105-
{
106-
return false;
107-
}
108-
109-
var evArgs = new GrabMouseEventArgs (view);
110-
UnGrabbingMouse?.Invoke (view, evArgs);
111-
112-
return evArgs.Cancel;
113-
}
114-
115-
/// <exception cref="Exception">A delegate callback throws an exception.</exception>
116-
private static void RaiseGrabbedMouseEvent (View? view)
117-
{
118-
if (view is null)
119-
{
120-
return;
121-
}
122-
123-
GrabbedMouse?.Invoke (view, new (view));
124-
}
125-
126-
/// <exception cref="Exception">A delegate callback throws an exception.</exception>
127-
private static void RaiseUnGrabbedMouseEvent (View? view)
128-
{
129-
if (view is null)
130-
{
131-
return;
132-
}
133-
134-
UnGrabbedMouse?.Invoke (view, new (view));
135-
}
136-
137-
13832
/// <summary>
13933
/// INTERNAL API: Called when a mouse event is raised by the driver. Determines the view under the mouse and
14034
/// calls the appropriate View mouse event handlers.
@@ -199,15 +93,6 @@ internal static void RaiseMouseEvent (MouseEventArgs mouseEvent)
19993
return;
20094
}
20195

202-
if (Initialized)
203-
{
204-
WantContinuousButtonPressedView = deepestViewUnderMouse switch
205-
{
206-
{ WantContinuousButtonPressed: true } => deepestViewUnderMouse,
207-
_ => null
208-
};
209-
}
210-
21196
// May be null before the prior condition or the condition may set it as null.
21297
// So, the checking must be outside the prior condition.
21398
if (deepestViewUnderMouse is null)
@@ -259,12 +144,7 @@ internal static void RaiseMouseEvent (MouseEventArgs mouseEvent)
259144

260145
RaiseMouseEnterLeaveEvents (viewMouseEvent.ScreenPosition, currentViewsUnderMouse);
261146

262-
if (Initialized)
263-
{
264-
WantContinuousButtonPressedView = deepestViewUnderMouse.WantContinuousButtonPressed ? deepestViewUnderMouse : null;
265-
}
266-
267-
while (deepestViewUnderMouse.NewMouseEvent (viewMouseEvent) is not true && MouseGrabView is not { })
147+
while (deepestViewUnderMouse.NewMouseEvent (viewMouseEvent) is not true && MouseGrabHandler.MouseGrabView is not { })
268148
{
269149
if (deepestViewUnderMouse is Adornment adornmentView)
270150
{
@@ -316,42 +196,39 @@ internal static void RaiseMouseEvent (MouseEventArgs mouseEvent)
316196

317197
internal static bool HandleMouseGrab (View? deepestViewUnderMouse, MouseEventArgs mouseEvent)
318198
{
319-
if (MouseGrabView is null)
199+
if (MouseGrabHandler.MouseGrabView is { })
320200
{
321-
return false;
322-
}
323-
324201
#if DEBUG_IDISPOSABLE
325-
if (View.EnableDebugIDisposableAsserts && MouseGrabView.WasDisposed)
326-
{
327-
throw new ObjectDisposedException (MouseGrabView.GetType ().FullName);
328-
}
202+
if (View.EnableDebugIDisposableAsserts && MouseGrabHandler.MouseGrabView.WasDisposed)
203+
{
204+
throw new ObjectDisposedException (MouseGrabHandler.MouseGrabView.GetType ().FullName);
205+
}
329206
#endif
330207

331-
// If the mouse is grabbed, send the event to the view that grabbed it.
332-
// The coordinates are relative to the Bounds of the view that grabbed the mouse.
333-
Point frameLoc = MouseGrabView.ScreenToViewport (mouseEvent.ScreenPosition);
208+
// If the mouse is grabbed, send the event to the view that grabbed it.
209+
// The coordinates are relative to the Bounds of the view that grabbed the mouse.
210+
Point frameLoc = MouseGrabHandler.MouseGrabView.ScreenToViewport (mouseEvent.ScreenPosition);
334211

335-
var viewRelativeMouseEvent = new MouseEventArgs
336-
{
337-
Position = frameLoc,
338-
Flags = mouseEvent.Flags,
339-
ScreenPosition = mouseEvent.ScreenPosition,
340-
View = deepestViewUnderMouse ?? MouseGrabView
341-
};
342-
343-
//Logging.Debug ($"{deepestViewUnderMouse!.Id};{viewRelativeMouseEvent.Flags};{viewRelativeMouseEvent.Position};{MouseGrabView.Id}");
344-
if (MouseGrabView?.NewMouseEvent (viewRelativeMouseEvent) is true || viewRelativeMouseEvent.IsSingleDoubleOrTripleClicked)
345-
{
346-
// If the view that grabbed the mouse handled the event OR it was a click we are done.
347-
return true;
348-
}
212+
var viewRelativeMouseEvent = new MouseEventArgs
213+
{
214+
Position = frameLoc,
215+
Flags = mouseEvent.Flags,
216+
ScreenPosition = mouseEvent.ScreenPosition,
217+
View = deepestViewUnderMouse ?? MouseGrabHandler.MouseGrabView
218+
};
349219

350-
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
351-
if (MouseGrabView is null && deepestViewUnderMouse is Adornment)
352-
{
353-
// The view that grabbed the mouse has been disposed
354-
return true;
220+
//System.Diagnostics.Debug.WriteLine ($"{nme.Flags};{nme.X};{nme.Y};{mouseGrabView}");
221+
if (MouseGrabHandler.MouseGrabView?.NewMouseEvent (viewRelativeMouseEvent) is true || viewRelativeMouseEvent.IsSingleDoubleOrTripleClicked)
222+
{
223+
return true;
224+
}
225+
226+
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
227+
if (MouseGrabHandler.MouseGrabView is null && deepestViewUnderMouse is Adornment)
228+
{
229+
// The view that grabbed the mouse has been disposed
230+
return true;
231+
}
355232
}
356233

357234
return false;

Terminal.Gui/App/Application.Run.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,9 @@ public static RunState Begin (Toplevel toplevel)
8989
//#endif
9090

9191
// Ensure the mouse is ungrabbed.
92-
if (MouseGrabView is { })
92+
if (MouseGrabHandler.MouseGrabView is { })
9393
{
94-
UngrabMouse ();
95-
MouseGrabView = null;
94+
MouseGrabHandler.UngrabMouse ();
9695
}
9796

9897
var rs = new RunState (toplevel);
@@ -366,7 +365,7 @@ public static T Run<T> (Func<Exception, bool>? errorHandler = null, IConsoleDriv
366365
/// Alternatively, to have a program control the main loop and process events manually, call
367366
/// <see cref="Begin(Toplevel)"/> to set things up manually and then repeatedly call
368367
/// <see cref="RunLoop(RunState)"/> with the wait parameter set to false. By doing this the
369-
/// <see cref="RunLoop(RunState)"/> method will only process any pending events, timers, idle handlers and then
368+
/// <see cref="RunLoop(RunState)"/> method will only process any pending events, timers handlers and then
370369
/// return control immediately.
371370
/// </para>
372371
/// <para>

0 commit comments

Comments
 (0)