From a7079edf779d3f526bda8e329cfbf8136a032a7e Mon Sep 17 00:00:00 2001 From: Tig Date: Sun, 31 Mar 2024 21:29:46 -0600 Subject: [PATCH 01/32] Prototype scrollbuttons in Padding for CharMap --- Terminal.Gui/View/ViewSubViews.cs | 21 +++++++++++-- Terminal.Gui/Views/Button.cs | 47 ++++++++++++++++++++++++++++- UICatalog/Scenarios/Buttons.cs | 19 ++++++++++++ UICatalog/Scenarios/CharacterMap.cs | 2 +- 4 files changed, 85 insertions(+), 4 deletions(-) diff --git a/Terminal.Gui/View/ViewSubViews.cs b/Terminal.Gui/View/ViewSubViews.cs index b9cacc711f..27570da2ca 100644 --- a/Terminal.Gui/View/ViewSubViews.cs +++ b/Terminal.Gui/View/ViewSubViews.cs @@ -31,8 +31,14 @@ public virtual View SuperView /// Adds a subview (child) to this view. /// + /// /// The Views that have been added to this view can be retrieved via the property. See also /// + /// + /// + /// Subviews will be disposed when this View is disposed. In other-words, calling this method causes + /// the lifecycle of the subviews to be transferred to this View. + /// /// public virtual void Add (View view) { @@ -92,8 +98,14 @@ public virtual void Add (View view) /// Adds the specified views (children) to the view. /// Array of one or more views (can be optional parameter). /// + /// /// The Views that have been added to this view can be retrieved via the property. See also - /// + /// and . + /// + /// + /// Subviews will be disposed when this View is disposed. In other-words, calling this method causes + /// the lifecycle of the subviews to be transferred to this View. + /// /// public void Add (params View [] views) { @@ -185,7 +197,12 @@ public virtual void OnRemoved (SuperViewChangedEventArgs e) } /// Removes a subview added via or from this View. - /// + /// + /// + /// Normally Subviews will be disposed when this View is disposed. Removing a Subview causes ownership of the Subview's + /// lifecycle to be transferred to the caller; the caller muse call . + /// + /// public virtual void Remove (View view) { if (view is null || _subviews is null) diff --git a/Terminal.Gui/Views/Button.cs b/Terminal.Gui/Views/Button.cs index f74c3de0e8..43b9837e8f 100644 --- a/Terminal.Gui/Views/Button.cs +++ b/Terminal.Gui/Views/Button.cs @@ -58,7 +58,52 @@ public Button () KeyBindings.Add (Key.Enter, Command.HotKey); TitleChanged += Button_TitleChanged; - MouseClick += Button_MouseClick; + MouseEvent += Button_MouseEvent; + //MouseClick += Button_MouseClick; + } + + private Attribute _originalNormal; + + private void Button_MouseEvent (object sender, MouseEventEventArgs e) + { + if (e.MouseEvent.Flags == MouseFlags.Button1Pressed) + { + if (Application.MouseGrabView == this) + { + e.Handled = InvokeCommand (Command.HotKey) == true; + + return; + } + Application.GrabMouse(this); + + _originalNormal = ColorScheme.Normal; + var cs = new ColorScheme (ColorScheme) + { + Normal = ColorScheme.HotFocus + }; + ColorScheme = cs; + } + + if (e.MouseEvent.Flags == MouseFlags.Button1Released) + { + Application.UngrabMouse (); + var cs = new ColorScheme (ColorScheme) + { + Normal = _originalNormal + }; + ColorScheme = cs; + + e.Handled = InvokeCommand (Command.HotKey) == true; + + return; + } + } + + /// + public override bool OnLeave (View view) + { + //Application.UngrabMouse(); + return base.OnLeave (view); } private void Button_MouseClick (object sender, MouseEventEventArgs e) diff --git a/UICatalog/Scenarios/Buttons.cs b/UICatalog/Scenarios/Buttons.cs index 78787e83c6..2702568eb0 100644 --- a/UICatalog/Scenarios/Buttons.cs +++ b/UICatalog/Scenarios/Buttons.cs @@ -286,6 +286,25 @@ string MoveHotkey (string txt) moveUnicodeHotKeyBtn.Accept += (s, e) => { moveUnicodeHotKeyBtn.Text = MoveHotkey (moveUnicodeHotKeyBtn.Text); }; Win.Add (moveUnicodeHotKeyBtn); + label = new Label () + { + X = 0, + Y = Pos.Bottom (moveUnicodeHotKeyBtn) + 1, + Title = "_1x1 Button:", + }; + var oneByOne = new Button () + { + AutoSize = false, + X = Pos.Right(label)+1, + Y = Pos.Top (label), + Height = 1, + Width = 1, + NoPadding = true, + NoDecorations = true, + Title = CM.Glyphs.UpArrow.ToString(), + }; + Win.Add (label, oneByOne); + radioGroup.SelectedItemChanged += (s, args) => { switch (args.SelectedItem) diff --git a/UICatalog/Scenarios/CharacterMap.cs b/UICatalog/Scenarios/CharacterMap.cs index bcac93b9b5..c8ba611001 100644 --- a/UICatalog/Scenarios/CharacterMap.cs +++ b/UICatalog/Scenarios/CharacterMap.cs @@ -1,4 +1,4 @@ -#define DRAW_CONTENT +#define DRAW_CONTENT //#define BASE_DRAW_CONTENT using System; From f65c49a8583a8da604d765e2cba449d072a371d7 Mon Sep 17 00:00:00 2001 From: Tig Date: Sun, 31 Mar 2024 22:13:48 -0600 Subject: [PATCH 02/32] More Prototype scrollbuttons in Padding for CharMap --- Terminal.Gui/View/ViewDrawing.cs | 11 +++++++++-- Terminal.Gui/Views/Button.cs | 27 +++++++++++++-------------- UICatalog/Scenarios/Buttons.cs | 2 +- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/Terminal.Gui/View/ViewDrawing.cs b/Terminal.Gui/View/ViewDrawing.cs index 2d8d319186..37094bbaea 100644 --- a/Terminal.Gui/View/ViewDrawing.cs +++ b/Terminal.Gui/View/ViewDrawing.cs @@ -524,12 +524,12 @@ public void SetNeedsDisplay (Rectangle region) _needsDisplayRect = new (x, y, w, h); } - SuperView?.SetSubViewNeedsDisplay (); - Margin?.SetNeedsDisplay (); Border?.SetNeedsDisplay (); Padding?.SetNeedsDisplay (); + SuperView?.SetSubViewNeedsDisplay (); + foreach (View subview in Subviews) { if (subview.Frame.IntersectsWith (region)) @@ -550,6 +550,13 @@ public void SetSubViewNeedsDisplay () if (SuperView is { SubViewNeedsDisplay: false }) { SuperView.SetSubViewNeedsDisplay (); + + return; + } + + if (this is Adornment adornment) + { + adornment.Parent?.SetSubViewNeedsDisplay (); } } diff --git a/Terminal.Gui/Views/Button.cs b/Terminal.Gui/Views/Button.cs index 43b9837e8f..32cef242c2 100644 --- a/Terminal.Gui/Views/Button.cs +++ b/Terminal.Gui/Views/Button.cs @@ -62,7 +62,8 @@ public Button () //MouseClick += Button_MouseClick; } - private Attribute _originalNormal; + [CanBeNull] + private ColorScheme _savedColorScheme; private void Button_MouseEvent (object sender, MouseEventEventArgs e) { @@ -71,31 +72,29 @@ private void Button_MouseEvent (object sender, MouseEventEventArgs e) if (Application.MouseGrabView == this) { e.Handled = InvokeCommand (Command.HotKey) == true; - return; } + + SetFocus(); Application.GrabMouse(this); - _originalNormal = ColorScheme.Normal; - var cs = new ColorScheme (ColorScheme) - { - Normal = ColorScheme.HotFocus - }; + _savedColorScheme = ColorScheme; + var cs = new ColorScheme (new Attribute (ColorScheme.Normal.Background, ColorScheme.Normal.Foreground)); ColorScheme = cs; } - if (e.MouseEvent.Flags == MouseFlags.Button1Released) + if (e.MouseEvent.Flags.HasFlag(MouseFlags.Button1Released)) { Application.UngrabMouse (); - var cs = new ColorScheme (ColorScheme) - { - Normal = _originalNormal - }; - ColorScheme = cs; e.Handled = InvokeCommand (Command.HotKey) == true; - return; + if (_savedColorScheme is { }) + { + ColorScheme = _savedColorScheme; + } + + _savedColorScheme = null; } } diff --git a/UICatalog/Scenarios/Buttons.cs b/UICatalog/Scenarios/Buttons.cs index 2702568eb0..7987711483 100644 --- a/UICatalog/Scenarios/Buttons.cs +++ b/UICatalog/Scenarios/Buttons.cs @@ -301,7 +301,7 @@ string MoveHotkey (string txt) Width = 1, NoPadding = true, NoDecorations = true, - Title = CM.Glyphs.UpArrow.ToString(), + Title = $"{CM.Glyphs.UpArrow}", }; Win.Add (label, oneByOne); From b980f07688b1054c4991811c2596cc0a12b87893 Mon Sep 17 00:00:00 2001 From: Tig Date: Mon, 1 Apr 2024 07:05:27 -0600 Subject: [PATCH 03/32] Test button --- UICatalog/Scenarios/Buttons.cs | 39 +++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/UICatalog/Scenarios/Buttons.cs b/UICatalog/Scenarios/Buttons.cs index 7987711483..15df072b01 100644 --- a/UICatalog/Scenarios/Buttons.cs +++ b/UICatalog/Scenarios/Buttons.cs @@ -290,10 +290,11 @@ string MoveHotkey (string txt) { X = 0, Y = Pos.Bottom (moveUnicodeHotKeyBtn) + 1, - Title = "_1x1 Button:", + Title = "_Numeric Up/Down:", }; - var oneByOne = new Button () + var downButton = new Button () { + CanFocus = false, AutoSize = false, X = Pos.Right(label)+1, Y = Pos.Top (label), @@ -301,9 +302,41 @@ string MoveHotkey (string txt) Width = 1, NoPadding = true, NoDecorations = true, + Title = $"{CM.Glyphs.DownArrow}", + WantContinuousButtonPressed = true, + }; + + var numericEdit = new TextField () + { + Text = "1966", + X = Pos.Right (downButton), + Y = Pos.Top (downButton), + Width = 5, + Height = 1, + }; + var upButton = new Button () + { + CanFocus = false, + AutoSize = false, + X = Pos.Right (numericEdit), + Y = Pos.Top (numericEdit), + Height = 1, + Width = 1, + NoPadding = true, + NoDecorations = true, Title = $"{CM.Glyphs.UpArrow}", + WantContinuousButtonPressed = true, }; - Win.Add (label, oneByOne); + downButton.Accept += (s, e) => + { + numericEdit.Text = $"{int.Parse(numericEdit.Text) - 1}"; + }; + upButton.Accept += (s, e) => + { + numericEdit.Text = $"{int.Parse (numericEdit.Text) + 1}"; + }; + + Win.Add (label, downButton, numericEdit, upButton); radioGroup.SelectedItemChanged += (s, args) => { From ca7b8bb0ee779e0f6b7a7cc73d0227f0a23b19dd Mon Sep 17 00:00:00 2001 From: Tig Date: Mon, 1 Apr 2024 09:19:03 -0600 Subject: [PATCH 04/32] fixed OnMouseClick logic --- Terminal.Gui/View/ViewMouse.cs | 11 ++++++++--- Terminal.Gui/Views/Button.cs | 10 ++++++++++ UnitTests/TestHelpers.cs | 1 + 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Terminal.Gui/View/ViewMouse.cs b/Terminal.Gui/View/ViewMouse.cs index 90422ecec6..81961441ec 100644 --- a/Terminal.Gui/View/ViewMouse.cs +++ b/Terminal.Gui/View/ViewMouse.cs @@ -120,7 +120,7 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) || mouseEvent.Flags.HasFlag (MouseFlags.Button3Clicked) || mouseEvent.Flags.HasFlag (MouseFlags.Button4Clicked)) { - return OnMouseClick (args); + OnMouseClick (args); } if (mouseEvent.Flags.HasFlag (MouseFlags.Button1DoubleClicked) @@ -128,10 +128,13 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) || mouseEvent.Flags.HasFlag (MouseFlags.Button3DoubleClicked) || mouseEvent.Flags.HasFlag (MouseFlags.Button4DoubleClicked)) { - return OnMouseClick (args); + OnMouseClick (args); } - MouseEvent?.Invoke (this, args); + if (args.Handled != true) + { + MouseEvent?.Invoke (this, args); + } return args.Handled == true; } @@ -147,6 +150,7 @@ protected bool OnMouseClick (MouseEventEventArgs args) { if (!Enabled) { + args.Handled = true; return true; } @@ -158,6 +162,7 @@ protected bool OnMouseClick (MouseEventEventArgs args) if (!HasFocus && CanFocus) { + args.Handled = true; SetFocus (); } diff --git a/Terminal.Gui/Views/Button.cs b/Terminal.Gui/Views/Button.cs index 32cef242c2..5ceef8b9c5 100644 --- a/Terminal.Gui/Views/Button.cs +++ b/Terminal.Gui/Views/Button.cs @@ -67,6 +67,16 @@ public Button () private void Button_MouseEvent (object sender, MouseEventEventArgs e) { + if (e.MouseEvent.Flags.HasFlag(MouseFlags.Button1Clicked)) + { + if (Application.MouseGrabView != this) + { + e.Handled = InvokeCommand (Command.HotKey) == true; + + return; + } + } + if (e.MouseEvent.Flags == MouseFlags.Button1Pressed) { if (Application.MouseGrabView == this) diff --git a/UnitTests/TestHelpers.cs b/UnitTests/TestHelpers.cs index 5842b3a388..83187ebf44 100644 --- a/UnitTests/TestHelpers.cs +++ b/UnitTests/TestHelpers.cs @@ -74,6 +74,7 @@ public override void After (MethodInfo methodUnderTest) if (AutoInit) { + // TODO: This Dispose call is here until all unit tests that don't correctly dispose Toplevel's they create are fixed. Application.Top?.Dispose (); Application.Shutdown (); #if DEBUG_IDISPOSABLE From cf4ead194f88a4beaf76f0d5316ec8f0be16c08b Mon Sep 17 00:00:00 2001 From: Tig Date: Mon, 1 Apr 2024 12:27:51 -0600 Subject: [PATCH 05/32] Initial commit --- UICatalog/Scenarios/Buttons.cs | 107 ++++++++++++++++++++------------- 1 file changed, 64 insertions(+), 43 deletions(-) diff --git a/UICatalog/Scenarios/Buttons.cs b/UICatalog/Scenarios/Buttons.cs index 15df072b01..df0bd44a43 100644 --- a/UICatalog/Scenarios/Buttons.cs +++ b/UICatalog/Scenarios/Buttons.cs @@ -286,11 +286,54 @@ string MoveHotkey (string txt) moveUnicodeHotKeyBtn.Accept += (s, e) => { moveUnicodeHotKeyBtn.Text = MoveHotkey (moveUnicodeHotKeyBtn.Text); }; Win.Add (moveUnicodeHotKeyBtn); + radioGroup.SelectedItemChanged += (s, args) => + { + switch (args.SelectedItem) + { + case 0: + moveBtn.TextAlignment = TextAlignment.Left; + sizeBtn.TextAlignment = TextAlignment.Left; + moveBtnA.TextAlignment = TextAlignment.Left; + sizeBtnA.TextAlignment = TextAlignment.Left; + moveHotKeyBtn.TextAlignment = TextAlignment.Left; + moveUnicodeHotKeyBtn.TextAlignment = TextAlignment.Left; + + break; + case 1: + moveBtn.TextAlignment = TextAlignment.Right; + sizeBtn.TextAlignment = TextAlignment.Right; + moveBtnA.TextAlignment = TextAlignment.Right; + sizeBtnA.TextAlignment = TextAlignment.Right; + moveHotKeyBtn.TextAlignment = TextAlignment.Right; + moveUnicodeHotKeyBtn.TextAlignment = TextAlignment.Right; + + break; + case 2: + moveBtn.TextAlignment = TextAlignment.Centered; + sizeBtn.TextAlignment = TextAlignment.Centered; + moveBtnA.TextAlignment = TextAlignment.Centered; + sizeBtnA.TextAlignment = TextAlignment.Centered; + moveHotKeyBtn.TextAlignment = TextAlignment.Centered; + moveUnicodeHotKeyBtn.TextAlignment = TextAlignment.Centered; + + break; + case 3: + moveBtn.TextAlignment = TextAlignment.Justified; + sizeBtn.TextAlignment = TextAlignment.Justified; + moveBtnA.TextAlignment = TextAlignment.Justified; + sizeBtnA.TextAlignment = TextAlignment.Justified; + moveHotKeyBtn.TextAlignment = TextAlignment.Justified; + moveUnicodeHotKeyBtn.TextAlignment = TextAlignment.Justified; + + break; + } + }; + label = new Label () { X = 0, Y = Pos.Bottom (moveUnicodeHotKeyBtn) + 1, - Title = "_Numeric Up/Down:", + Title = "_Numeric Up/Down (press-and-hold):", }; var downButton = new Button () { @@ -338,48 +381,26 @@ string MoveHotkey (string txt) Win.Add (label, downButton, numericEdit, upButton); - radioGroup.SelectedItemChanged += (s, args) => - { - switch (args.SelectedItem) - { - case 0: - moveBtn.TextAlignment = TextAlignment.Left; - sizeBtn.TextAlignment = TextAlignment.Left; - moveBtnA.TextAlignment = TextAlignment.Left; - sizeBtnA.TextAlignment = TextAlignment.Left; - moveHotKeyBtn.TextAlignment = TextAlignment.Left; - moveUnicodeHotKeyBtn.TextAlignment = TextAlignment.Left; - - break; - case 1: - moveBtn.TextAlignment = TextAlignment.Right; - sizeBtn.TextAlignment = TextAlignment.Right; - moveBtnA.TextAlignment = TextAlignment.Right; - sizeBtnA.TextAlignment = TextAlignment.Right; - moveHotKeyBtn.TextAlignment = TextAlignment.Right; - moveUnicodeHotKeyBtn.TextAlignment = TextAlignment.Right; - - break; - case 2: - moveBtn.TextAlignment = TextAlignment.Centered; - sizeBtn.TextAlignment = TextAlignment.Centered; - moveBtnA.TextAlignment = TextAlignment.Centered; - sizeBtnA.TextAlignment = TextAlignment.Centered; - moveHotKeyBtn.TextAlignment = TextAlignment.Centered; - moveUnicodeHotKeyBtn.TextAlignment = TextAlignment.Centered; - - break; - case 3: - moveBtn.TextAlignment = TextAlignment.Justified; - sizeBtn.TextAlignment = TextAlignment.Justified; - moveBtnA.TextAlignment = TextAlignment.Justified; - sizeBtnA.TextAlignment = TextAlignment.Justified; - moveHotKeyBtn.TextAlignment = TextAlignment.Justified; - moveUnicodeHotKeyBtn.TextAlignment = TextAlignment.Justified; - - break; - } - }; + label = new Label () + { + X = 0, + Y = Pos.Bottom (label) + 1, + Title = "_Repeat (CanFocus; press-and-hold):", + }; + int acceptCount = 0; + var repeatButton = new Button () + { + X = Pos.Right (label) + 1, + Y = Pos.Top (label), + Title = $"Accept Count: {acceptCount}", + WantContinuousButtonPressed = true, + }; + repeatButton.Accept += (s, e) => + { + repeatButton.Title = $"Accept Count: {++acceptCount}"; + }; + + Win.Add(label, repeatButton); Top.Ready += (s, e) => radioGroup.Refresh (); } From f3c3825f349049f539f1416c8a4c0585203131c8 Mon Sep 17 00:00:00 2001 From: Tig Date: Mon, 1 Apr 2024 12:36:20 -0600 Subject: [PATCH 06/32] Init->Main in Buttons scenario --- UICatalog/Scenarios/Buttons.cs | 50 ++++++++++++++++------------- UICatalog/Scenarios/CharacterMap.cs | 3 -- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/UICatalog/Scenarios/Buttons.cs b/UICatalog/Scenarios/Buttons.cs index df0bd44a43..c03bbbb62d 100644 --- a/UICatalog/Scenarios/Buttons.cs +++ b/UICatalog/Scenarios/Buttons.cs @@ -9,21 +9,25 @@ namespace UICatalog.Scenarios; [ScenarioCategory ("Layout")] public class Buttons : Scenario { - public override void Setup () + public override void Main () { + Window main = new () + { + Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}", + }; // Add a label & text field so we can demo IsDefault var editLabel = new Label { X = 0, Y = 0, TabStop = true, Text = "TextField (to demo IsDefault):" }; - Win.Add (editLabel); + main.Add (editLabel); // Add a TextField using Absolute layout. var edit = new TextField { X = 31, Width = 15, HotKey = Key.Y.WithAlt }; - Win.Add (edit); + main.Add (edit); // This is the default button (IsDefault = true); if user presses ENTER in the TextField // the scenario will quit var defaultButton = new Button { X = Pos.Center (), Y = Pos.AnchorEnd (1), IsDefault = true, Text = "_Quit" }; defaultButton.Accept += (s, e) => Application.RequestStop (); - Win.Add (defaultButton); + main.Add (defaultButton); var swapButton = new Button { X = 50, Text = "S_wap Default (Absolute Layout)" }; @@ -32,7 +36,7 @@ public override void Setup () defaultButton.IsDefault = !defaultButton.IsDefault; swapButton.IsDefault = !swapButton.IsDefault; }; - Win.Add (swapButton); + main.Add (swapButton); static void DoMessage (Button button, string txt) { @@ -44,7 +48,7 @@ static void DoMessage (Button button, string txt) } var colorButtonsLabel = new Label { X = 0, Y = Pos.Bottom (editLabel) + 1, Text = "Color Buttons:" }; - Win.Add (colorButtonsLabel); + main.Add (colorButtonsLabel); View prev = colorButtonsLabel; @@ -63,7 +67,7 @@ static void DoMessage (Button button, string txt) Text = $"_{colorScheme.Key}" }; DoMessage (colorButton, colorButton.Text); - Win.Add (colorButton); + main.Add (colorButton); prev = colorButton; // BUGBUG: AutoSize is true and the X doesn't change @@ -72,7 +76,7 @@ static void DoMessage (Button button, string txt) Button button; - Win.Add ( + main.Add ( button = new Button { X = 2, @@ -84,16 +88,16 @@ static void DoMessage (Button button, string txt) DoMessage (button, button.Text); // Note the 'N' in 'Newline' will be the hotkey - Win.Add ( + main.Add ( button = new Button { X = 2, Y = Pos.Bottom (button) + 1, Text = "a Newline\nin the button" } ); button.Accept += (s, e) => MessageBox.Query ("Message", "Question?", "Yes", "No"); var textChanger = new Button { X = 2, Y = Pos.Bottom (button) + 1, Text = "Te_xt Changer" }; - Win.Add (textChanger); + main.Add (textChanger); textChanger.Accept += (s, e) => textChanger.Text += "!"; - Win.Add ( + main.Add ( button = new Button { X = Pos.Right (textChanger) + 2, @@ -106,13 +110,13 @@ static void DoMessage (Button button, string txt) { X = 2, Y = Pos.Bottom (button) + 1, ColorScheme = Colors.ColorSchemes ["Error"], Text = "Remove this button" }; - Win.Add (removeButton); + main.Add (removeButton); // This in interesting test case because `moveBtn` and below are laid out relative to this one! removeButton.Accept += (s, e) => { // Now this throw a InvalidOperationException on the TopologicalSort method as is expected. - //Win.Remove (removeButton); + //main.Remove (removeButton); removeButton.Visible = false; }; @@ -125,7 +129,7 @@ static void DoMessage (Button button, string txt) Height = 5, Title = "Computed Layout" }; - Win.Add (computedFrame); + main.Add (computedFrame); // Demonstrates how changing the View.Frame property can move Views var moveBtn = new Button @@ -176,7 +180,7 @@ static void DoMessage (Button button, string txt) Height = 5, Title = "Absolute Layout" }; - Win.Add (absoluteFrame); + main.Add (absoluteFrame); // Demonstrates how changing the View.Frame property can move Views var moveBtnA = new Button { ColorScheme = Colors.ColorSchemes ["Error"], Text = "Move This Button via Frame" }; @@ -213,7 +217,7 @@ static void DoMessage (Button button, string txt) { X = 2, Y = Pos.Bottom (computedFrame) + 1, Text = "Text Alignment (changes the four buttons above): " }; - Win.Add (label); + main.Add (label); var radioGroup = new RadioGroup { @@ -222,7 +226,7 @@ static void DoMessage (Button button, string txt) SelectedItem = 2, RadioLabels = new [] { "Left", "Right", "Centered", "Justified" } }; - Win.Add (radioGroup); + main.Add (radioGroup); // Demo changing hotkey string MoveHotkey (string txt) @@ -269,7 +273,7 @@ string MoveHotkey (string txt) Text = mhkb }; moveHotKeyBtn.Accept += (s, e) => { moveHotKeyBtn.Text = MoveHotkey (moveHotKeyBtn.Text); }; - Win.Add (moveHotKeyBtn); + main.Add (moveHotKeyBtn); var muhkb = " ~  s  gui.cs   master ↑10 = Сохранить"; @@ -284,7 +288,7 @@ string MoveHotkey (string txt) Text = muhkb }; moveUnicodeHotKeyBtn.Accept += (s, e) => { moveUnicodeHotKeyBtn.Text = MoveHotkey (moveUnicodeHotKeyBtn.Text); }; - Win.Add (moveUnicodeHotKeyBtn); + main.Add (moveUnicodeHotKeyBtn); radioGroup.SelectedItemChanged += (s, args) => { @@ -379,7 +383,7 @@ string MoveHotkey (string txt) numericEdit.Text = $"{int.Parse (numericEdit.Text) + 1}"; }; - Win.Add (label, downButton, numericEdit, upButton); + main.Add (label, downButton, numericEdit, upButton); label = new Label () { @@ -400,8 +404,10 @@ string MoveHotkey (string txt) repeatButton.Title = $"Accept Count: {++acceptCount}"; }; - Win.Add(label, repeatButton); + main.Add(label, repeatButton); - Top.Ready += (s, e) => radioGroup.Refresh (); + main.Ready += (s, e) => radioGroup.Refresh (); + Application.Run (main); + main.Dispose (); } } diff --git a/UICatalog/Scenarios/CharacterMap.cs b/UICatalog/Scenarios/CharacterMap.cs index c8ba611001..68b1ee098f 100644 --- a/UICatalog/Scenarios/CharacterMap.cs +++ b/UICatalog/Scenarios/CharacterMap.cs @@ -1,6 +1,3 @@ -#define DRAW_CONTENT - -//#define BASE_DRAW_CONTENT using System; using System.Collections.Generic; using System.ComponentModel; From d57b58be1a4b75e42fd8f95bbe80a6ebae8302a6 Mon Sep 17 00:00:00 2001 From: Tig Date: Mon, 1 Apr 2024 14:24:32 -0600 Subject: [PATCH 07/32] Updated ViewMouse unit tests --- Terminal.Gui/View/Adornment/Adornment.cs | 5 + Terminal.Gui/View/Adornment/Padding.cs | 7 +- Terminal.Gui/View/ViewMouse.cs | 4 +- Terminal.Gui/Views/ScrollView.cs | 6 + UICatalog/Scenarios/Buttons.cs | 2 +- UnitTests/TestHelpers.cs | 81 ++++++++ UnitTests/View/MouseTests.cs | 224 ++++++++++++++++++++++ UnitTests/Views/AllViewsTests.cs | 90 +-------- UnitTests/Views/ButtonTests.cs | 228 +++++++++-------------- 9 files changed, 418 insertions(+), 229 deletions(-) diff --git a/Terminal.Gui/View/Adornment/Adornment.cs b/Terminal.Gui/View/Adornment/Adornment.cs index 5fe40cab9a..b6277f326a 100644 --- a/Terminal.Gui/View/Adornment/Adornment.cs +++ b/Terminal.Gui/View/Adornment/Adornment.cs @@ -244,6 +244,11 @@ protected internal override bool OnMouseEnter (MouseEvent mouseEvent) /// , if the event was handled, otherwise. protected internal override bool OnMouseEvent (MouseEvent mouseEvent) { + if (Parent is null) + { + return false; + } + var args = new MouseEventEventArgs (mouseEvent); if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked)) diff --git a/Terminal.Gui/View/Adornment/Padding.cs b/Terminal.Gui/View/Adornment/Padding.cs index 3c2a645c12..d9d373de4d 100644 --- a/Terminal.Gui/View/Adornment/Padding.cs +++ b/Terminal.Gui/View/Adornment/Padding.cs @@ -52,13 +52,18 @@ public override ColorScheme ColorScheme /// , if the event was handled, otherwise. protected internal override bool OnMouseEvent (MouseEvent mouseEvent) { + if (Parent is null) + { + return false; + } + if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked)) { if (Parent.CanFocus && !Parent.HasFocus) { Parent.SetFocus (); Parent.SetNeedsDisplay (); - return true; + return mouseEvent.Handled = true; } } diff --git a/Terminal.Gui/View/ViewMouse.cs b/Terminal.Gui/View/ViewMouse.cs index 81961441ec..e78ede31ea 100644 --- a/Terminal.Gui/View/ViewMouse.cs +++ b/Terminal.Gui/View/ViewMouse.cs @@ -104,7 +104,8 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) { if (!Enabled) { - return true; + // A disabled view should not eat mouse events + return false; } if (!CanBeVisible (this)) @@ -150,6 +151,7 @@ protected bool OnMouseClick (MouseEventEventArgs args) { if (!Enabled) { + // QUESTION: Is this right? Should a disabled view eat mouse clicks? args.Handled = true; return true; } diff --git a/Terminal.Gui/Views/ScrollView.cs b/Terminal.Gui/Views/ScrollView.cs index 9bc14c3f8f..72ebcb3552 100644 --- a/Terminal.Gui/Views/ScrollView.cs +++ b/Terminal.Gui/Views/ScrollView.cs @@ -410,6 +410,12 @@ public override bool OnKeyDown (Key a) /// protected internal override bool OnMouseEvent (MouseEvent me) { + if (!Enabled) + { + // A disabled view should not eat mouse events + return false; + } + if (me.Flags == MouseFlags.WheeledDown && ShowVerticalScrollIndicator) { ScrollDown (1); diff --git a/UICatalog/Scenarios/Buttons.cs b/UICatalog/Scenarios/Buttons.cs index c03bbbb62d..e3c9b5ea25 100644 --- a/UICatalog/Scenarios/Buttons.cs +++ b/UICatalog/Scenarios/Buttons.cs @@ -396,7 +396,7 @@ string MoveHotkey (string txt) { X = Pos.Right (label) + 1, Y = Pos.Top (label), - Title = $"Accept Count: {acceptCount}", + Title = $"Accept Count (press-and-hold): {acceptCount}", WantContinuousButtonPressed = true, }; repeatButton.Accept += (s, e) => diff --git a/UnitTests/TestHelpers.cs b/UnitTests/TestHelpers.cs index 83187ebf44..e87450dd4f 100644 --- a/UnitTests/TestHelpers.cs +++ b/UnitTests/TestHelpers.cs @@ -729,6 +729,87 @@ public static View CreateView (Type type, ConstructorInfo ctor) return view; } + public static List GetAllViewClasses () + { + return typeof (View).Assembly.GetTypes () + .Where ( + myType => myType.IsClass + && !myType.IsAbstract + && myType.IsPublic + && myType.IsSubclassOf (typeof (View)) + ) + .ToList (); + } + + public static View CreateViewFromType (Type type, ConstructorInfo ctor) + { + View viewType = null; + + if (type.IsGenericType && type.IsTypeDefinition) + { + List gTypes = new (); + + foreach (Type args in type.GetGenericArguments ()) + { + gTypes.Add (typeof (object)); + } + + type = type.MakeGenericType (gTypes.ToArray ()); + + Assert.IsType (type, (View)Activator.CreateInstance (type)); + } + else + { + ParameterInfo [] paramsInfo = ctor.GetParameters (); + Type paramType; + List pTypes = new (); + + if (type.IsGenericType) + { + foreach (Type args in type.GetGenericArguments ()) + { + paramType = args.GetType (); + + if (args.Name == "T") + { + pTypes.Add (typeof (object)); + } + else + { + AddArguments (paramType, pTypes); + } + } + } + + foreach (ParameterInfo p in paramsInfo) + { + paramType = p.ParameterType; + + if (p.HasDefaultValue) + { + pTypes.Add (p.DefaultValue); + } + else + { + AddArguments (paramType, pTypes); + } + } + + if (type.IsGenericType && !type.IsTypeDefinition) + { + viewType = (View)Activator.CreateInstance (type); + Assert.IsType (type, viewType); + } + else + { + viewType = (View)ctor.Invoke (pTypes.ToArray ()); + Assert.IsType (type, viewType); + } + } + + return viewType; + } + [GeneratedRegex ("^\\s+", RegexOptions.Multiline)] private static partial Regex LeadingWhitespaceRegEx (); diff --git a/UnitTests/View/MouseTests.cs b/UnitTests/View/MouseTests.cs index ee37f895ee..067f5f4c83 100644 --- a/UnitTests/View/MouseTests.cs +++ b/UnitTests/View/MouseTests.cs @@ -94,4 +94,228 @@ public void WheeledLeft_WheeledRight (MouseFlags mouseFlags, MouseFlags expected view.OnMouseEvent (new MouseEvent () { Flags = mouseFlags }); Assert.Equal (mouseFlagsFromEvent, expectedMouseFlagsFromEvent); } + + public static TheoryData AllViews => TestHelpers.GetAllViewsTheoryData (); + + + [Theory] + [MemberData (nameof (AllViews))] + + public void AllViews_Enter_Leave_Events (View view, string viewName) + { + if (view == null) + { + output.WriteLine ($"Ignoring {viewName} - It's a Generic"); + return; + } + + if (!view.CanFocus) + { + output.WriteLine ($"Ignoring {viewName} - It can't focus."); + + return; + } + + if (view is Toplevel && ((Toplevel)view).Modal) + { + output.WriteLine ($"Ignoring {viewName} - It's a Modal Toplevel"); + + return; + } + + Application.Init (new FakeDriver ()); + + Toplevel top = new () + { + Height = 10, + Width = 10 + }; + + View otherView = new () + { + X = 0, Y = 0, + Height = 1, + Width = 1, + CanFocus = true, + }; + + view.AutoSize = false; + view.X = Pos.Right(otherView); + view.Y = 0; + view.Width = 10; + view.Height = 1; + + var nEnter = 0; + var nLeave = 0; + + view.Enter += (s, e) => nEnter++; + view.Leave += (s, e) => nLeave++; + + top.Add (view, otherView); + Application.Begin (top); + + // Start with the focus on our test view + view.SetFocus (); + + Assert.Equal (1, nEnter); + Assert.Equal (0, nLeave); + + // Use keyboard to navigate to next view (otherView). + if (view is TextView) + { + top.NewKeyDownEvent (Key.Tab.WithCtrl); + } + else if (view is DatePicker) + { + for (var i = 0; i < 4; i++) + { + top.NewKeyDownEvent (Key.Tab.WithCtrl); + } + } + else + { + top.NewKeyDownEvent (Key.Tab); + } + + Assert.Equal (1, nEnter); + Assert.Equal (1, nLeave); + + top.NewKeyDownEvent (Key.Tab); + + Assert.Equal (2, nEnter); + Assert.Equal (1, nLeave); + + top.Dispose (); + Application.Shutdown (); + } + + + [Theory] + [MemberData (nameof (AllViews))] + + public void AllViews_Enter_Leave_Events_Visible_False (View view, string viewName) + { + if (view == null) + { + output.WriteLine ($"Ignoring {viewName} - It's a Generic"); + return; + } + + if (!view.CanFocus) + { + output.WriteLine ($"Ignoring {viewName} - It can't focus."); + + return; + } + + if (view is Toplevel && ((Toplevel)view).Modal) + { + output.WriteLine ($"Ignoring {viewName} - It's a Modal Toplevel"); + + return; + } + + Application.Init (new FakeDriver ()); + + Toplevel top = new () + { + Height = 10, + Width = 10 + }; + + View otherView = new () + { + X = 0, Y = 0, + Height = 1, + Width = 1, + CanFocus = true, + }; + + view.Visible = false; + view.AutoSize = false; + view.X = Pos.Right (otherView); + view.Y = 0; + view.Width = 10; + view.Height = 1; + + var nEnter = 0; + var nLeave = 0; + + view.Enter += (s, e) => nEnter++; + view.Leave += (s, e) => nLeave++; + + top.Add (view, otherView); + Application.Begin (top); + + // Start with the focus on our test view + view.SetFocus (); + + Assert.Equal (0, nEnter); + Assert.Equal (0, nLeave); + + // Use keyboard to navigate to next view (otherView). + if (view is TextView) + { + top.NewKeyDownEvent (Key.Tab.WithCtrl); + } + else if (view is DatePicker) + { + for (var i = 0; i < 4; i++) + { + top.NewKeyDownEvent (Key.Tab.WithCtrl); + } + } + else + { + top.NewKeyDownEvent (Key.Tab); + } + + Assert.Equal (0, nEnter); + Assert.Equal (0, nLeave); + + top.NewKeyDownEvent (Key.Tab); + + Assert.Equal (0, nEnter); + Assert.Equal (0, nLeave); + + top.Dispose (); + Application.Shutdown (); + } + + [Theory] + [MemberData (nameof (AllViews))] + public void AllViews_OnMouseEvent_Enabled_False_Does_Not_Set_Handled (View view, string viewName) + { + if (view == null) + { + output.WriteLine ($"Ignoring {viewName} - It's a Generic"); + return; + } + + view.Enabled = false; + var me = new MouseEvent (); + view.OnMouseEvent (me); + Assert.False (me.Handled); + view.Dispose (); + } + + [Theory] + [MemberData (nameof (AllViews))] + public void AllViews_OnMouseClick_Enabled_False_Does_Not_Set_Handled (View view, string viewName) + { + if (view == null) + { + output.WriteLine ($"Ignoring {viewName} - It's a Generic"); + return; + } + + view.Enabled = false; + var me = new MouseEvent () + { + Flags = MouseFlags.Button1Clicked + }; + view.OnMouseEvent (me); + Assert.False (me.Handled); + view.Dispose (); + } } diff --git a/UnitTests/Views/AllViewsTests.cs b/UnitTests/Views/AllViewsTests.cs index 676198e844..a96ab7e26a 100644 --- a/UnitTests/Views/AllViewsTests.cs +++ b/UnitTests/Views/AllViewsTests.cs @@ -58,14 +58,14 @@ public void AllViews_Center_Properly (View view, string viewName) [Fact] public void AllViews_Enter_Leave_Events () { - foreach (Type type in GetAllViewClasses ()) + foreach (Type type in TestHelpers.GetAllViewClasses ()) { output.WriteLine ($"Testing {type.Name}"); Application.Init (new FakeDriver ()); Toplevel top = new (); - View vType = CreateViewFromType (type, type.GetConstructor (Array.Empty ())); + View vType = TestHelpers.CreateViewFromType (type, type.GetConstructor (Array.Empty ())); if (vType == null) { @@ -139,12 +139,13 @@ public void AllViews_Enter_Leave_Events () } } + [Fact] public void AllViews_Tests_All_Constructors () { Application.Init (new FakeDriver ()); - foreach (Type type in GetAllViewClasses ()) + foreach (Type type in TestHelpers.GetAllViewClasses ()) { Assert.True (Test_All_Constructors_Of_Type (type)); } @@ -152,18 +153,6 @@ public void AllViews_Tests_All_Constructors () Application.Shutdown (); } - public static List GetAllViewClasses () - { - return typeof (View).Assembly.GetTypes () - .Where ( - myType => myType.IsClass - && !myType.IsAbstract - && myType.IsPublic - && myType.IsSubclassOf (typeof (View)) - ) - .ToList (); - } - //[Fact] //public void AllViews_HotKey_Works () //{ @@ -180,7 +169,7 @@ public bool Test_All_Constructors_Of_Type (Type type) { foreach (ConstructorInfo ctor in type.GetConstructors ()) { - View view = CreateViewFromType (type, ctor); + View view = TestHelpers.CreateViewFromType (type, ctor); if (view != null) { @@ -243,73 +232,4 @@ private static void AddArguments (Type paramType, List pTypes) pTypes.Add (null); } } - - private static View CreateViewFromType (Type type, ConstructorInfo ctor) - { - View viewType = null; - - if (type.IsGenericType && type.IsTypeDefinition) - { - List gTypes = new (); - - foreach (Type args in type.GetGenericArguments ()) - { - gTypes.Add (typeof (object)); - } - - type = type.MakeGenericType (gTypes.ToArray ()); - - Assert.IsType (type, (View)Activator.CreateInstance (type)); - } - else - { - ParameterInfo [] paramsInfo = ctor.GetParameters (); - Type paramType; - List pTypes = new (); - - if (type.IsGenericType) - { - foreach (Type args in type.GetGenericArguments ()) - { - paramType = args.GetType (); - - if (args.Name == "T") - { - pTypes.Add (typeof (object)); - } - else - { - AddArguments (paramType, pTypes); - } - } - } - - foreach (ParameterInfo p in paramsInfo) - { - paramType = p.ParameterType; - - if (p.HasDefaultValue) - { - pTypes.Add (p.DefaultValue); - } - else - { - AddArguments (paramType, pTypes); - } - } - - if (type.IsGenericType && !type.IsTypeDefinition) - { - viewType = (View)Activator.CreateInstance (type); - Assert.IsType (type, viewType); - } - else - { - viewType = (View)ctor.Invoke (pTypes.ToArray ()); - Assert.IsType (type, viewType); - } - } - - return viewType; - } } diff --git a/UnitTests/Views/ButtonTests.cs b/UnitTests/Views/ButtonTests.cs index d64214832b..d775568acf 100644 --- a/UnitTests/Views/ButtonTests.cs +++ b/UnitTests/Views/ButtonTests.cs @@ -3,11 +3,8 @@ namespace Terminal.Gui.ViewsTests; -public class ButtonTests +public class ButtonTests (ITestOutputHelper output) { - private readonly ITestOutputHelper _output; - public ButtonTests (ITestOutputHelper output) { _output = output; } - // Test that Title and Text are the same [Fact] public void Text_Mirrors_Title () @@ -15,10 +12,11 @@ public void Text_Mirrors_Title () var view = new Button (); view.Title = "Hello"; Assert.Equal ("Hello", view.Title); - Assert.Equal ($"Hello", view.TitleTextFormatter.Text); + Assert.Equal ("Hello", view.TitleTextFormatter.Text); Assert.Equal ("Hello", view.Text); Assert.Equal ($"{CM.Glyphs.LeftBracket} Hello {CM.Glyphs.RightBracket}", view.TextFormatter.Text); + view.Dispose (); } [Fact] @@ -30,7 +28,8 @@ public void Title_Mirrors_Text () Assert.Equal ($"{CM.Glyphs.LeftBracket} Hello {CM.Glyphs.RightBracket}", view.TextFormatter.Text); Assert.Equal ("Hello", view.Title); - Assert.Equal ($"Hello", view.TitleTextFormatter.Text); + Assert.Equal ("Hello", view.TitleTextFormatter.Text); + view.Dispose (); } // BUGBUG: This test is NOT a unit test and needs to be broken apart into @@ -105,7 +104,7 @@ public void AutoSize_False_With_Fixed_Width () tab.Add (ckbMatchWholeWord); var tabView = new TabView { Width = Dim.Fill (), Height = Dim.Fill () }; - tabView.AddTab (new Tab { DisplayText = "Find", View = tab }, true); + tabView.AddTab (new() { DisplayText = "Find", View = tab }, true); var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; @@ -119,11 +118,11 @@ public void AutoSize_False_With_Fixed_Width () Application.Begin (top); ((FakeDriver)Application.Driver).SetBufferSize (54, 11); - Assert.Equal (new Rectangle (0, 0, 54, 11), win.Frame); - Assert.Equal (new Rectangle (0, 0, 52, 9), tabView.Frame); - Assert.Equal (new Rectangle (0, 0, 50, 7), tab.Frame); - Assert.Equal (new Rectangle (0, 1, 8, 1), view.Frame); - Assert.Equal (new Rectangle (9, 1, 20, 1), txtToFind.Frame); + Assert.Equal (new (0, 0, 54, 11), win.Frame); + Assert.Equal (new (0, 0, 52, 9), tabView.Frame); + Assert.Equal (new (0, 0, 50, 7), tab.Frame); + Assert.Equal (new (0, 1, 8, 1), view.Frame); + Assert.Equal (new (9, 1, 20, 1), txtToFind.Frame); Assert.Equal (0, txtToFind.ScrollOffset); Assert.Equal (16, txtToFind.CursorPosition); @@ -131,19 +130,12 @@ public void AutoSize_False_With_Fixed_Width () Assert.Equal (new (30, 1, 20, 1), btnFindNext.Frame); Assert.Equal (new (30, 2, 20, 1), btnFindPrevious.Frame); Assert.Equal (new (30, 4, 20, 1), btnCancel.Frame); -// Assert.Equal (new (0, 3, 12, 1), ckbMatchCase.Frame); -// Assert.Equal (new (0, 4, 18, 1), ckbMatchWholeWord.Frame); + + // Assert.Equal (new (0, 3, 12, 1), ckbMatchCase.Frame); + // Assert.Equal (new (0, 4, 18, 1), ckbMatchWholeWord.Frame); var btn1 = - $"{ - CM.Glyphs.LeftBracket - }{ - CM.Glyphs.LeftDefaultIndicator - } Find Next { - CM.Glyphs.RightDefaultIndicator - }{ - CM.Glyphs.RightBracket - }"; + $"{CM.Glyphs.LeftBracket}{CM.Glyphs.LeftDefaultIndicator} Find Next {CM.Glyphs.RightDefaultIndicator}{CM.Glyphs.RightBracket}"; var btn2 = $"{CM.Glyphs.LeftBracket} Find Previous {CM.Glyphs.RightBracket}"; var btn3 = $"{CM.Glyphs.LeftBracket} Cancel {CM.Glyphs.RightBracket}"; @@ -153,25 +145,16 @@ public void AutoSize_False_With_Fixed_Width () ││Find│ │ ││ ╰─────────────────────────────────────────────╮│ ││ ││ -││ Find: Testing buttons. { - btn1 -} ││ -││ { - btn2 -} ││ -││{ - CM.Glyphs.Checked -} Match case ││ -││{ - CM.Glyphs.UnChecked -} Match whole word { - btn3 -} ││ +││ Find: Testing buttons. {btn1} ││ +││ {btn2} ││ +││{CM.Glyphs.Checked} Match case ││ +││{CM.Glyphs.UnChecked} Match whole word {btn3} ││ │└──────────────────────────────────────────────────┘│ └────────────────────────────────────────────────────┘ "; - TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); + TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + view.Dispose (); } [Fact] @@ -197,14 +180,12 @@ public void AutoSize_Stays_True_AnchorEnd () var expected = @$" ┌────────────────────────────┐ │ │ -│ { - btnTxt -}│ +│ {btnTxt}│ │ │ └────────────────────────────┘ "; - TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); + TestHelpers.AssertDriverContentsWithFrameAre (expected, output); Assert.True (btn.AutoSize); btn.Text = "Say Hello 你 changed"; @@ -215,14 +196,13 @@ public void AutoSize_Stays_True_AnchorEnd () expected = @$" ┌────────────────────────────┐ │ │ -│ { - btnTxt -}│ +│ {btnTxt}│ │ │ └────────────────────────────┘ "; - TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); + TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + top.Dispose (); } [Fact] @@ -244,16 +224,12 @@ public void AutoSize_Stays_True_Center () var expected = @$" ┌────────────────────────────┐ │ │ -│ { - CM.Glyphs.LeftBracket -} Say Hello 你 { - CM.Glyphs.RightBracket -} │ +│ {CM.Glyphs.LeftBracket} Say Hello 你 {CM.Glyphs.RightBracket} │ │ │ └────────────────────────────┘ "; - TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); + TestHelpers.AssertDriverContentsWithFrameAre (expected, output); Assert.True (btn.AutoSize); btn.Text = "Say Hello 你 changed"; @@ -263,16 +239,13 @@ public void AutoSize_Stays_True_Center () expected = @$" ┌────────────────────────────┐ │ │ -│ { - CM.Glyphs.LeftBracket -} Say Hello 你 changed { - CM.Glyphs.RightBracket -} │ +│ {CM.Glyphs.LeftBracket} Say Hello 你 changed {CM.Glyphs.RightBracket} │ │ │ └────────────────────────────┘ "; - TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); + TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + top.Dispose (); } [Fact] @@ -284,7 +257,7 @@ public void AutoSize_Stays_True_With_EmptyText () var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (btn); var top = new Toplevel (); - top.Add (win); + top.Add (win); Assert.True (btn.AutoSize); @@ -298,16 +271,13 @@ public void AutoSize_Stays_True_With_EmptyText () var expected = @$" ┌────────────────────────────┐ │ │ -│ { - CM.Glyphs.LeftBracket -} Say Hello 你 { - CM.Glyphs.RightBracket -} │ +│ {CM.Glyphs.LeftBracket} Say Hello 你 {CM.Glyphs.RightBracket} │ │ │ └────────────────────────────┘ "; - TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); + TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + top.Dispose (); } [Fact] @@ -347,22 +317,11 @@ public void Button_AutoSize_False_With_Fixed_Width () TestHelpers.AssertDriverContentsWithFrameAre ( @$" - { - CM.Glyphs.LeftBracket - } { - btn1.Text - } { - CM.Glyphs.RightBracket - } - { - CM.Glyphs.LeftBracket - } { - btn2.Text - } { - CM.Glyphs.RightBracket - }", - _output + {CM.Glyphs.LeftBracket} {btn1.Text} {CM.Glyphs.RightBracket} + {CM.Glyphs.LeftBracket} {btn2.Text} {CM.Glyphs.RightBracket}", + output ); + top.Dispose (); } [Fact] @@ -394,10 +353,10 @@ public void Button_HotKeyChanged_EventFires () Assert.Same (btn, sender); Assert.Equal (KeyCode.Y, args.OldKey); Assert.Equal (KeyCode.R, args.NewKey); + btn.Dispose (); } [Fact] - [AutoInitShutdown] public void Button_HotKeyChanged_EventFires_WithNone () { var btn = new Button (); @@ -415,6 +374,7 @@ public void Button_HotKeyChanged_EventFires_WithNone () Assert.Same (btn, sender); Assert.Equal (KeyCode.Null, args.OldKey); Assert.Equal (KeyCode.R, args.NewKey); + btn.Dispose (); } [Fact] @@ -431,15 +391,15 @@ public void Constructors_Defaults () Assert.Equal (TextAlignment.Centered, btn.TextAlignment); Assert.Equal ('_', btn.HotKeySpecifier.Value); Assert.True (btn.CanFocus); - Assert.Equal (new Rectangle (0, 0, 4, 1), btn.Bounds); - Assert.Equal (new Rectangle (0, 0, 4, 1), btn.Frame); + Assert.Equal (new (0, 0, 4, 1), btn.Bounds); + Assert.Equal (new (0, 0, 4, 1), btn.Frame); Assert.Equal ($"{CM.Glyphs.LeftBracket} {CM.Glyphs.RightBracket}", btn.TextFormatter.Text); Assert.False (btn.IsDefault); Assert.Equal (TextAlignment.Centered, btn.TextAlignment); Assert.Equal ('_', btn.HotKeySpecifier.Value); Assert.True (btn.CanFocus); - Assert.Equal (new Rectangle (0, 0, 4, 1), btn.Bounds); - Assert.Equal (new Rectangle (0, 0, 4, 1), btn.Frame); + Assert.Equal (new (0, 0, 4, 1), btn.Bounds); + Assert.Equal (new (0, 0, 4, 1), btn.Frame); Assert.Equal (string.Empty, btn.Title); Assert.Equal (KeyCode.Null, btn.HotKey); @@ -447,15 +407,12 @@ public void Constructors_Defaults () btn.Draw (); var expected = @$" -{ - CM.Glyphs.LeftBracket -} { - CM.Glyphs.RightBracket -} +{CM.Glyphs.LeftBracket} {CM.Glyphs.RightBracket} "; - TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); + TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + btn.Dispose (); - btn = new Button { Text = "_Test", IsDefault = true }; + btn = new() { Text = "_Test", IsDefault = true }; btn.BeginInit (); btn.EndInit (); Assert.Equal ('_', btn.HotKeySpecifier.Value); @@ -463,40 +420,26 @@ public void Constructors_Defaults () Assert.Equal ("_Test", btn.Text); Assert.Equal ( - $"{ - CM.Glyphs.LeftBracket - }{ - CM.Glyphs.LeftDefaultIndicator - } Test { - CM.Glyphs.RightDefaultIndicator - }{ - CM.Glyphs.RightBracket - }", + $"{CM.Glyphs.LeftBracket}{CM.Glyphs.LeftDefaultIndicator} Test {CM.Glyphs.RightDefaultIndicator}{CM.Glyphs.RightBracket}", btn.TextFormatter.Format () ); Assert.True (btn.IsDefault); Assert.Equal (TextAlignment.Centered, btn.TextAlignment); Assert.True (btn.CanFocus); - Assert.Equal (new Rectangle (0, 0, 10, 1), btn.Bounds); - Assert.Equal (new Rectangle (0, 0, 10, 1), btn.Frame); + Assert.Equal (new (0, 0, 10, 1), btn.Bounds); + Assert.Equal (new (0, 0, 10, 1), btn.Frame); Assert.Equal (KeyCode.T, btn.HotKey); - btn = new Button { X = 1, Y = 2, Text = "_abc", IsDefault = true }; + btn.Dispose (); + + btn = new() { X = 1, Y = 2, Text = "_abc", IsDefault = true }; btn.BeginInit (); btn.EndInit (); Assert.Equal ("_abc", btn.Text); Assert.Equal (Key.A, btn.HotKey); Assert.Equal ( - $"{ - CM.Glyphs.LeftBracket - }{ - CM.Glyphs.LeftDefaultIndicator - } abc { - CM.Glyphs.RightDefaultIndicator - }{ - CM.Glyphs.RightBracket - }", + $"{CM.Glyphs.LeftBracket}{CM.Glyphs.LeftDefaultIndicator} abc {CM.Glyphs.RightDefaultIndicator}{CM.Glyphs.RightBracket}", btn.TextFormatter.Format () ); Assert.True (btn.IsDefault); @@ -508,20 +451,13 @@ public void Constructors_Defaults () btn.Draw (); expected = @$" - { - CM.Glyphs.LeftBracket - }{ - CM.Glyphs.LeftDefaultIndicator - } abc { - CM.Glyphs.RightDefaultIndicator - }{ - CM.Glyphs.RightBracket - } + {CM.Glyphs.LeftBracket}{CM.Glyphs.LeftDefaultIndicator} abc {CM.Glyphs.RightDefaultIndicator}{CM.Glyphs.RightBracket} "; - TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); + TestHelpers.AssertDriverContentsWithFrameAre (expected, output); - Assert.Equal (new Rectangle (0, 0, 9, 1), btn.Bounds); - Assert.Equal (new Rectangle (1, 2, 9, 1), btn.Frame); + Assert.Equal (new (0, 0, 9, 1), btn.Bounds); + Assert.Equal (new (1, 2, 9, 1), btn.Frame); + btn.Dispose (); } [Fact] @@ -547,6 +483,7 @@ public void HotKeyChange_Works () btn.HotKey = KeyCode.E; Assert.True (btn.NewKeyDownEvent (Key.E.WithAlt)); Assert.True (clicked); + top.Dispose (); } /// @@ -571,7 +508,7 @@ public void KeyBindingExample () Application.Begin (top); // default keybinding is Space which results in keypress - Application.OnKeyDown (new Key ((KeyCode)' ')); + Application.OnKeyDown (new ((KeyCode)' ')); Assert.Equal (1, pressed); // remove the default keybinding (Space) @@ -579,7 +516,7 @@ public void KeyBindingExample () btn.KeyBindings.Clear (Command.Accept); // After clearing the default keystroke the Space button no longer does anything for the Button - Application.OnKeyDown (new Key ((KeyCode)' ')); + Application.OnKeyDown (new ((KeyCode)' ')); Assert.Equal (1, pressed); // Set a new binding of b for the click (Accept) event @@ -601,6 +538,7 @@ public void KeyBindingExample () // now pressing Shift-Alt-B should NOT call the button click event Application.OnKeyDown (Key.B.WithAlt.WithShift); Assert.Equal (2, pressed); + top.Dispose (); } [Fact] @@ -659,7 +597,7 @@ public void KeyBindings_Command () Assert.True (clicked); clicked = false; - Assert.True (btn.NewKeyDownEvent (new Key ((KeyCode)'T'))); + Assert.True (btn.NewKeyDownEvent (new ((KeyCode)'T'))); Assert.True (clicked); clicked = false; @@ -668,6 +606,8 @@ public void KeyBindings_Command () Assert.True (btn.NewKeyDownEvent (btn.HotKey)); Assert.True (clicked); clicked = false; + + top.Dispose (); } [Fact] @@ -680,8 +620,10 @@ public void HotKey_Command_Accepts () button.InvokeCommand (Command.HotKey); Assert.True (accepted); + button.Dispose (); return; + void ButtonOnAccept (object sender, CancelEventArgs e) { accepted = true; } } @@ -693,17 +635,21 @@ public void Accept_Cancel_Event_OnAccept_Returns_True () button.Accept += ButtonAccept; - var ret = button.InvokeCommand (Command.Accept); + bool? ret = button.InvokeCommand (Command.Accept); Assert.True (ret); Assert.True (acceptInvoked); + button.Dispose (); + return; + void ButtonAccept (object sender, CancelEventArgs e) { acceptInvoked = true; e.Cancel = true; } } + [Fact] public void Setting_Empty_Text_Sets_HoKey_To_KeyNull () { @@ -726,6 +672,7 @@ public void Setting_Empty_Text_Sets_HoKey_To_KeyNull () btn.Text = "Te_st"; Assert.Equal ("Te_st", btn.Text); Assert.Equal (KeyCode.S, btn.HotKey); + super.Dispose (); } [Fact] @@ -740,6 +687,7 @@ public void TestAssignTextToButton () // with cast Assert.Equal ("heyb", ((Button)b).Text); + b.Dispose (); } [Fact] @@ -760,21 +708,20 @@ public void Update_Only_On_Or_After_Initialize () Assert.True (btn.IsInitialized); Assert.Equal ("Say Hello 你", btn.Text); Assert.Equal ($"{CM.Glyphs.LeftBracket} {btn.Text} {CM.Glyphs.RightBracket}", btn.TextFormatter.Text); - Assert.Equal (new Rectangle (0, 0, 16, 1), btn.Bounds); + Assert.Equal (new (0, 0, 16, 1), btn.Bounds); var btnTxt = $"{CM.Glyphs.LeftBracket} {btn.Text} {CM.Glyphs.RightBracket}"; var expected = @$" ┌────────────────────────────┐ │ │ -│ { - btnTxt -} │ +│ {btnTxt} │ │ │ └────────────────────────────┘ "; - Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); - Assert.Equal (new Rectangle (0, 0, 30, 5), pos); + Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new (0, 0, 30, 5), pos); + top.Dispose (); } [Fact] @@ -795,20 +742,19 @@ public void Update_Parameterless_Only_On_Or_After_Initialize () Assert.True (btn.IsInitialized); Assert.Equal ("Say Hello 你", btn.Text); Assert.Equal ($"{CM.Glyphs.LeftBracket} {btn.Text} {CM.Glyphs.RightBracket}", btn.TextFormatter.Text); - Assert.Equal (new Rectangle (0, 0, 16, 1), btn.Bounds); + Assert.Equal (new (0, 0, 16, 1), btn.Bounds); var btnTxt = $"{CM.Glyphs.LeftBracket} {btn.Text} {CM.Glyphs.RightBracket}"; var expected = @$" ┌────────────────────────────┐ │ │ -│ { - btnTxt -} │ +│ {btnTxt} │ │ │ └────────────────────────────┘ "; - Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, _output); - Assert.Equal (new Rectangle (0, 0, 30, 5), pos); + Rectangle pos = TestHelpers.AssertDriverContentsWithFrameAre (expected, output); + Assert.Equal (new (0, 0, 30, 5), pos); + top.Dispose (); } } From 1cca002393da3b3fbb87c6b53f6dfb051c61f755 Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 2 Apr 2024 08:45:28 -0600 Subject: [PATCH 08/32] Got new button fn working on WindowsDriver; Now debugging netdriver and curses --- Terminal.Gui/Application.cs | 24 ++++---- .../CursesDriver/CursesDriver.cs | 6 ++ Terminal.Gui/ConsoleDrivers/NetDriver.cs | 4 +- Terminal.Gui/ConsoleDrivers/WindowsDriver.cs | 29 +++++++-- Terminal.Gui/Views/Button.cs | 60 +++++++++++-------- UICatalog/Scenarios/Buttons.cs | 15 ++++- 6 files changed, 90 insertions(+), 48 deletions(-) diff --git a/Terminal.Gui/Application.cs b/Terminal.Gui/Application.cs index 660104f334..d5bac89d99 100644 --- a/Terminal.Gui/Application.cs +++ b/Terminal.Gui/Application.cs @@ -1456,15 +1456,6 @@ internal static void OnMouseEvent (MouseEventEventArgs a) // TODO: In PR #3273, FindDeepestView will return adornments. Update logic below to fix adornment mouse handling var view = View.FindDeepestView (Current, a.MouseEvent.X, a.MouseEvent.Y); - if (view is { WantContinuousButtonPressed: true }) - { - WantContinuousButtonPressedView = view; - } - else - { - WantContinuousButtonPressedView = null; - } - if (view is { }) { a.MouseEvent.View = view; @@ -1494,10 +1485,7 @@ internal static void OnMouseEvent (MouseEventEventArgs a) if (MouseGrabView.Bounds.Contains (viewRelativeMouseEvent.X, viewRelativeMouseEvent.Y) is false) { - // The mouse has moved outside the bounds of the view that - // grabbed the mouse, so we tell the view that last got - // OnMouseEnter the mouse is leaving - // BUGBUG: That sentence makes no sense. Either I'm missing something or this logic is flawed. + // The mouse has moved outside the bounds of the view that grabbed the mouse _mouseEnteredView?.OnMouseLeave (a.MouseEvent); } @@ -1508,6 +1496,16 @@ internal static void OnMouseEvent (MouseEventEventArgs a) } } + if (view is { WantContinuousButtonPressed: true }) + { + WantContinuousButtonPressedView = view; + } + else + { + WantContinuousButtonPressedView = null; + } + + if (view is not Adornment) { if ((view is null || view == OverlappedTop) diff --git a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs index 7dcdd78a53..08457cc836 100644 --- a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs @@ -2,6 +2,7 @@ // Driver.cs: Curses-based Driver // +using System.Diagnostics; using System.Runtime.InteropServices; using Terminal.Gui.ConsoleDrivers; using Unix.Terminal; @@ -798,6 +799,9 @@ bool IsButtonClickedOrDoubleClicked (MouseFlags flag) || flag.HasFlag (MouseFlags.Button4DoubleClicked); } + Debug.WriteLine ($"CursesDriver: ({pos.X},{pos.Y}) - {mouseFlag}"); + + if ((WasButtonReleased (mouseFlag) && IsButtonNotPressed (_lastMouseFlags)) || (IsButtonClickedOrDoubleClicked (mouseFlag) && _lastMouseFlags == 0)) { return; @@ -806,6 +810,8 @@ bool IsButtonClickedOrDoubleClicked (MouseFlags flag) _lastMouseFlags = mouseFlag; var me = new MouseEvent { Flags = mouseFlag, X = pos.X, Y = pos.Y }; + Debug.WriteLine ($"CursesDriver: ({me.X},{me.Y}) - {me.Flags}"); + OnMouseEvent (new MouseEventEventArgs (me)); } diff --git a/Terminal.Gui/ConsoleDrivers/NetDriver.cs b/Terminal.Gui/ConsoleDrivers/NetDriver.cs index 19e3667b65..cb22d288c4 100644 --- a/Terminal.Gui/ConsoleDrivers/NetDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/NetDriver.cs @@ -1137,7 +1137,7 @@ private void ProcessInput (InputResult inputEvent) break; case EventType.Mouse: MouseEvent me = ToDriverMouse (inputEvent.MouseEvent); - //Debug.WriteLine ($"NetDriver: ({me.X},{me.Y}) - {me.Flags}"); + Debug.WriteLine ($"NetDriver: ({me.X},{me.Y}) - {me.Flags}"); OnMouseEvent (new MouseEventEventArgs (me)); break; @@ -1379,7 +1379,7 @@ public void StopReportingMouseMoves () private MouseEvent ToDriverMouse (NetEvents.MouseEvent me) { - // System.Diagnostics.Debug.WriteLine ($"X: {me.Position.X}; Y: {me.Position.Y}; ButtonState: {me.ButtonState}"); + //System.Diagnostics.Debug.WriteLine ($"X: {me.Position.X}; Y: {me.Position.Y}; ButtonState: {me.ButtonState}"); MouseFlags mouseFlag = 0; diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index 60989c5861..24adb1ca3f 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -1695,7 +1695,13 @@ private MouseFlags ProcessButtonClick (WindowsConsole.MouseEventRecord mouseEven private async Task ProcessButtonDoubleClickedAsync () { - await Task.Delay (300); + // Only delay if there's not a view wanting continuous button presses + if (Application.WantContinuousButtonPressedView is null) + { + // QUESTION: Why 300ms? + await Task.Delay (300); + } + _isButtonDoubleClicked = false; _isOneFingerDoubleClicked = false; @@ -1704,10 +1710,16 @@ private async Task ProcessButtonDoubleClickedAsync () private async Task ProcessContinuousButtonPressedAsync (MouseFlags mouseFlag) { + // When a user presses-and-holds, start generating pressed events every `startDelay` + // After `iterationsUntilFast` iterations, speed them up to `fastDelay` ms + const int startDelay = 500; + const int iterationsUntilFast = 4; + const int fastDelay = 50; + + int iterations = 0; + int delay = startDelay; while (_isButtonPressed) { - await Task.Delay (100); - var me = new MouseEvent { X = _pointMove.X, @@ -1715,13 +1727,18 @@ private async Task ProcessContinuousButtonPressedAsync (MouseFlags mouseFlag) Flags = mouseFlag }; - View view = Application.WantContinuousButtonPressedView; - - if (view is null) + if (Application.WantContinuousButtonPressedView is null) { break; } + if (iterations++ >= iterationsUntilFast) + { + delay = fastDelay; + } + await Task.Delay (delay); + + //Debug.WriteLine($"ProcessContinuousButtonPressedAsync: {view}"); if (_isButtonPressed && (mouseFlag & MouseFlags.ReportMousePosition) == 0) { Application.Invoke (() => OnMouseEvent (new MouseEventEventArgs (me))); diff --git a/Terminal.Gui/Views/Button.cs b/Terminal.Gui/Views/Button.cs index 5ceef8b9c5..7cd32f1a03 100644 --- a/Terminal.Gui/Views/Button.cs +++ b/Terminal.Gui/Views/Button.cs @@ -67,52 +67,62 @@ public Button () private void Button_MouseEvent (object sender, MouseEventEventArgs e) { - if (e.MouseEvent.Flags.HasFlag(MouseFlags.Button1Clicked)) + // Default behavior is to invoke Accept (via HotKey) on clicked. + if (!WantContinuousButtonPressed && + Application.MouseGrabView != this && + e.MouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked)) { - if (Application.MouseGrabView != this) - { - e.Handled = InvokeCommand (Command.HotKey) == true; - - return; - } + e.Handled = InvokeCommand (Command.HotKey) == true; + return; } - if (e.MouseEvent.Flags == MouseFlags.Button1Pressed) + if (e.MouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed)) { - if (Application.MouseGrabView == this) + // If WantContinuousButtonPressed is true, and this is not the first pressed event, + // invoke Accept (via HotKey) + if (WantContinuousButtonPressed && Application.MouseGrabView == this) { e.Handled = InvokeCommand (Command.HotKey) == true; return; } - SetFocus(); - Application.GrabMouse(this); + // The first time we get pressed event, grab the mouse and invert the colors + if (Application.MouseGrabView != this) + { + Application.GrabMouse (this); + _savedColorScheme = ColorScheme; + var cs = new ColorScheme (new Attribute (ColorScheme.Normal.Background, ColorScheme.Normal.Foreground)); + ColorScheme = cs; - _savedColorScheme = ColorScheme; - var cs = new ColorScheme (new Attribute (ColorScheme.Normal.Background, ColorScheme.Normal.Foreground)); - ColorScheme = cs; + // Set the focus, but don't invoke Accept + SetFocus (); + } } - if (e.MouseEvent.Flags.HasFlag(MouseFlags.Button1Released)) + if (e.MouseEvent.Flags.HasFlag (MouseFlags.Button1Released)) { - Application.UngrabMouse (); - - e.Handled = InvokeCommand (Command.HotKey) == true; - - if (_savedColorScheme is { }) + // When the mouse is released, if WantContinuousButtonPressed is set, invoke Accept one last time. + if (WantContinuousButtonPressed) { - ColorScheme = _savedColorScheme; + e.Handled = InvokeCommand (Command.HotKey) == true; } - _savedColorScheme = null; + if (Application.MouseGrabView == this) + { + Application.UngrabMouse (); + if (_savedColorScheme is { }) + { + ColorScheme = _savedColorScheme; + _savedColorScheme = null; + } + } } } /// - public override bool OnLeave (View view) + protected internal override bool OnMouseLeave (MouseEvent e) { - //Application.UngrabMouse(); - return base.OnLeave (view); + return base.OnMouseLeave (e); } private void Button_MouseClick (object sender, MouseEventEventArgs e) diff --git a/UICatalog/Scenarios/Buttons.cs b/UICatalog/Scenarios/Buttons.cs index e3c9b5ea25..8dd1553853 100644 --- a/UICatalog/Scenarios/Buttons.cs +++ b/UICatalog/Scenarios/Buttons.cs @@ -396,7 +396,7 @@ string MoveHotkey (string txt) { X = Pos.Right (label) + 1, Y = Pos.Top (label), - Title = $"Accept Count (press-and-hold): {acceptCount}", + Title = $"Accept Count: {acceptCount}", WantContinuousButtonPressed = true, }; repeatButton.Accept += (s, e) => @@ -404,7 +404,18 @@ string MoveHotkey (string txt) repeatButton.Title = $"Accept Count: {++acceptCount}"; }; - main.Add(label, repeatButton); + var enableCB = new CheckBox () + { + X = Pos.Right (repeatButton) + 1, + Y = Pos.Top (repeatButton), + Title = "Enabled", + Checked = true, + }; + enableCB.Toggled += (s, e) => + { + repeatButton.Enabled = !repeatButton.Enabled; + }; + main.Add(label, repeatButton, enableCB); main.Ready += (s, e) => radioGroup.Refresh (); Application.Run (main); From 06cc7d8f713e6e3ba383fc063c99608dfcc955f4 Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 2 Apr 2024 14:49:13 -0600 Subject: [PATCH 09/32] Moved view highlight on press code into View. Updated all Views that would benefit. Note this breaks Charmap because ScrollView blindly grabs mouse on Enter. This will be fixed in #3323. --- Terminal.Gui/ConsoleDrivers/WindowsDriver.cs | 2 + Terminal.Gui/View/ViewMouse.cs | 77 ++++++++++++-- Terminal.Gui/Views/Button.cs | 4 +- Terminal.Gui/Views/CheckBox.cs | 1 + Terminal.Gui/Views/ColorPicker.cs | 100 ++++++++++--------- Terminal.Gui/Views/DatePicker.cs | 16 ++- UICatalog/Scenarios/Buttons.cs | 22 +++- 7 files changed, 161 insertions(+), 61 deletions(-) diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index 24adb1ca3f..017a4be628 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -1911,6 +1911,8 @@ private MouseEvent ToDriverMouse (WindowsConsole.MouseEventRecord mouseEvent) { _point = null; } + _processButtonClick = true; + } else if (mouseEvent.EventFlags == WindowsConsole.EventFlags.MouseMoved && !_isOneFingerDoubleClicked diff --git a/Terminal.Gui/View/ViewMouse.cs b/Terminal.Gui/View/ViewMouse.cs index e78ede31ea..c8d07b99b9 100644 --- a/Terminal.Gui/View/ViewMouse.cs +++ b/Terminal.Gui/View/ViewMouse.cs @@ -2,6 +2,11 @@ public partial class View { + /// + /// Gets or sets whether the will invert the colors when the mouse button is pressed/released. + /// + public bool InvertColorsOnPress { get; set; } + /// Gets or sets a value indicating whether this want continuous button pressed event. public virtual bool WantContinuousButtonPressed { get; set; } @@ -91,6 +96,9 @@ protected internal virtual bool OnMouseLeave (MouseEvent mouseEvent) 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 . /// @@ -115,23 +123,76 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) var args = new MouseEventEventArgs (mouseEvent); - // Clicked support for all buttons and single and double click - if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked) + + // 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)) { - OnMouseClick (args); + return OnMouseClick (args); } - if (mouseEvent.Flags.HasFlag (MouseFlags.Button1DoubleClicked) - || mouseEvent.Flags.HasFlag (MouseFlags.Button2DoubleClicked) - || mouseEvent.Flags.HasFlag (MouseFlags.Button3DoubleClicked) - || mouseEvent.Flags.HasFlag (MouseFlags.Button4DoubleClicked)) + if (InvertColorsOnPress && mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed)) { - OnMouseClick (args); + // 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; + var cs = new ColorScheme (new Attribute (ColorScheme.Normal.Background, ColorScheme.Normal.Foreground)); + ColorScheme = cs; + + // Set the focus, but don't invoke Accept + SetFocus (); + } } + if (InvertColorsOnPress && 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 (_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); diff --git a/Terminal.Gui/Views/Button.cs b/Terminal.Gui/Views/Button.cs index 7cd32f1a03..c7c1096391 100644 --- a/Terminal.Gui/Views/Button.cs +++ b/Terminal.Gui/Views/Button.cs @@ -58,8 +58,8 @@ public Button () KeyBindings.Add (Key.Enter, Command.HotKey); TitleChanged += Button_TitleChanged; - MouseEvent += Button_MouseEvent; - //MouseClick += Button_MouseClick; + MouseClick += Button_MouseClick; + InvertColorsOnPress = true; } [CanBeNull] diff --git a/Terminal.Gui/Views/CheckBox.cs b/Terminal.Gui/Views/CheckBox.cs index fb8665b872..30979555e2 100644 --- a/Terminal.Gui/Views/CheckBox.cs +++ b/Terminal.Gui/Views/CheckBox.cs @@ -35,6 +35,7 @@ public CheckBox () TitleChanged += Checkbox_TitleChanged; + InvertColorsOnPress = true; MouseClick += CheckBox_MouseClick; } diff --git a/Terminal.Gui/Views/ColorPicker.cs b/Terminal.Gui/Views/ColorPicker.cs index e1f8179a51..36ff5b48ba 100644 --- a/Terminal.Gui/Views/ColorPicker.cs +++ b/Terminal.Gui/Views/ColorPicker.cs @@ -29,6 +29,49 @@ public class ColorPicker : View /// Initializes a new instance of . public ColorPicker () { SetInitialProperties (); } + private void SetInitialProperties () + { + InvertColorsOnPress = true; + + CanFocus = true; + AddCommands (); + AddKeyBindings (); + + LayoutStarted += (o, a) => + { + Thickness thickness = GetAdornmentsThickness (); + Width = _cols * BoxWidth + thickness.Vertical; + Height = _rows * BoxHeight + thickness.Horizontal; + }; +// MouseEvent += ColorPicker_MouseEvent; + MouseClick += ColorPicker_MouseClick; + } + + // TODO: Decouple Cursor from SelectedColor so that mouse press-and-hold can show the color under the cursor. + //private void ColorPicker_MouseEvent (object sender, MouseEventEventArgs me) + //{ + // if (me.MouseEvent.X > Bounds.Width || me.MouseEvent.Y > Bounds.Height) + // { + // me.Handled = true; + + // return; + // } + + // me.Handled = true; + + // return; + //} + + private void ColorPicker_MouseClick (object sender, MouseEventEventArgs me) + { + if (CanFocus) + { + Cursor = new Point (me.MouseEvent.X / _boxWidth, me.MouseEvent.Y / _boxHeight); + SetFocus (); + me.Handled = true; + } + } + /// Height of a color box public int BoxHeight { @@ -88,37 +131,6 @@ public ColorName SelectedColor /// Fired when a color is picked. public event EventHandler ColorChanged; - /// - protected internal override bool OnMouseEvent (MouseEvent me) - { - if (!me.Flags.HasFlag (MouseFlags.Button1Clicked) || !CanFocus) - { - return false; - } - - SetFocus (); - - if (me.X > Bounds.Width || me.Y > Bounds.Height) - { - return true; - } - - Cursor = new Point (me.X / _boxWidth, me.Y / _boxHeight); - - return true; - } - - /// Moves the selected item index to the next row. - /// - public virtual bool MoveDown () - { - if (Cursor.Y < _rows - 1) - { - SelectedColor += _cols; - } - - return true; - } /// Moves the selected item index to the previous column. /// @@ -156,6 +168,18 @@ public virtual bool MoveUp () return true; } + /// Moves the selected item index to the next row. + /// + public virtual bool MoveDown () + { + if (Cursor.Y < _rows - 1) + { + SelectedColor += _cols; + } + + return true; + } + /// public override void OnDrawContent (Rectangle contentArea) { @@ -265,18 +289,4 @@ private void DrawFocusRect (Rectangle rect) AddRune (p.Key.X, p.Key.Y, p.Value); } } - - private void SetInitialProperties () - { - CanFocus = true; - AddCommands (); - AddKeyBindings (); - - LayoutStarted += (o, a) => - { - Thickness thickness = GetAdornmentsThickness (); - Width = _cols * BoxWidth + thickness.Vertical; - Height = _rows * BoxHeight + thickness.Horizontal; - }; - } } diff --git a/Terminal.Gui/Views/DatePicker.cs b/Terminal.Gui/Views/DatePicker.cs index 833537fbfe..1b4c4c8412 100644 --- a/Terminal.Gui/Views/DatePicker.cs +++ b/Terminal.Gui/Views/DatePicker.cs @@ -215,11 +215,14 @@ private void SetInitialProperties (DateTime date) _previousMonthButton = new Button { AutoSize = false, - X = Pos.Center () - 4, + X = Pos.Center () - 2, Y = Pos.Bottom (_calendar) - 1, Height = 1, - Width = CalculateCalendarWidth () / 2, - Text = GetBackButtonText () + Width = 2, + Text = GetBackButtonText (), + WantContinuousButtonPressed = true, + NoPadding = true, + NoDecorations = true }; _previousMonthButton.Accept += (sender, e) => @@ -235,8 +238,11 @@ private void SetInitialProperties (DateTime date) X = Pos.Right (_previousMonthButton) + 2, Y = Pos.Bottom (_calendar) - 1, Height = 1, - Width = CalculateCalendarWidth () / 2, - Text = GetBackButtonText () + Width = 2, + Text = GetForwardButtonText(), + WantContinuousButtonPressed = true, + NoPadding = true, + NoDecorations = true }; _nextMonthButton.Accept += (sender, e) => diff --git a/UICatalog/Scenarios/Buttons.cs b/UICatalog/Scenarios/Buttons.cs index 8dd1553853..36f567e5da 100644 --- a/UICatalog/Scenarios/Buttons.cs +++ b/UICatalog/Scenarios/Buttons.cs @@ -389,7 +389,27 @@ string MoveHotkey (string txt) { X = 0, Y = Pos.Bottom (label) + 1, - Title = "_Repeat (CanFocus; press-and-hold):", + Title = "_No Repeat:", + }; + int noRepeatAcceptCount = 0; + var noRepeatButton = new Button () + { + X = Pos.Right (label) + 1, + Y = Pos.Top (label), + Title = $"Accept Count: {noRepeatAcceptCount}", + WantContinuousButtonPressed = false, + }; + noRepeatButton.Accept += (s, e) => + { + noRepeatButton.Title = $"Accept Count: {++noRepeatAcceptCount}"; + }; + main.Add(label, noRepeatButton); + + label = new Label () + { + X = 0, + Y = Pos.Bottom (label) + 1, + Title = "_Repeat (press-and-hold):", }; int acceptCount = 0; var repeatButton = new Button () From d9d5f860c37eb332251065121c15ac270b3eacaf Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 2 Apr 2024 14:56:11 -0600 Subject: [PATCH 10/32] Made RadioGroup utilize InvertColorsOnPress. Works, but not optimally. The entire view invert. What would be really nice is if just the radio item under the mouse inverted. We can fix this later. --- Terminal.Gui/Views/RadioGroup.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Terminal.Gui/Views/RadioGroup.cs b/Terminal.Gui/Views/RadioGroup.cs index 82de31e386..3b42c28bf7 100644 --- a/Terminal.Gui/Views/RadioGroup.cs +++ b/Terminal.Gui/Views/RadioGroup.cs @@ -76,6 +76,8 @@ public RadioGroup () KeyBindings.Add (Key.Space, Command.Accept); LayoutStarted += RadioGroup_LayoutStarted; + + InvertColorsOnPress = true; } /// @@ -163,6 +165,7 @@ public int SelectedItem /// protected internal override bool OnMouseEvent (MouseEvent me) { + base.OnMouseEvent (me); if (!me.Flags.HasFlag (MouseFlags.Button1Clicked)) { return false; From dc7b504890fdb57fdcd61b1c4035daaeb13aa947 Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 2 Apr 2024 15:37:00 -0600 Subject: [PATCH 11/32] RadioButton now works --- Terminal.Gui/Views/RadioGroup.cs | 74 ++++++++++++++------------------ 1 file changed, 33 insertions(+), 41 deletions(-) diff --git a/Terminal.Gui/Views/RadioGroup.cs b/Terminal.Gui/Views/RadioGroup.cs index 3b42c28bf7..7a16265538 100644 --- a/Terminal.Gui/Views/RadioGroup.cs +++ b/Terminal.Gui/Views/RadioGroup.cs @@ -78,6 +78,39 @@ public RadioGroup () LayoutStarted += RadioGroup_LayoutStarted; InvertColorsOnPress = true; + + MouseClick += RadioGroup_MouseClick; + } + + // TODO: Fix InvertColorsOnPress - only highlight the selected item + + private void RadioGroup_MouseClick (object sender, MouseEventEventArgs e) + { + SetFocus (); + + int boundsX = e.MouseEvent.X; + int boundsY = e.MouseEvent.Y; + + int pos = _orientation == Orientation.Horizontal ? boundsX : boundsY; + + int rCount = _orientation == Orientation.Horizontal + ? _horizontal.Last ().pos + _horizontal.Last ().length + : _radioLabels.Count; + + if (pos < rCount) + { + int c = _orientation == Orientation.Horizontal + ? _horizontal.FindIndex (x => x.pos <= boundsX && x.pos + x.length - 2 >= boundsX) + : boundsY; + + if (c > -1) + { + _cursor = SelectedItem = c; + SetNeedsDisplay (); + } + } + + e.Handled = true; } /// @@ -162,47 +195,6 @@ public int SelectedItem } } - /// - protected internal override bool OnMouseEvent (MouseEvent me) - { - base.OnMouseEvent (me); - if (!me.Flags.HasFlag (MouseFlags.Button1Clicked)) - { - return false; - } - - if (!CanFocus) - { - return false; - } - - SetFocus (); - - int boundsX = me.X; - int boundsY = me.Y; - - int pos = _orientation == Orientation.Horizontal ? boundsX : boundsY; - - int rCount = _orientation == Orientation.Horizontal - ? _horizontal.Last ().pos + _horizontal.Last ().length - : _radioLabels.Count; - - if (pos < rCount) - { - int c = _orientation == Orientation.Horizontal - ? _horizontal.FindIndex (x => x.pos <= boundsX && x.pos + x.length - 2 >= boundsX) - : boundsY; - - if (c > -1) - { - _cursor = SelectedItem = c; - SetNeedsDisplay (); - } - } - - return true; - } - /// public override void OnDrawContent (Rectangle contentArea) { From e1219707f626b6daec1186f5a902216f697fbd4e Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 2 Apr 2024 15:40:00 -0600 Subject: [PATCH 12/32] API docs --- Terminal.Gui/Views/Button.cs | 70 +++--------------------------------- 1 file changed, 5 insertions(+), 65 deletions(-) diff --git a/Terminal.Gui/Views/Button.cs b/Terminal.Gui/Views/Button.cs index c7c1096391..6fe4b7a4c4 100644 --- a/Terminal.Gui/Views/Button.cs +++ b/Terminal.Gui/Views/Button.cs @@ -20,6 +20,10 @@ namespace Terminal.Gui; /// no other processes the key, the 's event will /// be fired. /// +/// +/// Set to to have the event +/// invoked repeatedly while the button is pressed. +/// /// public class Button : View { @@ -46,6 +50,7 @@ public Button () CanFocus = true; AutoSize = true; + InvertColorsOnPress = true; // Override default behavior of View AddCommand (Command.HotKey, () => @@ -59,72 +64,7 @@ public Button () TitleChanged += Button_TitleChanged; MouseClick += Button_MouseClick; - InvertColorsOnPress = true; - } - - [CanBeNull] - private ColorScheme _savedColorScheme; - - private void Button_MouseEvent (object sender, MouseEventEventArgs e) - { - // Default behavior is to invoke Accept (via HotKey) on clicked. - if (!WantContinuousButtonPressed && - Application.MouseGrabView != this && - e.MouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked)) - { - e.Handled = InvokeCommand (Command.HotKey) == true; - return; - } - - if (e.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) - { - e.Handled = InvokeCommand (Command.HotKey) == true; - return; - } - - // The first time we get pressed event, grab the mouse and invert the colors - if (Application.MouseGrabView != this) - { - Application.GrabMouse (this); - _savedColorScheme = ColorScheme; - var cs = new ColorScheme (new Attribute (ColorScheme.Normal.Background, ColorScheme.Normal.Foreground)); - ColorScheme = cs; - - // Set the focus, but don't invoke Accept - SetFocus (); - } - } - - if (e.MouseEvent.Flags.HasFlag (MouseFlags.Button1Released)) - { - // When the mouse is released, if WantContinuousButtonPressed is set, invoke Accept one last time. - if (WantContinuousButtonPressed) - { - e.Handled = InvokeCommand (Command.HotKey) == true; - } - - if (Application.MouseGrabView == this) - { - Application.UngrabMouse (); - if (_savedColorScheme is { }) - { - ColorScheme = _savedColorScheme; - _savedColorScheme = null; - } - } - } - } - - /// - protected internal override bool OnMouseLeave (MouseEvent e) - { - return base.OnMouseLeave (e); } - private void Button_MouseClick (object sender, MouseEventEventArgs e) { e.Handled = InvokeCommand (Command.HotKey) == true; From 45309c75640cd363576e48f9609257d9d3174619 Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 2 Apr 2024 15:51:10 -0600 Subject: [PATCH 13/32] Better looking invert color logic --- Terminal.Gui/View/ViewMouse.cs | 20 ++++++++++++++++++-- UICatalog/Scenarios/Buttons.cs | 8 ++++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/Terminal.Gui/View/ViewMouse.cs b/Terminal.Gui/View/ViewMouse.cs index c8d07b99b9..30e20f15c0 100644 --- a/Terminal.Gui/View/ViewMouse.cs +++ b/Terminal.Gui/View/ViewMouse.cs @@ -149,8 +149,24 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) { Application.GrabMouse (this); _savedColorScheme = ColorScheme; - var cs = new ColorScheme (new Attribute (ColorScheme.Normal.Background, ColorScheme.Normal.Foreground)); - ColorScheme = cs; + + 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; + } // Set the focus, but don't invoke Accept SetFocus (); diff --git a/UICatalog/Scenarios/Buttons.cs b/UICatalog/Scenarios/Buttons.cs index 36f567e5da..545b4bf97f 100644 --- a/UICatalog/Scenarios/Buttons.cs +++ b/UICatalog/Scenarios/Buttons.cs @@ -396,12 +396,12 @@ string MoveHotkey (string txt) { X = Pos.Right (label) + 1, Y = Pos.Top (label), - Title = $"Accept Count: {noRepeatAcceptCount}", + Title = $"Accept Cou_nt: {noRepeatAcceptCount}", WantContinuousButtonPressed = false, }; noRepeatButton.Accept += (s, e) => { - noRepeatButton.Title = $"Accept Count: {++noRepeatAcceptCount}"; + noRepeatButton.Title = $"Accept Cou_nt: {++noRepeatAcceptCount}"; }; main.Add(label, noRepeatButton); @@ -416,12 +416,12 @@ string MoveHotkey (string txt) { X = Pos.Right (label) + 1, Y = Pos.Top (label), - Title = $"Accept Count: {acceptCount}", + Title = $"Accept Co_unt: {acceptCount}", WantContinuousButtonPressed = true, }; repeatButton.Accept += (s, e) => { - repeatButton.Title = $"Accept Count: {++acceptCount}"; + repeatButton.Title = $"Accept Co_unt: {++acceptCount}"; }; var enableCB = new CheckBox () From c1896ee0482637a43d3330a53e75612c420c0b6f Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 2 Apr 2024 16:22:55 -0600 Subject: [PATCH 14/32] Renamed to HighlightOnPress and added unit tests --- Terminal.Gui/View/ViewMouse.cs | 47 ++++++------ Terminal.Gui/Views/Button.cs | 2 +- Terminal.Gui/Views/CheckBox.cs | 2 +- Terminal.Gui/Views/ColorPicker.cs | 2 +- Terminal.Gui/Views/RadioGroup.cs | 2 +- UnitTests/View/MouseTests.cs | 120 +++++++++++++++++++++++++++++- UnitTests/Views/ButtonTests.cs | 8 +- 7 files changed, 150 insertions(+), 33 deletions(-) diff --git a/Terminal.Gui/View/ViewMouse.cs b/Terminal.Gui/View/ViewMouse.cs index 30e20f15c0..21091d1721 100644 --- a/Terminal.Gui/View/ViewMouse.cs +++ b/Terminal.Gui/View/ViewMouse.cs @@ -3,9 +3,9 @@ public partial class View { /// - /// Gets or sets whether the will invert the colors when the mouse button is pressed/released. + /// Gets or sets whether the will highlight the view visually when the mouse button is pressed/released. /// - public bool InvertColorsOnPress { get; set; } + public bool HighlightOnPress { get; set; } /// Gets or sets a value indicating whether this want continuous button pressed event. public virtual bool WantContinuousButtonPressed { get; set; } @@ -125,9 +125,9 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) // Default behavior is to invoke Accept (via HotKey) on clicked. - if (!WantContinuousButtonPressed && - Application.MouseGrabView != this && - mouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked) + 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)) @@ -135,7 +135,7 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) return OnMouseClick (args); } - if (InvertColorsOnPress && mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed)) + if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed)) { // If WantContinuousButtonPressed is true, and this is not the first pressed event, // invoke Accept (via HotKey) @@ -150,30 +150,35 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) Application.GrabMouse (this); _savedColorScheme = ColorScheme; - if (CanFocus) + if (HighlightOnPress && ColorScheme is { }) { - // TODO: Make the inverted color configurable - var cs = new ColorScheme (ColorScheme) + if (CanFocus) { - Focus = new Attribute (ColorScheme.Normal.Foreground, ColorScheme.Focus.Background) - }; - ColorScheme = cs; - } - else - { - var cs = new ColorScheme (ColorScheme) + // TODO: Make the inverted color configurable + var cs = new ColorScheme (ColorScheme) + { + Focus = new Attribute (ColorScheme.Normal.Foreground, ColorScheme.Focus.Background) + }; + ColorScheme = cs; + } + else { - Normal = new Attribute (ColorScheme.Focus.Background, ColorScheme.Normal.Foreground) - }; - ColorScheme = cs; + 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 (InvertColorsOnPress && mouseEvent.Flags.HasFlag (MouseFlags.Button1Released)) + if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Released)) { // When the mouse is released, if WantContinuousButtonPressed is set, invoke Accept one last time. if (WantContinuousButtonPressed) @@ -184,7 +189,7 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) if (Application.MouseGrabView == this) { Application.UngrabMouse (); - if (_savedColorScheme is { }) + if (HighlightOnPress && _savedColorScheme is { }) { ColorScheme = _savedColorScheme; _savedColorScheme = null; diff --git a/Terminal.Gui/Views/Button.cs b/Terminal.Gui/Views/Button.cs index 6fe4b7a4c4..0ab379b7df 100644 --- a/Terminal.Gui/Views/Button.cs +++ b/Terminal.Gui/Views/Button.cs @@ -50,7 +50,7 @@ public Button () CanFocus = true; AutoSize = true; - InvertColorsOnPress = true; + HighlightOnPress = true; // Override default behavior of View AddCommand (Command.HotKey, () => diff --git a/Terminal.Gui/Views/CheckBox.cs b/Terminal.Gui/Views/CheckBox.cs index 30979555e2..bcf41f2c13 100644 --- a/Terminal.Gui/Views/CheckBox.cs +++ b/Terminal.Gui/Views/CheckBox.cs @@ -35,7 +35,7 @@ public CheckBox () TitleChanged += Checkbox_TitleChanged; - InvertColorsOnPress = true; + HighlightOnPress = true; MouseClick += CheckBox_MouseClick; } diff --git a/Terminal.Gui/Views/ColorPicker.cs b/Terminal.Gui/Views/ColorPicker.cs index 36ff5b48ba..61c41d4e63 100644 --- a/Terminal.Gui/Views/ColorPicker.cs +++ b/Terminal.Gui/Views/ColorPicker.cs @@ -31,7 +31,7 @@ public class ColorPicker : View private void SetInitialProperties () { - InvertColorsOnPress = true; + HighlightOnPress = true; CanFocus = true; AddCommands (); diff --git a/Terminal.Gui/Views/RadioGroup.cs b/Terminal.Gui/Views/RadioGroup.cs index 7a16265538..13c7d53fd6 100644 --- a/Terminal.Gui/Views/RadioGroup.cs +++ b/Terminal.Gui/Views/RadioGroup.cs @@ -77,7 +77,7 @@ public RadioGroup () LayoutStarted += RadioGroup_LayoutStarted; - InvertColorsOnPress = true; + HighlightOnPress = true; MouseClick += RadioGroup_MouseClick; } diff --git a/UnitTests/View/MouseTests.cs b/UnitTests/View/MouseTests.cs index 067f5f4c83..1e56e679f0 100644 --- a/UnitTests/View/MouseTests.cs +++ b/UnitTests/View/MouseTests.cs @@ -75,8 +75,6 @@ public void ButtonPressed_In_Margin_Or_Border_Starts_Drag (int marginThickness, Assert.Equal (new Point (4, 4), testView.Frame.Location); Application.OnMouseEvent (new (new () { X = xy, Y = xy, Flags = MouseFlags.Button1Pressed })); - Assert.False (Application.MouseGrabView is { } && (Application.MouseGrabView != testView.Margin && Application.MouseGrabView != testView.Border)); - Application.OnMouseEvent (new (new () { X = xy + 1, Y = xy + 1, Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition })); Assert.Equal (expectedMoved, new Point (5, 5) == testView.Frame.Location); @@ -135,12 +133,12 @@ public void AllViews_Enter_Leave_Events (View view, string viewName) { X = 0, Y = 0, Height = 1, - Width = 1, + Width = 1, CanFocus = true, }; view.AutoSize = false; - view.X = Pos.Right(otherView); + view.X = Pos.Right (otherView); view.Y = 0; view.Width = 10; view.Height = 1; @@ -318,4 +316,118 @@ public void AllViews_OnMouseClick_Enabled_False_Does_Not_Set_Handled (View view, Assert.False (me.Handled); view.Dispose (); } + + [Fact] + public void WantContinuousButtonPressed_False_Button1Press_Release_DoesNotClick () + { + var view = new View () + { + WantContinuousButtonPressed = false + }; + + var clicked = 0; + + view.MouseClick += (s, e) => clicked++; + + var me = new MouseEvent () + { + Flags = MouseFlags.Button1Pressed + }; + + view.OnMouseEvent (me); + Assert.Equal (0, clicked); + me.Handled = false; + + view.OnMouseEvent (me); + Assert.Equal (0, clicked); + me.Handled = false; + + me.Flags = MouseFlags.Button1Released; + view.OnMouseEvent (me); + Assert.Equal (0, clicked); + + me.Flags = MouseFlags.Button1Clicked; + view.OnMouseEvent (me); + Assert.Equal (1, clicked); + + view.Dispose (); + } + [Fact] + public void WantContinuousButtonPressed_True_Button1Press_Release_Repeats () + { + var view = new View () + { + WantContinuousButtonPressed = true + }; + + var clicked = 0; + + view.MouseClick += (s, e) => clicked++; + + var me = new MouseEvent () + { + Flags = MouseFlags.Button1Pressed + }; + + view.OnMouseEvent (me); + Assert.Equal (0, clicked); + me.Handled = false; + + view.OnMouseEvent (me); + Assert.Equal (1, clicked); + me.Handled = false; + + me.Flags = MouseFlags.Button1Released; + view.OnMouseEvent (me); + Assert.Equal (2, clicked); + + me.Flags = MouseFlags.Button1Clicked; + view.OnMouseEvent (me); + Assert.Equal (2, clicked); + + view.Dispose (); + } + + [Fact] + public void HighlightOnPress_False_No_Highlights () + { + var view = new View () + { + HighlightOnPress = false + }; + view.ColorScheme = new ColorScheme (new Attribute (ColorName.Red, ColorName.Blue)); + ColorScheme originalColorScheme = view.ColorScheme; + + var me = new MouseEvent () + { + Flags = MouseFlags.Button1Pressed + }; + + view.OnMouseEvent (me); + Assert.Equal (originalColorScheme, view.ColorScheme); + + view.Dispose (); + } + + + [Fact] + public void HighlightOnPress_False_Highlights () + { + var view = new View () + { + HighlightOnPress = true + }; + view.ColorScheme = new ColorScheme (new Attribute (ColorName.Red, ColorName.Blue)); + ColorScheme originalColorScheme = view.ColorScheme; + + var me = new MouseEvent () + { + Flags = MouseFlags.Button1Pressed + }; + + view.OnMouseEvent (me); + Assert.NotEqual (originalColorScheme, view.ColorScheme); + + view.Dispose (); + } } diff --git a/UnitTests/Views/ButtonTests.cs b/UnitTests/Views/ButtonTests.cs index d775568acf..24fab8ae26 100644 --- a/UnitTests/Views/ButtonTests.cs +++ b/UnitTests/Views/ButtonTests.cs @@ -104,7 +104,7 @@ public void AutoSize_False_With_Fixed_Width () tab.Add (ckbMatchWholeWord); var tabView = new TabView { Width = Dim.Fill (), Height = Dim.Fill () }; - tabView.AddTab (new() { DisplayText = "Find", View = tab }, true); + tabView.AddTab (new () { DisplayText = "Find", View = tab }, true); var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; @@ -412,7 +412,7 @@ public void Constructors_Defaults () TestHelpers.AssertDriverContentsWithFrameAre (expected, output); btn.Dispose (); - btn = new() { Text = "_Test", IsDefault = true }; + btn = new () { Text = "_Test", IsDefault = true }; btn.BeginInit (); btn.EndInit (); Assert.Equal ('_', btn.HotKeySpecifier.Value); @@ -432,7 +432,7 @@ public void Constructors_Defaults () btn.Dispose (); - btn = new() { X = 1, Y = 2, Text = "_abc", IsDefault = true }; + btn = new () { X = 1, Y = 2, Text = "_abc", IsDefault = true }; btn.BeginInit (); btn.EndInit (); Assert.Equal ("_abc", btn.Text); @@ -757,4 +757,4 @@ public void Update_Parameterless_Only_On_Or_After_Initialize () Assert.Equal (new (0, 0, 30, 5), pos); top.Dispose (); } -} +} \ No newline at end of file From 2ed6ed52c75342f55c9184f0ad64b9a3f4924163 Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 2 Apr 2024 16:38:42 -0600 Subject: [PATCH 15/32] beefed up unit tests --- Terminal.Gui/View/ViewMouse.cs | 103 ++++++++++++++++----------------- UnitTests/View/MouseTests.cs | 70 ++++++++++++---------- 2 files changed, 90 insertions(+), 83 deletions(-) diff --git a/Terminal.Gui/View/ViewMouse.cs b/Terminal.Gui/View/ViewMouse.cs index 21091d1721..f06c0615c1 100644 --- a/Terminal.Gui/View/ViewMouse.cs +++ b/Terminal.Gui/View/ViewMouse.cs @@ -3,7 +3,8 @@ public partial class View { /// - /// Gets or sets whether the will highlight the view visually when the mouse button is pressed/released. + /// Gets or sets whether the will highlight the view visually when the mouse button is + /// pressed/released. /// public bool HighlightOnPress { get; set; } @@ -16,21 +17,21 @@ public partial class View /// Event fired when a mouse event occurs. /// - /// - /// The coordinates are relative to . - /// + /// + /// 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 . - /// + /// + /// 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; @@ -42,11 +43,12 @@ public partial class View // 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 + /// 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 . + /// The coordinates are relative to . /// /// /// , if the event was handled, otherwise. @@ -70,11 +72,12 @@ protected internal virtual bool OnMouseEnter (MouseEvent mouseEvent) // 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 + /// 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 . + /// The coordinates are relative to . /// /// /// , if the event was handled, otherwise. @@ -102,9 +105,9 @@ protected internal virtual bool OnMouseLeave (MouseEvent mouseEvent) // TODO: OnMouseEvent should not be public virtual, but protected. /// Called when a mouse event occurs within the view's . /// - /// - /// The coordinates are relative to . - /// + /// + /// The coordinates are relative to . + /// /// /// /// , if the event was handled, otherwise. @@ -123,19 +126,21 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) 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)) + 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 (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed) + || mouseEvent.Flags.HasFlag (MouseFlags.Button2Pressed) + || mouseEvent.Flags.HasFlag (MouseFlags.Button3Pressed) + || mouseEvent.Flags.HasFlag (MouseFlags.Button4Pressed)) { // If WantContinuousButtonPressed is true, and this is not the first pressed event, // invoke Accept (via HotKey) @@ -157,7 +162,7 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) // TODO: Make the inverted color configurable var cs = new ColorScheme (ColorScheme) { - Focus = new Attribute (ColorScheme.Normal.Foreground, ColorScheme.Focus.Background) + Focus = new (ColorScheme.Normal.Foreground, ColorScheme.Focus.Background) }; ColorScheme = cs; } @@ -165,20 +170,24 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) { var cs = new ColorScheme (ColorScheme) { - Normal = new Attribute (ColorScheme.Focus.Background, ColorScheme.Normal.Foreground) + Normal = new (ColorScheme.Focus.Background, ColorScheme.Normal.Foreground) }; ColorScheme = cs; } } - if (CanFocus){ - // Set the focus, but don't invoke Accept - SetFocus (); + if (CanFocus) + { + // Set the focus, but don't invoke Accept + SetFocus (); } } } - if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Released)) + if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Released) + || mouseEvent.Flags.HasFlag (MouseFlags.Button2Released) + || mouseEvent.Flags.HasFlag (MouseFlags.Button3Released) + || mouseEvent.Flags.HasFlag (MouseFlags.Button4Released)) { // When the mouse is released, if WantContinuousButtonPressed is set, invoke Accept one last time. if (WantContinuousButtonPressed) @@ -189,6 +198,7 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) if (Application.MouseGrabView == this) { Application.UngrabMouse (); + if (HighlightOnPress && _savedColorScheme is { }) { ColorScheme = _savedColorScheme; @@ -197,37 +207,20 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) } } - //// 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; + return args.Handled; } /// Invokes the MouseClick event. /// - /// - /// Called when the mouse is either clicked or double-clicked. Check - /// to see which button was clicked. - /// + /// + /// Called when the mouse is either clicked or double-clicked. Check + /// to see which button was clicked. + /// /// protected bool OnMouseClick (MouseEventEventArgs args) { @@ -235,10 +228,12 @@ protected bool OnMouseClick (MouseEventEventArgs args) { // 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; diff --git a/UnitTests/View/MouseTests.cs b/UnitTests/View/MouseTests.cs index 1e56e679f0..12a81e2101 100644 --- a/UnitTests/View/MouseTests.cs +++ b/UnitTests/View/MouseTests.cs @@ -317,73 +317,85 @@ public void AllViews_OnMouseClick_Enabled_False_Does_Not_Set_Handled (View view, view.Dispose (); } - [Fact] - public void WantContinuousButtonPressed_False_Button1Press_Release_DoesNotClick () + [Theory] + [InlineData (MouseFlags.Button1Pressed, MouseFlags.Button1Released, MouseFlags.Button1Clicked)] + [InlineData (MouseFlags.Button2Pressed, MouseFlags.Button2Released, MouseFlags.Button2Clicked)] + [InlineData (MouseFlags.Button3Pressed, MouseFlags.Button3Released, MouseFlags.Button3Clicked)] + [InlineData (MouseFlags.Button4Pressed, MouseFlags.Button4Released, MouseFlags.Button4Clicked)] + public void WantContinuousButtonPressed_False_Button1Press_Release_DoesNotClick (MouseFlags pressed, MouseFlags released, MouseFlags clicked) { + var me = new MouseEvent () + { + Flags = pressed + }; + var view = new View () { WantContinuousButtonPressed = false }; - var clicked = 0; + var clickedCount = 0; - view.MouseClick += (s, e) => clicked++; + view.MouseClick += (s, e) => clickedCount++; - var me = new MouseEvent () - { - Flags = MouseFlags.Button1Pressed - }; view.OnMouseEvent (me); - Assert.Equal (0, clicked); + Assert.Equal (0, clickedCount); me.Handled = false; view.OnMouseEvent (me); - Assert.Equal (0, clicked); + Assert.Equal (0, clickedCount); me.Handled = false; - me.Flags = MouseFlags.Button1Released; + me.Flags = released; view.OnMouseEvent (me); - Assert.Equal (0, clicked); + Assert.Equal (0, clickedCount); + me.Handled = false; - me.Flags = MouseFlags.Button1Clicked; + me.Flags =clicked; view.OnMouseEvent (me); - Assert.Equal (1, clicked); + Assert.Equal (1, clickedCount); view.Dispose (); } - [Fact] - public void WantContinuousButtonPressed_True_Button1Press_Release_Repeats () + + [Theory] + [InlineData (MouseFlags.Button1Pressed, MouseFlags.Button1Released, MouseFlags.Button1Clicked)] + [InlineData (MouseFlags.Button2Pressed, MouseFlags.Button2Released, MouseFlags.Button2Clicked)] + [InlineData (MouseFlags.Button3Pressed, MouseFlags.Button3Released, MouseFlags.Button3Clicked)] + [InlineData (MouseFlags.Button4Pressed, MouseFlags.Button4Released, MouseFlags.Button4Clicked)] + public void WantContinuousButtonPressed_True_Button1Press_Release_Clicks_Repeatedly (MouseFlags pressed, MouseFlags released, MouseFlags clicked) { + var me = new MouseEvent () + { + Flags = pressed + }; + var view = new View () { WantContinuousButtonPressed = true }; - var clicked = 0; + var clickedCount = 0; - view.MouseClick += (s, e) => clicked++; - - var me = new MouseEvent () - { - Flags = MouseFlags.Button1Pressed - }; + view.MouseClick += (s, e) => clickedCount++; view.OnMouseEvent (me); - Assert.Equal (0, clicked); + Assert.Equal (0, clickedCount); me.Handled = false; view.OnMouseEvent (me); - Assert.Equal (1, clicked); + Assert.Equal (1, clickedCount); me.Handled = false; - me.Flags = MouseFlags.Button1Released; + me.Flags = released; view.OnMouseEvent (me); - Assert.Equal (2, clicked); + Assert.Equal (2, clickedCount); + me.Handled = false; - me.Flags = MouseFlags.Button1Clicked; + me.Flags = clicked; view.OnMouseEvent (me); - Assert.Equal (2, clicked); + Assert.Equal (2, clickedCount); view.Dispose (); } From 1f89d6f098a5b1694e6e2e26068a0bb98b0ca5c1 Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 2 Apr 2024 16:43:18 -0600 Subject: [PATCH 16/32] Code cleanup --- Terminal.Gui/View/ViewMouse.cs | 67 ++++++++++++++++------------------ 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/Terminal.Gui/View/ViewMouse.cs b/Terminal.Gui/View/ViewMouse.cs index f06c0615c1..0a3311e1ca 100644 --- a/Terminal.Gui/View/ViewMouse.cs +++ b/Terminal.Gui/View/ViewMouse.cs @@ -3,45 +3,18 @@ public partial class View { /// - /// Gets or sets whether the will highlight the view visually when the mouse button is - /// pressed/released. + /// Gets or sets whether the will be highlighted visually while the mouse button is + /// pressed. /// public bool HighlightOnPress { get; set; } - /// Gets or sets a value indicating whether this want continuous button pressed event. + /// Gets or sets whether the wants continuous button pressed events. public virtual bool WantContinuousButtonPressed { get; set; } - /// Gets or sets a value indicating whether this wants mouse position reports. - /// if want mouse position reports; otherwise, . + /// Gets or sets whether the wants mouse position reports. + /// if mouse position reports are wanted; 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 @@ -70,7 +43,9 @@ protected internal virtual bool OnMouseEnter (MouseEvent mouseEvent) return args.Handled; } - // TODO: OnMouseLeave should not be public virtual, but protected. + /// Event fired when the mouse moves into the View's . + public event EventHandler MouseEnter; + /// /// Called when the mouse has moved out of the View's . The view will no longer receive mouse /// events (until the @@ -99,10 +74,12 @@ protected internal virtual bool OnMouseLeave (MouseEvent mouseEvent) return args.Handled; } + /// Event fired when the mouse leaves the View's . + public event EventHandler MouseLeave; + [CanBeNull] private ColorScheme _savedColorScheme; - // TODO: OnMouseEvent should not be public virtual, but protected. /// Called when a mouse event occurs within the view's . /// /// @@ -215,6 +192,14 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) return args.Handled; } + /// Event fired when a mouse event occurs. + /// + /// + /// The coordinates are relative to . + /// + /// + public event EventHandler MouseEvent; + /// Invokes the MouseClick event. /// /// @@ -247,4 +232,16 @@ protected bool OnMouseClick (MouseEventEventArgs args) return args.Handled; } + + /// 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; } From 86617724de81a2b7a3c700ec464443b75b76f17b Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 2 Apr 2024 17:08:47 -0600 Subject: [PATCH 17/32] Revamped Mouse scenario --- UICatalog/Scenarios/Mouse.cs | 100 +++++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 22 deletions(-) diff --git a/UICatalog/Scenarios/Mouse.cs b/UICatalog/Scenarios/Mouse.cs index 0e214a3a07..966c90423d 100644 --- a/UICatalog/Scenarios/Mouse.cs +++ b/UICatalog/Scenarios/Mouse.cs @@ -7,45 +7,101 @@ namespace UICatalog.Scenarios; [ScenarioCategory ("Mouse and Keyboard")] public class Mouse : Scenario { - public override void Setup () + public override void Main () { + Window win = new () + { + Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}", + }; + Label ml; var count = 0; ml = new Label { X = 1, Y = 1, Text = "Mouse: " }; - List rme = new (); - Win.Add (ml); + win.Add (ml); + + CheckBox cbWantContinuousPresses = new CheckBox () + { + X = 0, + Y = Pos.Bottom(ml) + 1, + Title = "_Want Continuous Button Presses", + }; + cbWantContinuousPresses.Toggled += (s,e) => + { + win.WantContinuousButtonPressed = !win.WantContinuousButtonPressed; + }; + + win.Add (cbWantContinuousPresses); + + var demo = new MouseDemo () + { + X = 0, + Y = Pos.Bottom (cbWantContinuousPresses) + 1, + Width = 20, + Height = 5, + Text = "Enter/Leave Demo", + TextAlignment = TextAlignment.Centered, + VerticalTextAlignment = VerticalTextAlignment.Middle, + ColorScheme = Colors.ColorSchemes ["Dialog"], + }; + win.Add (demo); - var logList = new ListView + var label = new Label () { - X = Pos.AnchorEnd (41), - Y = 0, - Width = 41, + Text = "_App Events:", + X = 0, + Y = Pos.Bottom (demo), + }; + List appLogList = new (); + var appLog = new ListView + { + X = Pos.Left (label), + Y = Pos.Bottom (label), + Width = Dim.Percent(49), Height = Dim.Fill (), ColorScheme = Colors.ColorSchemes ["TopLevel"], - Source = new ListWrapper (rme) + Source = new ListWrapper (appLogList) }; - Win.Add (logList); + win.Add (label, appLog); Application.MouseEvent += (sender, a) => { - ml.Text = $"Mouse: ({a.MouseEvent.X},{a.MouseEvent.Y}) - {a.MouseEvent.Flags} {count}"; - rme.Add ($"({a.MouseEvent.X},{a.MouseEvent.Y}) - {a.MouseEvent.Flags} {count++}"); - logList.MoveDown (); + ml.Text = $"MouseEvent: ({a.MouseEvent.X},{a.MouseEvent.Y}) - {a.MouseEvent.Flags} {count}"; + appLogList.Add ($"({a.MouseEvent.X},{a.MouseEvent.Y}) - {a.MouseEvent.Flags} {count++}"); + appLog.MoveDown (); }; - Win.Add (new MouseDemo () + + label = new Label () { - X = 0, - Y = 3, - Width = 15, - Height = 10, - Text = "Mouse Demo", - TextAlignment = TextAlignment.Centered, - VerticalTextAlignment = VerticalTextAlignment.Middle, - ColorScheme = Colors.ColorSchemes ["Dialog"], - }); + Text = "_Window Events:", + X = Pos.Percent(50), + Y = Pos.Bottom (demo), + }; + List winLogList = new (); + var winLog = new ListView + { + X = Pos.Left(label), + Y = Pos.Bottom (label), + Width = Dim.Percent (50), + Height = Dim.Fill (), + ColorScheme = Colors.ColorSchemes ["TopLevel"], + Source = new ListWrapper (winLogList) + }; + win.Add (label, winLog); + win.MouseEvent += (sender, a) => + { + winLogList.Add ($"MouseEvent: ({a.MouseEvent.X},{a.MouseEvent.Y}) - {a.MouseEvent.Flags} {count++}"); + winLog.MoveDown (); + }; + win.MouseClick += (sender, a) => + { + winLogList.Add ($"MouseClick: ({a.MouseEvent.X},{a.MouseEvent.Y}) - {a.MouseEvent.Flags} {count++}"); + winLog.MoveDown (); + }; + Application.Run (win); + win.Dispose (); } public class MouseDemo : View From ca3b49dfe863c3c110ce10f35c797eb47ec221e2 Mon Sep 17 00:00:00 2001 From: Tig Date: Tue, 2 Apr 2024 17:21:14 -0600 Subject: [PATCH 18/32] Found and fixed coord bug in Application.OnMouseEvent --- Terminal.Gui/Application.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Terminal.Gui/Application.cs b/Terminal.Gui/Application.cs index d5bac89d99..53cd14af6a 100644 --- a/Terminal.Gui/Application.cs +++ b/Terminal.Gui/Application.cs @@ -1472,15 +1472,15 @@ internal static void OnMouseEvent (MouseEventEventArgs a) { // If the mouse is grabbed, send the event to the view that grabbed it. // The coordinates are relative to the Bounds of the view that grabbed the mouse. - Point frameLoc = MouseGrabView.ScreenToFrame (a.MouseEvent.X, a.MouseEvent.Y); + Point boundsLoc = MouseGrabView.ScreenToBounds (a.MouseEvent.X, a.MouseEvent.Y); var viewRelativeMouseEvent = new MouseEvent { - X = frameLoc.X, - Y = frameLoc.Y, + X = boundsLoc.X, + Y = boundsLoc.Y, Flags = a.MouseEvent.Flags, ScreenPosition = new (a.MouseEvent.X, a.MouseEvent.Y), - View = view + View = MouseGrabView }; if (MouseGrabView.Bounds.Contains (viewRelativeMouseEvent.X, viewRelativeMouseEvent.Y) is false) From 3bd69c24f33f9013c63c9759e670dea5eae76a06 Mon Sep 17 00:00:00 2001 From: Tig Date: Wed, 3 Apr 2024 06:19:00 -0600 Subject: [PATCH 19/32] Set args.Handled where needed --- Terminal.Gui/View/ViewMouse.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Terminal.Gui/View/ViewMouse.cs b/Terminal.Gui/View/ViewMouse.cs index 0a3311e1ca..522a206b90 100644 --- a/Terminal.Gui/View/ViewMouse.cs +++ b/Terminal.Gui/View/ViewMouse.cs @@ -158,6 +158,7 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) // Set the focus, but don't invoke Accept SetFocus (); } + args.Handled = true; } } @@ -181,6 +182,7 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) ColorScheme = _savedColorScheme; _savedColorScheme = null; } + args.Handled = true; } } From 94749e428ee343f6d1bb2e490f4ddb13b66cf27a Mon Sep 17 00:00:00 2001 From: Tig Date: Wed, 3 Apr 2024 09:17:14 -0600 Subject: [PATCH 20/32] Fixed crash moving mouuse in All Views Tester --- Terminal.Gui/View/Adornment/Adornment.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Terminal.Gui/View/Adornment/Adornment.cs b/Terminal.Gui/View/Adornment/Adornment.cs index b6277f326a..67b8a25e08 100644 --- a/Terminal.Gui/View/Adornment/Adornment.cs +++ b/Terminal.Gui/View/Adornment/Adornment.cs @@ -203,6 +203,10 @@ public override bool SuperViewRendersLineCanvas /// if the specified Parent's SuperView-relative coordinates are within the Adornment's Thickness. public override bool Contains (int x, int y) { + if (Parent is null) + { + return false; + } Rectangle frame = Frame; frame.Offset (Parent.Frame.Location); From a8d6f846d74e99ba53ba2e63eb378e679b8c77e9 Mon Sep 17 00:00:00 2001 From: Tig Date: Wed, 3 Apr 2024 09:41:59 -0600 Subject: [PATCH 21/32] Fixed MessagBox paint issue --- Terminal.Gui/Views/MessageBox.cs | 119 +++++++++++++++---------------- UICatalog/Scenarios/Buttons.cs | 2 - 2 files changed, 59 insertions(+), 62 deletions(-) diff --git a/Terminal.Gui/Views/MessageBox.cs b/Terminal.Gui/Views/MessageBox.cs index 04e4c25b70..9b00337d71 100644 --- a/Terminal.Gui/Views/MessageBox.cs +++ b/Terminal.Gui/Views/MessageBox.cs @@ -386,66 +386,6 @@ params string [] buttons messageLabel.TextFormatter.MultiLine = !wrapMessage; d.Add (messageLabel); - d.Loaded += (s, e) => - { - if (width != 0 || height != 0) - { - return; - } - - // TODO: replace with Dim.Fit when implemented - Rectangle maxBounds = d.SuperView?.Bounds ?? Application.Top.Bounds; - - Thickness adornmentsThickness = d.GetAdornmentsThickness (); - - if (wrapMessage) - { - messageLabel.TextFormatter.Size = new ( - maxBounds.Size.Width - - adornmentsThickness.Horizontal, - maxBounds.Size.Height - - adornmentsThickness.Vertical - ); - } - - string msg = messageLabel.TextFormatter.Format (); - Size messageSize = messageLabel.TextFormatter.FormatAndGetSize (); - - // Ensure the width fits the text + buttons - int newWidth = Math.Max ( - width, - Math.Max ( - messageSize.Width + adornmentsThickness.Horizontal, - d.GetButtonsWidth () + d.Buttons.Length + adornmentsThickness.Horizontal - ) - ); - - if (newWidth > d.Frame.Width) - { - d.Width = newWidth; - } - - // Ensure height fits the text + vspace + buttons - if (messageSize.Height == 0) - { - d.Height = Math.Max (height, 3 + adornmentsThickness.Vertical); - } - else - { - string lastLine = messageLabel.TextFormatter.GetLines () [^1]; - - // INTENT: Instead of the check against \n or \r\n, how about just Environment.NewLine? - d.Height = Math.Max ( - height, - messageSize.Height - + (lastLine.EndsWith ("\r\n") || lastLine.EndsWith ('\n') ? 1 : 2) - + adornmentsThickness.Vertical - ); - } - - d.SetRelativeLayout (d.SuperView?.Frame ?? Application.Top.Frame); - }; - // Setup actions Clicked = -1; @@ -466,10 +406,69 @@ params string [] buttons } } + d.Loaded += Dialog_Loaded; + // Run the modal; do not shutdown the mainloop driver when done Application.Run (d); d.Dispose (); return Clicked; + + void Dialog_Loaded (object s, EventArgs e) + { + if (width != 0 || height != 0) + { + return; + } + + // TODO: replace with Dim.Fit when implemented + Rectangle maxBounds = d.SuperView?.Bounds ?? Application.Top.Bounds; + + Thickness adornmentsThickness = d.GetAdornmentsThickness (); + + if (wrapMessage) + { + messageLabel.TextFormatter.Size = new ( + maxBounds.Size.Width + - adornmentsThickness.Horizontal, + maxBounds.Size.Height + - adornmentsThickness.Vertical); + } + + string msg = messageLabel.TextFormatter.Format (); + Size messageSize = messageLabel.TextFormatter.FormatAndGetSize (); + + // Ensure the width fits the text + buttons + int newWidth = Math.Max ( + width, + Math.Max ( + messageSize.Width + adornmentsThickness.Horizontal, + d.GetButtonsWidth () + d.Buttons.Length + adornmentsThickness.Horizontal)); + + if (newWidth > d.Frame.Width) + { + d.Width = newWidth; + } + + // Ensure height fits the text + vspace + buttons + if (messageSize.Height == 0) + { + d.Height = Math.Max (height, 3 + adornmentsThickness.Vertical); + } + else + { + string lastLine = messageLabel.TextFormatter.GetLines () [^1]; + + // INTENT: Instead of the check against \n or \r\n, how about just Environment.NewLine? + d.Height = Math.Max ( + height, + messageSize.Height + + (lastLine.EndsWith ("\r\n") || lastLine.EndsWith ('\n') ? 1 : 2) + + adornmentsThickness.Vertical); + } + + d.SetRelativeLayout (d.SuperView?.Frame ?? Application.Top.Frame); + d.LayoutSubviews (); + } } } diff --git a/UICatalog/Scenarios/Buttons.cs b/UICatalog/Scenarios/Buttons.cs index 545b4bf97f..068c15a7c2 100644 --- a/UICatalog/Scenarios/Buttons.cs +++ b/UICatalog/Scenarios/Buttons.cs @@ -61,8 +61,6 @@ static void DoMessage (Button button, string txt) { ColorScheme = colorScheme.Value, X = Pos.Right (prev) + 2, - - //X = x, Y = Pos.Y (colorButtonsLabel), Text = $"_{colorScheme.Key}" }; From f793eb4bb6fb581dcb9b5af09cb9275ae15ad4c5 Mon Sep 17 00:00:00 2001 From: Tig Date: Wed, 3 Apr 2024 13:39:02 -0500 Subject: [PATCH 22/32] Cherry picked #3382 fix --- Terminal.Gui/ConsoleDrivers/WindowsDriver.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index 017a4be628..3e78b219f9 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -1791,8 +1791,7 @@ private MouseEvent ToDriverMouse (WindowsConsole.MouseEventRecord mouseEvent) { var mouseFlag = MouseFlags.AllEvents; - //System.Diagnostics.Debug.WriteLine ( - // $"X:{mouseEvent.MousePosition.X};Y:{mouseEvent.MousePosition.Y};ButtonState:{mouseEvent.ButtonState};EventFlags:{mouseEvent.EventFlags}"); + //Debug.WriteLine ($"ToDriverMouse: {mouseEvent}"); if (_isButtonDoubleClicked || _isOneFingerDoubleClicked) { @@ -2147,6 +2146,19 @@ void IMainLoopDriver.Iteration () void IMainLoopDriver.TearDown () { + // Eat any outstanding events. See # + //var records = + _winConsole.ReadConsoleInput (); + + //if (records != null) + //{ + // foreach (var rec in records) + // { + // Debug.WriteLine ($"Teardown: {rec.ToString ()}"); + // //Debug.Assert (rec is not { EventType: WindowsConsole.EventType.Mouse, MouseEvent.ButtonState: WindowsConsole.ButtonState.Button1Pressed }); + // } + //} + _inputHandlerTokenSource?.Cancel (); _inputHandlerTokenSource?.Dispose (); From fd7e273f852b55e8034d93982d8ce436f27fa582 Mon Sep 17 00:00:00 2001 From: Tig Date: Wed, 3 Apr 2024 21:10:14 -0400 Subject: [PATCH 23/32] Updated Mouse scenario with filter --- Terminal.Gui/ConsoleDrivers/WindowsDriver.cs | 2 +- Terminal.Gui/View/ViewMouse.cs | 32 +++++--- UICatalog/Scenarios/Mouse.cs | 79 ++++++++++++++++---- 3 files changed, 85 insertions(+), 28 deletions(-) diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index 3e78b219f9..b4464b4251 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -1712,7 +1712,7 @@ private async Task ProcessContinuousButtonPressedAsync (MouseFlags mouseFlag) { // When a user presses-and-holds, start generating pressed events every `startDelay` // After `iterationsUntilFast` iterations, speed them up to `fastDelay` ms - const int startDelay = 500; + const int startDelay = 50; const int iterationsUntilFast = 4; const int fastDelay = 50; diff --git a/Terminal.Gui/View/ViewMouse.cs b/Terminal.Gui/View/ViewMouse.cs index 522a206b90..70416b8b37 100644 --- a/Terminal.Gui/View/ViewMouse.cs +++ b/Terminal.Gui/View/ViewMouse.cs @@ -14,7 +14,7 @@ public partial class View /// Gets or sets whether the wants mouse position reports. /// if mouse position reports are wanted; otherwise, . public virtual bool WantMousePositionReports { get; set; } - + /// /// Called when the mouse enters the View's . The view will now receive mouse events until the /// mouse leaves @@ -104,16 +104,22 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) var args = new MouseEventEventArgs (mouseEvent); // Default behavior is to invoke Accept (via HotKey) on clicked. - if (!WantContinuousButtonPressed - && Application.MouseGrabView != this + if ( + !HighlightOnPress + && Application.MouseGrabView is null && (mouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked) || mouseEvent.Flags.HasFlag (MouseFlags.Button2Clicked) || mouseEvent.Flags.HasFlag (MouseFlags.Button3Clicked) || mouseEvent.Flags.HasFlag (MouseFlags.Button4Clicked))) - { + { return OnMouseClick (args); } + if (!HighlightOnPress) + { + return false; + } + if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed) || mouseEvent.Flags.HasFlag (MouseFlags.Button2Pressed) || mouseEvent.Flags.HasFlag (MouseFlags.Button3Pressed) @@ -130,10 +136,10 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) if (Application.MouseGrabView != this) { Application.GrabMouse (this); - _savedColorScheme = ColorScheme; if (HighlightOnPress && ColorScheme is { }) { + _savedColorScheme = ColorScheme; if (CanFocus) { // TODO: Make the inverted color configurable @@ -158,8 +164,8 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) // Set the focus, but don't invoke Accept SetFocus (); } - args.Handled = true; } + args.Handled = true; } if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Released) @@ -167,14 +173,15 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) || mouseEvent.Flags.HasFlag (MouseFlags.Button3Released) || mouseEvent.Flags.HasFlag (MouseFlags.Button4Released)) { - // When the mouse is released, if WantContinuousButtonPressed is set, invoke Accept one last time. - if (WantContinuousButtonPressed) - { - OnMouseClick (args); - } if (Application.MouseGrabView == this) { + // When the mouse is released, if WantContinuousButtonPressed is set, invoke Accept one last time. + //if (WantContinuousButtonPressed) + { + OnMouseClick (args); + } + Application.UngrabMouse (); if (HighlightOnPress && _savedColorScheme is { }) @@ -182,8 +189,8 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) ColorScheme = _savedColorScheme; _savedColorScheme = null; } - args.Handled = true; } + args.Handled = true; } if (args.Handled != true) @@ -209,6 +216,7 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) /// to see which button was clicked. /// /// + /// , if the event was handled, otherwise. protected bool OnMouseClick (MouseEventEventArgs args) { if (!Enabled) diff --git a/UICatalog/Scenarios/Mouse.cs b/UICatalog/Scenarios/Mouse.cs index 966c90423d..b10a3d27e3 100644 --- a/UICatalog/Scenarios/Mouse.cs +++ b/UICatalog/Scenarios/Mouse.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.CommandLine; +using System.Linq; using Terminal.Gui; namespace UICatalog.Scenarios; @@ -14,19 +17,53 @@ public override void Main () Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}", }; + + var filterSlider = new Slider () + { + Title = "_Filter", + X = 0, + Y = 0, + AutoSize = true, + BorderStyle = LineStyle.Single, + Type = SliderType.Multiple, + Orientation = Orientation.Vertical, + }; + filterSlider.Options = Enum.GetValues (typeof (MouseFlags)) + .Cast () + .Where (value => !value.ToString ().Contains ("None") && + !value.ToString().Contains("All")) + .Select (value => new SliderOption + { + Legend = value.ToString (), + Data = value, + }) + .ToList (); + for (int i = 0; i < filterSlider.Options.Count; i++) + { + filterSlider.SetOption (i); + } + win.Add (filterSlider); + + var clearButton = new Button () + { + Title = "_Clear Logs", + X = 1, + Y = Pos.Bottom (filterSlider) + 1, + }; + win.Add (clearButton); Label ml; var count = 0; - ml = new Label { X = 1, Y = 1, Text = "Mouse: " }; + ml = new Label { X = Pos.Right(filterSlider), Y = 0, Text = "Mouse: " }; win.Add (ml); CheckBox cbWantContinuousPresses = new CheckBox () { - X = 0, - Y = Pos.Bottom(ml) + 1, + X = Pos.Right (filterSlider), + Y = Pos.Bottom (ml) + 1, Title = "_Want Continuous Button Presses", }; - cbWantContinuousPresses.Toggled += (s,e) => + cbWantContinuousPresses.Toggled += (s, e) => { win.WantContinuousButtonPressed = !win.WantContinuousButtonPressed; }; @@ -35,10 +72,10 @@ public override void Main () var demo = new MouseDemo () { - X = 0, + X = Pos.Right (filterSlider), Y = Pos.Bottom (cbWantContinuousPresses) + 1, Width = 20, - Height = 5, + Height = 3, Text = "Enter/Leave Demo", TextAlignment = TextAlignment.Centered, VerticalTextAlignment = VerticalTextAlignment.Middle, @@ -49,15 +86,16 @@ public override void Main () var label = new Label () { Text = "_App Events:", - X = 0, + X = Pos.Right (filterSlider), Y = Pos.Bottom (demo), }; + List appLogList = new (); var appLog = new ListView { X = Pos.Left (label), Y = Pos.Bottom (label), - Width = Dim.Percent(49), + Width = 50, Height = Dim.Fill (), ColorScheme = Colors.ColorSchemes ["TopLevel"], Source = new ListWrapper (appLogList) @@ -66,22 +104,26 @@ public override void Main () Application.MouseEvent += (sender, a) => { - ml.Text = $"MouseEvent: ({a.MouseEvent.X},{a.MouseEvent.Y}) - {a.MouseEvent.Flags} {count}"; - appLogList.Add ($"({a.MouseEvent.X},{a.MouseEvent.Y}) - {a.MouseEvent.Flags} {count++}"); - appLog.MoveDown (); + var i = filterSlider.Options.FindIndex (o => o.Data == a.MouseEvent.Flags); + if (filterSlider.GetSetOptions().Contains(i)) + { + ml.Text = $"MouseEvent: ({a.MouseEvent.X},{a.MouseEvent.Y}) - {a.MouseEvent.Flags} {count}"; + appLogList.Add ($"({a.MouseEvent.X},{a.MouseEvent.Y}) - {a.MouseEvent.Flags} {count++}"); + appLog.MoveDown (); + } }; label = new Label () { Text = "_Window Events:", - X = Pos.Percent(50), - Y = Pos.Bottom (demo), + X = Pos.Right (appLog)+1, + Y = Pos.Top (label), }; List winLogList = new (); var winLog = new ListView { - X = Pos.Left(label), + X = Pos.Left (label), Y = Pos.Bottom (label), Width = Dim.Percent (50), Height = Dim.Fill (), @@ -89,6 +131,13 @@ public override void Main () Source = new ListWrapper (winLogList) }; win.Add (label, winLog); + + clearButton.Accept += (s, e) => + { + appLogList.Clear (); + winLogList.Clear (); + }; + win.MouseEvent += (sender, a) => { winLogList.Add ($"MouseEvent: ({a.MouseEvent.X},{a.MouseEvent.Y}) - {a.MouseEvent.Flags} {count++}"); From c5b7b084a91fba1c65edab082e3d976aad71f56b Mon Sep 17 00:00:00 2001 From: Tig Date: Thu, 4 Apr 2024 18:50:13 -0400 Subject: [PATCH 24/32] Way too big a committ.... but I got carried away. - Started MouseEventEventArgs -> MouseEvent transition - for OnMouseEvent. Partially fixes #3029. - Refactored Appliation.OnMouseEvent and View.OnMouseEvent to match design guidelines. - Re-impleented highlight, enabling extensibility (see Border). - Beefed up unit tests --- Terminal.Gui/Application.cs | 50 +-- Terminal.Gui/ConsoleDrivers/ConsoleDriver.cs | 4 +- .../CursesDriver/CursesDriver.cs | 2 +- Terminal.Gui/ConsoleDrivers/NetDriver.cs | 2 +- Terminal.Gui/ConsoleDrivers/WindowsDriver.cs | 20 +- Terminal.Gui/View/Adornment/Border.cs | 22 ++ Terminal.Gui/View/ViewAdornments.cs | 5 +- Terminal.Gui/View/ViewMouse.cs | 272 ++++++++++++---- Terminal.Gui/Views/ComboBox.cs | 4 +- Terminal.Gui/Views/Menu/Menu.cs | 32 +- Terminal.Gui/Views/Menu/MenuBar.cs | 8 +- Terminal.Gui/Views/ScrollBarView.cs | 4 +- Terminal.Gui/Views/ScrollView.cs | 4 +- Terminal.Gui/Views/TabView.cs | 2 +- UICatalog/Scenarios/ASCIICustomButton.cs | 2 +- UICatalog/Scenarios/Adornments.cs | 2 +- UICatalog/Scenarios/BasicColors.cs | 6 +- UICatalog/Scenarios/ContextMenus.cs | 2 +- UICatalog/Scenarios/Mouse.cs | 38 ++- UICatalog/Scenarios/Scrolling.cs | 2 +- UICatalog/Scenarios/TrueColors.cs | 4 +- UnitTests/Application/ApplicationTests.cs | 82 ++--- UnitTests/Application/MouseTests.cs | 55 +--- UnitTests/Input/EscSeqUtilsTests.cs | 12 +- UnitTests/Input/ResponderTests.cs | 2 +- UnitTests/View/MouseTests.cs | 227 ++++++++++--- UnitTests/View/NavigationTests.cs | 8 +- UnitTests/View/ViewTests.cs | 2 +- UnitTests/Views/CheckBoxTests.cs | 6 +- UnitTests/Views/ColorPickerTests.cs | 4 +- UnitTests/Views/ComboBoxTests.cs | 54 ++-- UnitTests/Views/ContextMenuTests.cs | 70 ++-- UnitTests/Views/LabelTests.cs | 2 +- UnitTests/Views/ListViewTests.cs | 25 +- UnitTests/Views/MenuBarTests.cs | 102 +++--- UnitTests/Views/OverlappedTests.cs | 24 +- UnitTests/Views/ScrollBarViewTests.cs | 12 +- UnitTests/Views/TabViewTests.cs | 38 +-- UnitTests/Views/TextFieldTests.cs | 10 +- UnitTests/Views/ToplevelTests.cs | 302 ++++++------------ UnitTests/Views/TreeTableSourceTests.cs | 8 +- 41 files changed, 805 insertions(+), 727 deletions(-) diff --git a/Terminal.Gui/Application.cs b/Terminal.Gui/Application.cs index 53cd14af6a..b8cbb7f1f7 100644 --- a/Terminal.Gui/Application.cs +++ b/Terminal.Gui/Application.cs @@ -318,7 +318,7 @@ internal static void InternalInit ( private static void Driver_SizeChanged (object sender, SizeChangedEventArgs e) { OnSizeChanging (e); } private static void Driver_KeyDown (object sender, Key e) { OnKeyDown (e); } private static void Driver_KeyUp (object sender, Key e) { OnKeyUp (e); } - private static void Driver_MouseEvent (object sender, MouseEventEventArgs e) { OnMouseEvent (e); } + private static void Driver_MouseEvent (object sender, MouseEvent e) { OnMouseEvent (e); } /// Gets of list of types that are available. /// @@ -1441,12 +1441,12 @@ private static void OnUnGrabbedMouse (View view) /// /// The will contain the that contains the mouse coordinates. /// - public static event EventHandler MouseEvent; + public static event EventHandler MouseEvent; /// Called when a mouse event occurs. Raises the event. /// This method can be used to simulate a mouse event, e.g. in unit tests. /// The mouse event with coordinates relative to the screen. - internal static void OnMouseEvent (MouseEventEventArgs a) + internal static void OnMouseEvent (MouseEvent mouseEvent) { if (IsMouseDisabled) { @@ -1454,16 +1454,16 @@ internal static void OnMouseEvent (MouseEventEventArgs a) } // TODO: In PR #3273, FindDeepestView will return adornments. Update logic below to fix adornment mouse handling - var view = View.FindDeepestView (Current, a.MouseEvent.X, a.MouseEvent.Y); + var view = View.FindDeepestView (Current, mouseEvent.X, mouseEvent.Y); if (view is { }) { - a.MouseEvent.View = view; + mouseEvent.View = view; } - MouseEvent?.Invoke (null, new (a.MouseEvent)); + MouseEvent?.Invoke (null, mouseEvent); - if (a.MouseEvent.Handled) + if (mouseEvent.Handled) { return; } @@ -1472,25 +1472,25 @@ internal static void OnMouseEvent (MouseEventEventArgs a) { // If the mouse is grabbed, send the event to the view that grabbed it. // The coordinates are relative to the Bounds of the view that grabbed the mouse. - Point boundsLoc = MouseGrabView.ScreenToBounds (a.MouseEvent.X, a.MouseEvent.Y); + Point boundsLoc = MouseGrabView.ScreenToBounds (mouseEvent.X, mouseEvent.Y); var viewRelativeMouseEvent = new MouseEvent { X = boundsLoc.X, Y = boundsLoc.Y, - Flags = a.MouseEvent.Flags, - ScreenPosition = new (a.MouseEvent.X, a.MouseEvent.Y), + Flags = mouseEvent.Flags, + ScreenPosition = new (mouseEvent.X, mouseEvent.Y), View = MouseGrabView }; if (MouseGrabView.Bounds.Contains (viewRelativeMouseEvent.X, viewRelativeMouseEvent.Y) is false) { // The mouse has moved outside the bounds of the view that grabbed the mouse - _mouseEnteredView?.OnMouseLeave (a.MouseEvent); + _mouseEnteredView?.OnMouseLeave (mouseEvent); } //System.Diagnostics.Debug.WriteLine ($"{nme.Flags};{nme.X};{nme.Y};{mouseGrabView}"); - if (MouseGrabView?.OnMouseEvent (viewRelativeMouseEvent) == true) + if (MouseGrabView?.NewMouseEvent (viewRelativeMouseEvent) == true) { return; } @@ -1511,13 +1511,13 @@ internal static void OnMouseEvent (MouseEventEventArgs a) if ((view is null || view == OverlappedTop) && Current is { Modal: false } && OverlappedTop != null - && a.MouseEvent.Flags != MouseFlags.ReportMousePosition - && a.MouseEvent.Flags != 0) + && mouseEvent.Flags != MouseFlags.ReportMousePosition + && mouseEvent.Flags != 0) { // This occurs when there are multiple overlapped "tops" // E.g. "Mdi" - in the Background Worker Scenario - View? top = FindDeepestTop (Top, a.MouseEvent.X, a.MouseEvent.Y); - view = View.FindDeepestView (top, a.MouseEvent.X, a.MouseEvent.Y); + View? top = FindDeepestTop (Top, mouseEvent.X, mouseEvent.Y); + view = View.FindDeepestView (top, mouseEvent.X, mouseEvent.Y); if (view is { } && view != OverlappedTop && top != Current) { @@ -1535,27 +1535,27 @@ internal static void OnMouseEvent (MouseEventEventArgs a) if (view is Adornment adornment) { - Point frameLoc = adornment.ScreenToFrame (a.MouseEvent.X, a.MouseEvent.Y); + Point frameLoc = adornment.ScreenToFrame (mouseEvent.X, mouseEvent.Y); me = new () { X = frameLoc.X, Y = frameLoc.Y, - Flags = a.MouseEvent.Flags, - ScreenPosition = new (a.MouseEvent.X, a.MouseEvent.Y), + Flags = mouseEvent.Flags, + ScreenPosition = new (mouseEvent.X, mouseEvent.Y), View = view }; } - else if (view.BoundsToScreen (view.Bounds).Contains (a.MouseEvent.X, a.MouseEvent.Y)) + else if (view.BoundsToScreen (view.Bounds).Contains (mouseEvent.X, mouseEvent.Y)) { - Point boundsPoint = view.ScreenToBounds (a.MouseEvent.X, a.MouseEvent.Y); + Point boundsPoint = view.ScreenToBounds (mouseEvent.X, mouseEvent.Y); me = new () { X = boundsPoint.X, Y = boundsPoint.Y, - Flags = a.MouseEvent.Flags, - ScreenPosition = new (a.MouseEvent.X, a.MouseEvent.Y), + Flags = mouseEvent.Flags, + ScreenPosition = new (mouseEvent.X, mouseEvent.Y), View = view }; } @@ -1577,7 +1577,7 @@ internal static void OnMouseEvent (MouseEventEventArgs a) _mouseEnteredView = view; } - if (!view.WantMousePositionReports && a.MouseEvent.Flags == MouseFlags.ReportMousePosition) + if (!view.WantMousePositionReports && mouseEvent.Flags == MouseFlags.ReportMousePosition) { return; } @@ -1586,7 +1586,7 @@ internal static void OnMouseEvent (MouseEventEventArgs a) //Debug.WriteLine ($"OnMouseEvent: ({a.MouseEvent.X},{a.MouseEvent.Y}) - {a.MouseEvent.Flags}"); - if (view.OnMouseEvent (me)) + if (view.NewMouseEvent (me) == false) { // Should we bubble up the event, if it is not handled? //return; diff --git a/Terminal.Gui/ConsoleDrivers/ConsoleDriver.cs b/Terminal.Gui/ConsoleDrivers/ConsoleDriver.cs index 2a80f34738..1974b6147e 100644 --- a/Terminal.Gui/ConsoleDrivers/ConsoleDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/ConsoleDriver.cs @@ -538,11 +538,11 @@ public virtual Attribute MakeColor (in Color foreground, in Color background) public void OnKeyUp (Key a) { KeyUp?.Invoke (this, a); } /// Event fired when a mouse event occurs. - public event EventHandler MouseEvent; + public event EventHandler MouseEvent; /// Called when a mouse event occurs. Fires the event. /// - public void OnMouseEvent (MouseEventEventArgs a) { MouseEvent?.Invoke (this, a); } + public void OnMouseEvent (MouseEvent a) { MouseEvent?.Invoke (this, a); } /// Simulates a key press. /// The key character. diff --git a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs index 08457cc836..d372c52d43 100644 --- a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs @@ -812,7 +812,7 @@ bool IsButtonClickedOrDoubleClicked (MouseFlags flag) var me = new MouseEvent { Flags = mouseFlag, X = pos.X, Y = pos.Y }; Debug.WriteLine ($"CursesDriver: ({me.X},{me.Y}) - {me.Flags}"); - OnMouseEvent (new MouseEventEventArgs (me)); + OnMouseEvent (me); } #region Color Handling diff --git a/Terminal.Gui/ConsoleDrivers/NetDriver.cs b/Terminal.Gui/ConsoleDrivers/NetDriver.cs index 0f4188be46..4a85804f28 100644 --- a/Terminal.Gui/ConsoleDrivers/NetDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/NetDriver.cs @@ -1138,7 +1138,7 @@ private void ProcessInput (InputResult inputEvent) case EventType.Mouse: MouseEvent me = ToDriverMouse (inputEvent.MouseEvent); Debug.WriteLine ($"NetDriver: ({me.X},{me.Y}) - {me.Flags}"); - OnMouseEvent (new MouseEventEventArgs (me)); + OnMouseEvent (me); break; case EventType.WindowSize: diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs index ac5dd75ffd..e02234aa3c 100644 --- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs +++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs @@ -1396,18 +1396,16 @@ internal void ProcessInput (WindowsConsole.InputRecord inputEvent) break; } - OnMouseEvent (new MouseEventEventArgs (me)); + OnMouseEvent (me); if (_processButtonClick) { - OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent - { - X = me.X, - Y = me.Y, - Flags = ProcessButtonClick (inputEvent.MouseEvent) - })); + OnMouseEvent (new () + { + X = me.X, + Y = me.Y, + Flags = ProcessButtonClick (inputEvent.MouseEvent) + }); } break; @@ -1715,7 +1713,7 @@ private async Task ProcessContinuousButtonPressedAsync (MouseFlags mouseFlag) { // When a user presses-and-holds, start generating pressed events every `startDelay` // After `iterationsUntilFast` iterations, speed them up to `fastDelay` ms - const int startDelay = 50; + const int startDelay = 500; const int iterationsUntilFast = 4; const int fastDelay = 50; @@ -1744,7 +1742,7 @@ private async Task ProcessContinuousButtonPressedAsync (MouseFlags mouseFlag) //Debug.WriteLine($"ProcessContinuousButtonPressedAsync: {view}"); if (_isButtonPressed && (mouseFlag & MouseFlags.ReportMousePosition) == 0) { - Application.Invoke (() => OnMouseEvent (new MouseEventEventArgs (me))); + Application.Invoke (() => OnMouseEvent (me)); } } } diff --git a/Terminal.Gui/View/Adornment/Border.cs b/Terminal.Gui/View/Adornment/Border.cs index 5cf8cd8080..8e32edde27 100644 --- a/Terminal.Gui/View/Adornment/Border.cs +++ b/Terminal.Gui/View/Adornment/Border.cs @@ -56,6 +56,9 @@ public Border (View parent) : base (parent) Parent = parent; Application.GrabbingMouse += Application_GrabbingMouse; Application.UnGrabbingMouse += Application_UnGrabbingMouse; + + EnablingHighlight += Border_EnablingHighlight; + DisablingHighlight += Border_DisablingHighlight; } #if SUBVIEW_BASED_BORDER @@ -187,6 +190,23 @@ public LineStyle LineStyle #region Mouse Support + private LineStyle _savedHighlightLineStyle; + + private void Border_EnablingHighlight (object sender, System.ComponentModel.CancelEventArgs e) + { + _savedHighlightLineStyle = Parent?.BorderStyle ?? LineStyle; + LineStyle = LineStyle.Heavy; + Parent?.SetNeedsDisplay (); + e.Cancel = true; + } + + private void Border_DisablingHighlight (object sender, System.ComponentModel.CancelEventArgs e) + { + LineStyle = _savedHighlightLineStyle; + Parent?.SetNeedsDisplay (); + e.Cancel = true; + } + private Point? _dragPosition; private Point _startGrabPoint; @@ -222,6 +242,7 @@ protected internal override bool OnMouseEvent (MouseEvent mouseEvent) _startGrabPoint = new (mouseEvent.X + Frame.X, mouseEvent.Y + Frame.Y); _dragPosition = new (mouseEvent.X, mouseEvent.Y); Application.GrabMouse (this); + EnableHighlight (); } return true; @@ -265,6 +286,7 @@ out _ { _dragPosition = null; Application.UngrabMouse (); + DisableHighlight(); return true; } diff --git a/Terminal.Gui/View/ViewAdornments.cs b/Terminal.Gui/View/ViewAdornments.cs index 5cf0364394..55445cef82 100644 --- a/Terminal.Gui/View/ViewAdornments.cs +++ b/Terminal.Gui/View/ViewAdornments.cs @@ -99,7 +99,10 @@ public LineStyle BorderStyle if (value != LineStyle.None) { - Border.Thickness = new (1); + if (Border.Thickness == Thickness.Empty) + { + Border.Thickness = new (1); + } } else { diff --git a/Terminal.Gui/View/ViewMouse.cs b/Terminal.Gui/View/ViewMouse.cs index 689168e505..9f3dac4f28 100644 --- a/Terminal.Gui/View/ViewMouse.cs +++ b/Terminal.Gui/View/ViewMouse.cs @@ -1,4 +1,7 @@ -namespace Terminal.Gui; +using System.ComponentModel; +using System.Diagnostics; + +namespace Terminal.Gui; public partial class View { @@ -77,18 +80,31 @@ protected internal virtual bool OnMouseLeave (MouseEvent mouseEvent) /// Event fired when the mouse leaves the View's . public event EventHandler MouseLeave; - [CanBeNull] - private ColorScheme _savedColorScheme; - - /// Called when a mouse event occurs within the view's . + /// + /// Processes a . This method is called by when a mouse + /// event occurs. + /// /// /// - /// The coordinates are relative to . + /// A view must be both enabled and visible to receive mouse events. + /// + /// + /// This method calls to process the event. If the event is not handled, and one of the + /// mouse buttons was clicked, it calls to process the click. + /// + /// + /// If is , the view will be highlighted when the mouse is + /// pressed. + /// See and for more information. + /// + /// + /// If is , the event + /// will be invoked repeatedly while the button is pressed. /// /// /// - /// , if the event was handled, otherwise. - protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) + /// if the event was handled, otherwise. + public bool? NewMouseEvent (MouseEvent mouseEvent) { if (!Enabled) { @@ -101,23 +117,67 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) return false; } - var args = new MouseEventEventArgs (mouseEvent); + if (OnMouseEvent (mouseEvent)) + { + // Technically mouseEvent.Handled should already be true if implementers of OnMouseEvent + // follow the rules. But we'll update it just in case. + return mouseEvent.Handled = true; + } + + if ((HighlightOnPress || WantContinuousButtonPressed) && Highlight (mouseEvent)) + { + Debug.Assert (mouseEvent.Handled); + + return mouseEvent.Handled; + } + + if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked) + || mouseEvent.Flags.HasFlag (MouseFlags.Button2Clicked) + || mouseEvent.Flags.HasFlag (MouseFlags.Button3Clicked) + || mouseEvent.Flags.HasFlag (MouseFlags.Button4Clicked)) + { + return OnMouseClick (new (mouseEvent)); + } - // Default behavior is to invoke Accept (via HotKey) on clicked. - if ( - // !WantContinuousButtonPressed && - Application.MouseGrabView != this + return false; + } + + /// + /// Highlight the view when the mouse is pressed. + /// + /// + /// + /// Set to to have the view highlighted when the mouse is + /// pressed. + /// + /// + /// Calls which fires the event. + /// + /// + /// Calls which fires the event. + /// + /// + /// + /// , if the event was handled, otherwise. + private bool Highlight (MouseEvent mouseEvent) + { + if (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 (!HighlightOnPress) { - return false; + // We're grabbed. Clicked event comes after the last Release. This is our signal to ungrab + Application.UngrabMouse (); + DisableHighlight (); + + // If mouse is still in bounds, click + if (!WantContinuousButtonPressed && Bounds.Contains (mouseEvent.X, mouseEvent.Y)) + { + return OnMouseClick (new (mouseEvent)); + } + + return mouseEvent.Handled = true; } if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed) @@ -125,47 +185,34 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) || mouseEvent.Flags.HasFlag (MouseFlags.Button3Pressed) || mouseEvent.Flags.HasFlag (MouseFlags.Button4Pressed)) { - // 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 + // The first time we get pressed event, grab the mouse and set focus if (Application.MouseGrabView != this) { Application.GrabMouse (this); - if (HighlightOnPress && ColorScheme is { }) - { - _savedColorScheme = ColorScheme; - if (CanFocus) - { - // TODO: Make the inverted color configurable - var cs = new ColorScheme (ColorScheme) - { - Focus = new (ColorScheme.Normal.Foreground, ColorScheme.Focus.Background) - }; - ColorScheme = cs; - } - else - { - var cs = new ColorScheme (ColorScheme) - { - Normal = new (ColorScheme.Focus.Background, ColorScheme.Normal.Foreground) - }; - ColorScheme = cs; - } - } - if (CanFocus) { // Set the focus, but don't invoke Accept SetFocus (); } } - args.Handled = true; + + if (Bounds.Contains (mouseEvent.X, mouseEvent.Y)) + { + EnableHighlight (); + } + else + { + DisableHighlight (); + } + + if (WantContinuousButtonPressed && Application.MouseGrabView == this) + { + // If this is not the first pressed event, click + return OnMouseClick (new (mouseEvent)); + } + + return mouseEvent.Handled = true; } if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Released) @@ -173,30 +220,127 @@ protected internal virtual bool OnMouseEvent (MouseEvent mouseEvent) || mouseEvent.Flags.HasFlag (MouseFlags.Button3Released) || mouseEvent.Flags.HasFlag (MouseFlags.Button4Released)) { - if (Application.MouseGrabView == this) { - // When the mouse is released, if WantContinuousButtonPressed is set, invoke Accept one last time. - //if (WantContinuousButtonPressed) - { - OnMouseClick (args); - } + DisableHighlight (); + } - Application.UngrabMouse (); + return mouseEvent.Handled = true; + } + + return mouseEvent.Handled; + } + + [CanBeNull] + private ColorScheme _savedHighlightColorScheme; + + /// + /// Enables the highlight for the view. Called from OnMouseEvent. + /// + public void EnableHighlight () + { + if (OnEnablingHighlight () == true) + { + return; + } + + if (_savedHighlightColorScheme is null && ColorScheme is { }) + { + _savedHighlightColorScheme ??= ColorScheme; - if (HighlightOnPress && _savedColorScheme is { }) + if (CanFocus) + { + // TODO: Make the inverted color configurable + var cs = new ColorScheme (ColorScheme) { - ColorScheme = _savedColorScheme; - _savedColorScheme = null; - } + // For Buttons etc... + Focus = new (ColorScheme.Normal.Foreground, ColorScheme.Focus.Background), + + // For Adornments + Normal = new (ColorScheme.Focus.Foreground, ColorScheme.Normal.Background) + }; + ColorScheme = cs; + } + else + { + var cs = new ColorScheme (ColorScheme) + { + // For Buttons etc... that can't focus (like up/down). + Normal = new (ColorScheme.Focus.Background, ColorScheme.Normal.Foreground) + }; + ColorScheme = cs; } - args.Handled = true; } + } + + /// + /// Fired when the view is highlighted. Set to + /// to implement a custom highlight scheme or prevent the view from being highlighted. + /// + public event EventHandler EnablingHighlight; + + /// + /// Called when the view is to be highlighted. + /// + /// , if the event was handled, otherwise. + protected virtual bool? OnEnablingHighlight () + { + CancelEventArgs args = new (); + EnablingHighlight?.Invoke (this, args); - if (args.Handled != true) + return args.Cancel; + } + + /// + /// Disables the highlight for the view. Called from OnMouseEvent. + /// + public void DisableHighlight () + { + if (OnDisablingHighlight () == true) + { + return; + } + + // Unhighlight + if (_savedHighlightColorScheme is { }) { - MouseEvent?.Invoke (this, args); + ColorScheme = _savedHighlightColorScheme; + _savedHighlightColorScheme = null; } + } + + /// + /// Fired when the view is no longer to be highlighted. Set to + /// + /// to implement a custom highlight scheme or prevent the view from being highlighted. + /// + public event EventHandler DisablingHighlight; + + /// + /// Called when the view is no longer to be highlighted. + /// + /// , if the event was handled, otherwise. + protected virtual bool? OnDisablingHighlight () + { + CancelEventArgs args = new (); + DisablingHighlight?.Invoke (this, args); + + return args.Cancel; + } + + /// 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) + { + var args = new MouseEventEventArgs (mouseEvent); + + MouseEvent?.Invoke (this, args); return args.Handled; } diff --git a/Terminal.Gui/Views/ComboBox.cs b/Terminal.Gui/Views/ComboBox.cs index 9d151f465f..b3c719b5ef 100644 --- a/Terminal.Gui/Views/ComboBox.cs +++ b/Terminal.Gui/Views/ComboBox.cs @@ -264,7 +264,7 @@ protected internal override bool OnMouseEvent (MouseEvent me) FocusSelectedItem (); } - return true; + return me.Handled = true; } if (me.Flags == MouseFlags.Button1Pressed) @@ -274,7 +274,7 @@ protected internal override bool OnMouseEvent (MouseEvent me) _search.SetFocus (); } - return true; + return me.Handled = true; } return false; diff --git a/Terminal.Gui/Views/Menu/Menu.cs b/Terminal.Gui/Views/Menu/Menu.cs index d02791836d..60f7c00bf3 100644 --- a/Terminal.Gui/Views/Menu/Menu.cs +++ b/Terminal.Gui/Views/Menu/Menu.cs @@ -712,9 +712,9 @@ public override void OnVisibleChanged () } } - private void Application_RootMouseEvent (object sender, MouseEventEventArgs a) + private void Application_RootMouseEvent (object sender, MouseEvent a) { - if (a.MouseEvent.View is { } and (MenuBar or not Menu)) + if (a.View is { } and (MenuBar or not Menu)) { return; } @@ -724,21 +724,21 @@ private void Application_RootMouseEvent (object sender, MouseEventEventArgs a) throw new InvalidOperationException ("This shouldn't running on a invisible menu!"); } - View view = a.MouseEvent.View ?? this; + View view = a.View ?? this; - Point boundsPoint = view.ScreenToBounds (a.MouseEvent.X, a.MouseEvent.Y); + Point boundsPoint = view.ScreenToBounds (a.X, a.Y); var me = new MouseEvent { X = boundsPoint.X, Y = boundsPoint.Y, - Flags = a.MouseEvent.Flags, - ScreenPosition = new (a.MouseEvent.X, a.MouseEvent.Y), + Flags = a.Flags, + ScreenPosition = new (a.X, a.Y), View = view }; - if (view.OnMouseEvent (me) || a.MouseEvent.Flags == MouseFlags.Button1Pressed || a.MouseEvent.Flags == MouseFlags.Button1Released) + if (view.NewMouseEvent (me) == true || a.Flags == MouseFlags.Button1Pressed || a.Flags == MouseFlags.Button1Released) { - a.MouseEvent.Handled = true; + a.Handled = true; } } @@ -1189,12 +1189,12 @@ protected internal override bool OnMouseEvent (MouseEvent me) if (me.Y < 0) { - return true; + return me.Handled = true; } if (me.Y >= _barItems.Children.Length) { - return true; + return me.Handled = true; } MenuItem item = _barItems.Children [me.Y]; @@ -1206,13 +1206,13 @@ protected internal override bool OnMouseEvent (MouseEvent me) if (disabled) { - return true; + return me.Handled = true; } _currentChild = me.Y; RunSelected (); - return true; + return me.Handled = true; } if (me.Flags != MouseFlags.Button1Pressed @@ -1229,14 +1229,14 @@ protected internal override bool OnMouseEvent (MouseEvent me) if (me.Y < 0 || me.Y >= _barItems.Children.Length) { - return true; + return me.Handled = true; } MenuItem item = _barItems.Children [me.Y]; if (item is null) { - return true; + return me.Handled = true; } if (item?.IsEnabled () != true) @@ -1254,12 +1254,12 @@ protected internal override bool OnMouseEvent (MouseEvent me) SetNeedsDisplay (); SetParentSetNeedsDisplay (); - return true; + return me.Handled = true; } _host.OnMenuOpened (); - return true; + return me.Handled = true; } } diff --git a/Terminal.Gui/Views/Menu/MenuBar.cs b/Terminal.Gui/Views/Menu/MenuBar.cs index e1c8189ace..07ff6912c3 100644 --- a/Terminal.Gui/Views/Menu/MenuBar.cs +++ b/Terminal.Gui/Views/Menu/MenuBar.cs @@ -1715,7 +1715,7 @@ protected internal override bool OnMouseEvent (MouseEvent me) { if (!CloseMenu (true, false)) { - return true; + return me.Handled = true; } Activate (i); @@ -1733,7 +1733,7 @@ protected internal override bool OnMouseEvent (MouseEvent me) } } - return true; + return me.Handled = true; } if (i == Menus.Length - 1 && me.Flags == MouseFlags.Button1Clicked) @@ -1742,7 +1742,7 @@ protected internal override bool OnMouseEvent (MouseEvent me) { CloseAllMenus (); - return true; + return me.Handled = true; } } @@ -1804,7 +1804,7 @@ internal bool HandleGrabView (MouseEvent me, View current) nme = new () { X = me.X + current.Frame.X, Y = 0, Flags = me.Flags, View = v }; } - v.OnMouseEvent (nme); + v.NewMouseEvent (nme); return false; } diff --git a/Terminal.Gui/Views/ScrollBarView.cs b/Terminal.Gui/Views/ScrollBarView.cs index 92fcbd505b..e70f1e5c73 100644 --- a/Terminal.Gui/Views/ScrollBarView.cs +++ b/Terminal.Gui/Views/ScrollBarView.cs @@ -325,7 +325,7 @@ protected internal override bool OnMouseEvent (MouseEvent mouseEvent) || mouseEvent.Flags == MouseFlags.WheeledRight || mouseEvent.Flags == MouseFlags.WheeledLeft)) { - return Host.OnMouseEvent (mouseEvent); + return Host.NewMouseEvent (mouseEvent) == true; } if (mouseEvent.Flags == MouseFlags.Button1Pressed && location == 0) @@ -800,7 +800,7 @@ private void ContentBottomRightCorner_MouseClick (object sender, MouseEventEvent || me.MouseEvent.Flags == MouseFlags.WheeledRight || me.MouseEvent.Flags == MouseFlags.WheeledLeft) { - OnMouseEvent (me.MouseEvent); + NewMouseEvent (me.MouseEvent); } else if (me.MouseEvent.Flags == MouseFlags.Button1Clicked) { diff --git a/Terminal.Gui/Views/ScrollView.cs b/Terminal.Gui/Views/ScrollView.cs index 72ebcb3552..f021932ab9 100644 --- a/Terminal.Gui/Views/ScrollView.cs +++ b/Terminal.Gui/Views/ScrollView.cs @@ -434,11 +434,11 @@ protected internal override bool OnMouseEvent (MouseEvent me) } else if (me.X == _vertical.Frame.X && ShowVerticalScrollIndicator) { - _vertical.OnMouseEvent (me); + _vertical.NewMouseEvent (me); } else if (me.Y == _horizontal.Frame.Y && ShowHorizontalScrollIndicator) { - _horizontal.OnMouseEvent (me); + _horizontal.NewMouseEvent (me); } else if (IsOverridden (me.View, "OnMouseEvent")) { diff --git a/Terminal.Gui/Views/TabView.cs b/Terminal.Gui/Views/TabView.cs index 88689e2c5e..8c7638a1da 100644 --- a/Terminal.Gui/Views/TabView.cs +++ b/Terminal.Gui/Views/TabView.cs @@ -533,7 +533,7 @@ private int GetTabHeight (bool top) return Style.ShowTopLine ? 3 : 2; } - private void Tab_MouseClick (object sender, MouseEventEventArgs e) { e.Handled = _tabsBar.OnMouseEvent (e.MouseEvent); } + private void Tab_MouseClick (object sender, MouseEventEventArgs e) { e.Handled = _tabsBar.NewMouseEvent (e.MouseEvent) == true; } private void UnSetCurrentTabs () { diff --git a/UICatalog/Scenarios/ASCIICustomButton.cs b/UICatalog/Scenarios/ASCIICustomButton.cs index 729db92657..8051e08ea6 100644 --- a/UICatalog/Scenarios/ASCIICustomButton.cs +++ b/UICatalog/Scenarios/ASCIICustomButton.cs @@ -134,7 +134,7 @@ public override bool OnLeave (View view) } public event Action PointerEnter; - private void This_MouseClick (object sender, MouseEventEventArgs obj) { OnMouseEvent (obj.MouseEvent); } + private void This_MouseClick (object sender, MouseEventEventArgs obj) { NewMouseEvent (obj.MouseEvent); } } public class ScrollViewTestWindow : Window diff --git a/UICatalog/Scenarios/Adornments.cs b/UICatalog/Scenarios/Adornments.cs index 91c40f5a41..302eda6236 100644 --- a/UICatalog/Scenarios/Adornments.cs +++ b/UICatalog/Scenarios/Adornments.cs @@ -85,7 +85,7 @@ public override void Init () view.X = 36; view.Y = 0; view.Width = Dim.Percent (60); - view.Height = Dim.Percent (80); + view.Height = Dim.Percent (80); editor.Initialized += (s, e) => { editor.ViewToEdit = view; }; diff --git a/UICatalog/Scenarios/BasicColors.cs b/UICatalog/Scenarios/BasicColors.cs index faefc6441e..9fc6fead50 100644 --- a/UICatalog/Scenarios/BasicColors.cs +++ b/UICatalog/Scenarios/BasicColors.cs @@ -85,10 +85,10 @@ public override void Setup () Application.MouseEvent += (s, e) => { - if (e.MouseEvent.View != null) + if (e.View != null) { - Color fore = e.MouseEvent.View.GetNormalColor ().Foreground; - Color back = e.MouseEvent.View.GetNormalColor ().Background; + Color fore = e.View.GetNormalColor ().Foreground; + Color back = e.View.GetNormalColor ().Background; lblForeground.Text = $"#{fore.R:X2}{fore.G:X2}{fore.B:X2} {fore.GetClosestNamedColor ()} "; diff --git a/UICatalog/Scenarios/ContextMenus.cs b/UICatalog/Scenarios/ContextMenus.cs index 35ac50c640..f1bb6c90de 100644 --- a/UICatalog/Scenarios/ContextMenus.cs +++ b/UICatalog/Scenarios/ContextMenus.cs @@ -74,7 +74,7 @@ public override void Setup () Application.MouseEvent += ApplicationMouseEvent; - void ApplicationMouseEvent (object sender, MouseEventEventArgs a) { mousePos = new Point (a.MouseEvent.X, a.MouseEvent.Y); } + void ApplicationMouseEvent (object sender, MouseEvent a) { mousePos = new Point (a.X, a.Y); } Win.WantMousePositionReports = true; diff --git a/UICatalog/Scenarios/Mouse.cs b/UICatalog/Scenarios/Mouse.cs index 9e4096e4a2..7291ba92c8 100644 --- a/UICatalog/Scenarios/Mouse.cs +++ b/UICatalog/Scenarios/Mouse.cs @@ -58,10 +58,10 @@ public override void Main () win.Add (ml); - CheckBox cbWantContinuousPresses = new CheckBox () + CheckBox cbWantContinuousPresses = new () { X = Pos.Right (filterSlider), - Y = Pos.Bottom (ml) + 1, + Y = Pos.Bottom (ml), Title = "_Want Continuous Button Pressed", }; cbWantContinuousPresses.Toggled += (s, e) => @@ -70,11 +70,23 @@ public override void Main () }; win.Add (cbWantContinuousPresses); + CheckBox cbHighlightOnPress = new () + { + X = Pos.Right (filterSlider), + Y = Pos.Bottom (cbWantContinuousPresses), + Title = "_Highlight on Press", + }; + cbHighlightOnPress.Toggled += (s, e) => + { + win.HighlightOnPress = !win.HighlightOnPress; + }; + + win.Add (cbHighlightOnPress); var demo = new MouseDemo () { X = Pos.Right (filterSlider), - Y = Pos.Bottom (cbWantContinuousPresses) + 1, + Y = Pos.Bottom (cbHighlightOnPress), Width = 20, Height = 3, Text = "Enter/Leave Demo", @@ -105,17 +117,15 @@ public override void Main () Application.MouseEvent += (sender, a) => { - var i = filterSlider.Options.FindIndex (o => o.Data == a.MouseEvent.Flags); + var i = filterSlider.Options.FindIndex (o => o.Data == a.Flags); if (filterSlider.GetSetOptions().Contains(i)) { - ml.Text = $"MouseEvent: ({a.MouseEvent.X},{a.MouseEvent.Y}) - {a.MouseEvent.Flags} {count}"; - appLogList.Add ($"({a.MouseEvent.X},{a.MouseEvent.Y}) - {a.MouseEvent.Flags} {count++}"); + ml.Text = $"MouseEvent: ({a.X},{a.Y}) - {a.Flags} {count}"; + appLogList.Add ($"({a.X},{a.Y}) - {a.Flags} {count++}"); appLog.MoveDown (); - } + } }; - - label = new Label () { Text = "_Window Events:", @@ -137,13 +147,19 @@ public override void Main () clearButton.Accept += (s, e) => { appLogList.Clear (); + appLog.SetSource (appLogList); winLogList.Clear (); + winLog.SetSource(winLogList); }; win.MouseEvent += (sender, a) => { - winLogList.Add ($"MouseEvent: ({a.MouseEvent.X},{a.MouseEvent.Y}) - {a.MouseEvent.Flags} {count++}"); - winLog.MoveDown (); + var i = filterSlider.Options.FindIndex (o => o.Data == a.MouseEvent.Flags); + if (filterSlider.GetSetOptions ().Contains (i)) + { + winLogList.Add ($"MouseEvent: ({a.MouseEvent.X},{a.MouseEvent.Y}) - {a.MouseEvent.Flags} {count++}"); + winLog.MoveDown (); + } }; win.MouseClick += (sender, a) => { diff --git a/UICatalog/Scenarios/Scrolling.cs b/UICatalog/Scenarios/Scrolling.cs index 33c15e8660..f9cf293769 100644 --- a/UICatalog/Scenarios/Scrolling.cs +++ b/UICatalog/Scenarios/Scrolling.cs @@ -251,7 +251,7 @@ void Top_Loaded (object sender, EventArgs args) Text = "Mouse: " }; Win.Add (mousePos); - Application.MouseEvent += (sender, a) => { mousePos.Text = $"Mouse: ({a.MouseEvent.X},{a.MouseEvent.Y}) - {a.MouseEvent.Flags} {count++}"; }; + Application.MouseEvent += (sender, a) => { mousePos.Text = $"Mouse: ({a.X},{a.Y}) - {a.Flags} {count++}"; }; var progress = new ProgressBar { X = Pos.Right (scrollView) + 1, Y = Pos.AnchorEnd (2), Width = 50 }; Win.Add (progress); diff --git a/UICatalog/Scenarios/TrueColors.cs b/UICatalog/Scenarios/TrueColors.cs index df86971062..7e89626173 100644 --- a/UICatalog/Scenarios/TrueColors.cs +++ b/UICatalog/Scenarios/TrueColors.cs @@ -76,9 +76,9 @@ public override void Setup () Application.MouseEvent += (s, e) => { - if (e.MouseEvent.View != null) + if (e.View != null) { - Attribute normal = e.MouseEvent.View.GetNormalColor (); + Attribute normal = e.View.GetNormalColor (); lblRed.Text = normal.Foreground.R.ToString (); lblGreen.Text = normal.Foreground.G.ToString (); lblBlue.Text = normal.Foreground.B.ToString (); diff --git a/UnitTests/Application/ApplicationTests.cs b/UnitTests/Application/ApplicationTests.cs index 2dbad7cccf..9569c99b79 100644 --- a/UnitTests/Application/ApplicationTests.cs +++ b/UnitTests/Application/ApplicationTests.cs @@ -41,9 +41,9 @@ public void Begin_Sets_Application_Top_To_Console_Size () { Assert.Null (Application.Top); Application.Begin (new ()); - Assert.Equal (new Rectangle (0, 0, 80, 25), Application.Top.Frame); + Assert.Equal (new (0, 0, 80, 25), Application.Top.Frame); ((FakeDriver)Application.Driver).SetBufferSize (5, 5); - Assert.Equal (new Rectangle (0, 0, 5, 5), Application.Top.Frame); + Assert.Equal (new (0, 0, 5, 5), Application.Top.Frame); } [Fact] @@ -62,10 +62,10 @@ public void End_And_Shutdown_Should_Not_Dispose_ApplicationTop () Assert.Null (rs.Toplevel); - var top = Application.Top; + Toplevel top = Application.Top; #if DEBUG_IDISPOSABLE - var exception = Record.Exception (() => Shutdown ()); + Exception exception = Record.Exception (() => Shutdown ()); Assert.NotNull (exception); Assert.False (top.WasDisposed); top.Dispose (); @@ -130,7 +130,7 @@ public void Init_DriverName_Should_Pick_Correct_Driver (Type driverType) var driver = (ConsoleDriver)Activator.CreateInstance (driverType); Application.Init (driverName: driverType.Name); Assert.NotNull (Application.Driver); - Assert.NotEqual(driver, Application.Driver); + Assert.NotEqual (driver, Application.Driver); Assert.Equal (driverType, Application.Driver.GetType ()); Shutdown (); } @@ -212,7 +212,7 @@ void CheckReset () Application._mainThreadId = 1; //Application._topLevels = new List (); - Application._mouseEnteredView = new View (); + Application._mouseEnteredView = new (); //Application.SupportedCultures = new List (); Application.Force16Colors = true; @@ -225,7 +225,7 @@ void CheckReset () //Application.OverlappedChildren = new List (); //Application.OverlappedTop = - Application._mouseEnteredView = new View (); + Application._mouseEnteredView = new (); //Application.WantContinuousButtonPressedView = new View (); @@ -464,6 +464,7 @@ public void SetCurrentAsTop_Run_A_Not_Modal_Toplevel_Make_It_The_Current_Applica Application.Run (t1); Assert.Equal (t1, Application.Top); + // top wasn't run and so never was added to toplevel's stack Assert.NotEqual (top, Application.Top); #if DEBUG_IDISPOSABLE @@ -511,7 +512,6 @@ private class TestToplevel : Toplevel #region RunTests [Fact] - public void Run_T_After_InitWithDriver_with_TopLevel_Does_Not_Throws () { // Setup Mock driver @@ -533,7 +533,6 @@ public void Run_T_After_InitWithDriver_with_TopLevel_Does_Not_Throws () } [Fact] - public void Run_T_After_InitWithDriver_with_TopLevel_and_Driver_Does_Not_Throws () { // Setup Mock driver @@ -547,6 +546,7 @@ public void Run_T_After_InitWithDriver_with_TopLevel_and_Driver_Does_Not_Throws Assert.True (Application.Top is Window); Application.Top.Dispose (); + // Run when already initialized or not with a Driver will not throw (because Dialog is derived from Toplevel) Application.Run (null, new FakeDriver ()); Assert.True (Application.Top is Dialog); @@ -561,7 +561,6 @@ public void Run_T_After_InitWithDriver_with_TopLevel_and_Driver_Does_Not_Throws [Fact] [TestRespondersDisposed] - public void Run_T_After_Init_Does_Not_Disposes_Application_Top () { Init (); @@ -572,7 +571,7 @@ public void Run_T_After_Init_Does_Not_Disposes_Application_Top () Application.Iteration += (s, a) => { - Assert.NotEqual(initTop, Application.Top); + Assert.NotEqual (initTop, Application.Top); #if DEBUG_IDISPOSABLE Assert.False (initTop.WasDisposed); #endif @@ -596,7 +595,6 @@ public void Run_T_After_Init_Does_Not_Disposes_Application_Top () [Fact] [TestRespondersDisposed] - public void Run_T_After_InitWithDriver_with_TestTopLevel_DoesNotThrow () { // Setup Mock driver @@ -617,7 +615,6 @@ public void Run_T_After_InitWithDriver_with_TestTopLevel_DoesNotThrow () [Fact] [TestRespondersDisposed] - public void Run_T_After_InitNullDriver_with_TestTopLevel_DoesNotThrow () { Application.ForceDriver = "FakeDriver"; @@ -640,7 +637,6 @@ public void Run_T_After_InitNullDriver_with_TestTopLevel_DoesNotThrow () [Fact] [TestRespondersDisposed] - public void Run_T_Init_Driver_Cleared_with_TestTopLevel_Throws () { Init (); @@ -678,7 +674,6 @@ public void Run_T_NoInit_DoesNotThrow () [Fact] [TestRespondersDisposed] - public void Run_T_NoInit_WithDriver_DoesNotThrow () { Application.Iteration += (s, a) => { Application.RequestStop (); }; @@ -696,7 +691,6 @@ public void Run_T_NoInit_WithDriver_DoesNotThrow () [Fact] [TestRespondersDisposed] - public void Run_RequestStop_Stops () { // Setup Mock driver @@ -721,7 +715,6 @@ public void Run_RequestStop_Stops () [Fact] [TestRespondersDisposed] - public void Run_RunningFalse_Stops () { // Setup Mock driver @@ -746,7 +739,6 @@ public void Run_RunningFalse_Stops () [Fact] [TestRespondersDisposed] - public void Run_Loaded_Ready_Unlodaded_Events () { Init (); @@ -782,18 +774,13 @@ public void Run_Toplevel_With_Modal_View_Does_Not_Refresh_If_Not_Dirty () if (iteration == 0) { // TODO: Don't use Dialog here as it has more layout logic. Use Window instead. - d = new Dialog (); + d = new (); d.DrawContent += (s, a) => count++; Application.Run (d); } else if (iteration < 3) { - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent - { X = 0, Y = 0, Flags = MouseFlags.ReportMousePosition } - ) - ); + Application.OnMouseEvent (new () { X = 0, Y = 0, Flags = MouseFlags.ReportMousePosition }); Assert.False (top.NeedsDisplay); Assert.False (top.SubViewNeedsDisplay); Assert.False (top.LayoutNeeded); @@ -858,25 +845,11 @@ Colors.ColorSchemes ["Base"].Normal // TODO: In PR #2920 this breaks because the mouse is not grabbed anymore. // TODO: Move the mouse grap/drag mode from Toplevel to Border. - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Pressed } - ) - ); + Application.OnMouseEvent (new () { X = 0, Y = 0, Flags = MouseFlags.Button1Pressed }); Assert.Equal (w.Border, Application.MouseGrabView); // Move down and to the right. - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent - { - X = 1, - Y = 1, - Flags = MouseFlags.Button1Pressed - | MouseFlags.ReportMousePosition - } - ) - ); + Application.OnMouseEvent (new () { X = 1, Y = 1, Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition }); Application.Refresh (); TestHelpers.AssertDriverContentsWithFrameAre ( @@ -925,7 +898,7 @@ public void End_Does_Not_Dispose () Window w = new (); w.Ready += (s, e) => Application.RequestStop (); // Causes `End` to be called - Application.Run(w); + Application.Run (w); #if DEBUG_IDISPOSABLE Assert.False (w.WasDisposed); @@ -934,20 +907,23 @@ public void End_Does_Not_Dispose () Assert.NotNull (w); Assert.Equal (string.Empty, w.Title); // Valid - w has not been disposed. The user may want to run it again Assert.NotNull (Application.Top); - Assert.Equal(w, Application.Top); - Assert.NotEqual(top, Application.Top); + Assert.Equal (w, Application.Top); + Assert.NotEqual (top, Application.Top); Assert.Null (Application.Current); - Application.Run(w); // Valid - w has not been disposed. + Application.Run (w); // Valid - w has not been disposed. #if DEBUG_IDISPOSABLE Assert.False (w.WasDisposed); - var exception = Record.Exception (() => Application.Shutdown()); // Invalid - w has not been disposed. + Exception exception = Record.Exception (() => Application.Shutdown ()); // Invalid - w has not been disposed. Assert.NotNull (exception); w.Dispose (); Assert.True (w.WasDisposed); - exception = Record.Exception (() => Application.Run (w)); // Invalid - w has been disposed. Run it in debug mode will throw, otherwise the user may want to run it again + + exception = Record.Exception ( + () => Application.Run ( + w)); // Invalid - w has been disposed. Run it in debug mode will throw, otherwise the user may want to run it again Assert.NotNull (exception); exception = Record.Exception (() => Assert.Equal (string.Empty, w.Title)); // Invalid - w has been disposed and cannot be accessed @@ -974,11 +950,11 @@ public void Run_Creates_Top_Without_Init () Assert.NotNull (Application.Top); Application.RequestStop (); }; - var top = Application.Run (null, driver); + Toplevel top = Application.Run (null, driver); #if DEBUG_IDISPOSABLE - Assert.Equal(top, Application.Top); + Assert.Equal (top, Application.Top); Assert.False (top.WasDisposed); - var exception = Record.Exception (() => Application.Shutdown ()); + Exception exception = Record.Exception (() => Application.Shutdown ()); Assert.NotNull (exception); Assert.False (top.WasDisposed); #endif @@ -1010,9 +986,10 @@ public void Run_T_Creates_Top_Without_Init () Application.Run (null, driver); #if DEBUG_IDISPOSABLE Assert.False (Application.Top.WasDisposed); - var exception = Record.Exception (() => Application.Shutdown ()); + Exception exception = Record.Exception (() => Application.Shutdown ()); Assert.NotNull (exception); Assert.False (Application.Top.WasDisposed); + // It's up to caller to dispose it Application.Top.Dispose (); Assert.True (Application.Top.WasDisposed); @@ -1038,9 +1015,10 @@ public void Run_t_Creates_Top_Without_Init () Application.Run (new (), null, driver); #if DEBUG_IDISPOSABLE Assert.False (Application.Top.WasDisposed); - var exception = Record.Exception (() => Application.Shutdown ()); + Exception exception = Record.Exception (() => Application.Shutdown ()); Assert.NotNull (exception); Assert.False (Application.Top.WasDisposed); + // It's up to caller to dispose it Application.Top.Dispose (); Assert.True (Application.Top.WasDisposed); diff --git a/UnitTests/Application/MouseTests.cs b/UnitTests/Application/MouseTests.cs index d6b4cecca8..559cfbb9ef 100644 --- a/UnitTests/Application/MouseTests.cs +++ b/UnitTests/Application/MouseTests.cs @@ -42,19 +42,18 @@ bool expectedClicked ) { var mouseEvent = new MouseEvent { X = clickX, Y = clickY, Flags = MouseFlags.Button1Pressed }; - var mouseEventArgs = new MouseEventEventArgs (mouseEvent); var clicked = false; - void OnApplicationOnMouseEvent (object s, MouseEventEventArgs e) + void OnApplicationOnMouseEvent (object s, MouseEvent e) { - Assert.Equal (expectedX, e.MouseEvent.X); - Assert.Equal (expectedY, e.MouseEvent.Y); + Assert.Equal (expectedX, e.X); + Assert.Equal (expectedY, e.Y); clicked = true; } Application.MouseEvent += OnApplicationOnMouseEvent; - Application.OnMouseEvent (mouseEventArgs); + Application.OnMouseEvent (mouseEvent); Assert.Equal (expectedClicked, clicked); Application.MouseEvent -= OnApplicationOnMouseEvent; } @@ -107,7 +106,8 @@ bool expectedClicked Point pos = new (offset, offset); var clicked = false; - var view = new View () + + var view = new View { X = pos.X, Y = pos.Y, @@ -116,20 +116,19 @@ bool expectedClicked }; var mouseEvent = new MouseEvent { X = clickX, Y = clickY, Flags = MouseFlags.Button1Clicked }; - var mouseEventArgs = new MouseEventEventArgs (mouseEvent); view.MouseClick += (s, e) => - { - Assert.Equal (expectedX, e.MouseEvent.X); - Assert.Equal (expectedY, e.MouseEvent.Y); - clicked = true; - }; + { + Assert.Equal (expectedX, e.MouseEvent.X); + Assert.Equal (expectedY, e.MouseEvent.Y); + clicked = true; + }; var top = new Toplevel (); top.Add (view); Application.Begin (top); - Application.OnMouseEvent (mouseEventArgs); + Application.OnMouseEvent (mouseEvent); Assert.Equal (expectedClicked, clicked); } @@ -215,7 +214,6 @@ bool expectedClicked top.Add (view); Application.Begin (top); var mouseEvent = new MouseEvent { X = clickX, Y = clickY, Flags = MouseFlags.Button1Clicked }; - var mouseEventArgs = new MouseEventEventArgs (mouseEvent); view.MouseClick += (s, e) => { @@ -224,7 +222,7 @@ bool expectedClicked clicked = true; }; - Application.OnMouseEvent (mouseEventArgs); + Application.OnMouseEvent (mouseEvent); Assert.Equal (expectedClicked, clicked); } @@ -254,12 +252,7 @@ public void MouseGrabView_WithNullMouseEventView () Assert.True (tf.HasFocus); Assert.Null (Application.MouseGrabView); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent - { X = 5, Y = 5, Flags = MouseFlags.ReportMousePosition } - ) - ); + Application.OnMouseEvent (new() { X = 5, Y = 5, Flags = MouseFlags.ReportMousePosition }); Assert.Equal (sv, Application.MouseGrabView); @@ -273,29 +266,15 @@ public void MouseGrabView_WithNullMouseEventView () // another toplevel (Dialog) was opened Assert.Null (Application.MouseGrabView); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent - { X = 5, Y = 5, Flags = MouseFlags.ReportMousePosition } - ) - ); + Application.OnMouseEvent (new() { X = 5, Y = 5, Flags = MouseFlags.ReportMousePosition }); Assert.Null (Application.MouseGrabView); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent - { X = 40, Y = 12, Flags = MouseFlags.ReportMousePosition } - ) - ); + Application.OnMouseEvent (new() { X = 40, Y = 12, Flags = MouseFlags.ReportMousePosition }); Assert.Null (Application.MouseGrabView); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Pressed } - ) - ); + Application.OnMouseEvent (new() { X = 0, Y = 0, Flags = MouseFlags.Button1Pressed }); Assert.Null (Application.MouseGrabView); diff --git a/UnitTests/Input/EscSeqUtilsTests.cs b/UnitTests/Input/EscSeqUtilsTests.cs index bf2c930e7b..b4486b84a9 100644 --- a/UnitTests/Input/EscSeqUtilsTests.cs +++ b/UnitTests/Input/EscSeqUtilsTests.cs @@ -699,11 +699,7 @@ public void DecodeEscSeq_Tests () top.Add (view); Application.Begin (top); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 0, Y = 0, Flags = 0 } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 0, Y = 0, Flags = 0 }); ClearAll (); @@ -760,11 +756,7 @@ public void DecodeEscSeq_Tests () // set Application.WantContinuousButtonPressedView to null view.WantContinuousButtonPressed = false; - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 0, Y = 0, Flags = 0 } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 0, Y = 0, Flags = 0 }); Application.RequestStop (); } diff --git a/UnitTests/Input/ResponderTests.cs b/UnitTests/Input/ResponderTests.cs index 7600a221e4..3a1d530766 100644 --- a/UnitTests/Input/ResponderTests.cs +++ b/UnitTests/Input/ResponderTests.cs @@ -234,7 +234,7 @@ public void New_Methods_Return_False () //Assert.False (r.OnKeyDown (new KeyEventArgs () { Key = Key.Unknown })); Assert.False (r.OnKeyDown (new Key { KeyCode = KeyCode.Null })); Assert.False (r.OnKeyUp (new Key { KeyCode = KeyCode.Null })); - Assert.False (r.OnMouseEvent (new MouseEvent { Flags = MouseFlags.AllEvents })); + Assert.False (r.NewMouseEvent (new MouseEvent { Flags = MouseFlags.AllEvents })); Assert.False (r.OnMouseEnter (new MouseEvent { Flags = MouseFlags.AllEvents })); Assert.False (r.OnMouseLeave (new MouseEvent { Flags = MouseFlags.AllEvents })); diff --git a/UnitTests/View/MouseTests.cs b/UnitTests/View/MouseTests.cs index bee5e35b53..5e6b7ef61d 100644 --- a/UnitTests/View/MouseTests.cs +++ b/UnitTests/View/MouseTests.cs @@ -27,7 +27,7 @@ public void MouseClick_SetsFocus_If_CanFocus (bool canFocus, bool setFocus, bool testView.SetFocus (); } - testView.OnMouseEvent (new () { X = 0, Y = 0, Flags = MouseFlags.Button1Clicked }); + testView.NewMouseEvent (new () { X = 0, Y = 0, Flags = MouseFlags.Button1Clicked }); Assert.True (superView.HasFocus); Assert.Equal (expectedHasFocus, testView.HasFocus); } @@ -73,9 +73,9 @@ public void ButtonPressed_In_Border_Starts_Drag (int marginThickness, int border Application.Begin (top); Assert.Equal (new Point (4, 4), testView.Frame.Location); - Application.OnMouseEvent (new (new () { X = xy, Y = xy, Flags = MouseFlags.Button1Pressed })); + Application.OnMouseEvent (new () { X = xy, Y = xy, Flags = MouseFlags.Button1Pressed }); - Application.OnMouseEvent (new (new () { X = xy + 1, Y = xy + 1, Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition })); + Application.OnMouseEvent (new () { X = xy + 1, Y = xy + 1, Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition }); Assert.Equal (expectedMoved, new Point (5, 5) == testView.Frame.Location); } @@ -89,7 +89,7 @@ public void WheeledLeft_WheeledRight (MouseFlags mouseFlags, MouseFlags expected var view = new View (); view.MouseEvent += (s, e) => mouseFlagsFromEvent = e.MouseEvent.Flags; - view.OnMouseEvent (new MouseEvent () { Flags = mouseFlags }); + view.NewMouseEvent (new MouseEvent () { Flags = mouseFlags }); Assert.Equal (mouseFlagsFromEvent, expectedMouseFlagsFromEvent); } @@ -280,9 +280,32 @@ public void AllViews_Enter_Leave_Events_Visible_False (View view, string viewNam Application.Shutdown (); } + [Fact] + public void NewMouseEvent_Invokes_MouseEvent_Properly () + { + View view = new () + { + Width = 1, + Height = 1, + }; + bool mouseEventInvoked = false; + view.MouseEvent += (s, e) => + { + mouseEventInvoked = true; + e.Handled = true; + }; + + MouseEvent me = new (); + view.NewMouseEvent (me); + Assert.True (mouseEventInvoked); + Assert.True (me.Handled); + + view.Dispose (); + } + [Theory] [MemberData (nameof (AllViews))] - public void AllViews_OnMouseEvent_Enabled_False_Does_Not_Set_Handled (View view, string viewName) + public void AllViews_NewMouseEvent_Enabled_False_Does_Not_Set_Handled (View view, string viewName) { if (view == null) { @@ -292,14 +315,14 @@ public void AllViews_OnMouseEvent_Enabled_False_Does_Not_Set_Handled (View view, view.Enabled = false; var me = new MouseEvent (); - view.OnMouseEvent (me); + view.NewMouseEvent (me); Assert.False (me.Handled); view.Dispose (); } [Theory] [MemberData (nameof (AllViews))] - public void AllViews_OnMouseClick_Enabled_False_Does_Not_Set_Handled (View view, string viewName) + public void AllViews_NewMouseEvent_Clicked_Enabled_False_Does_Not_Set_Handled (View view, string viewName) { if (view == null) { @@ -312,7 +335,7 @@ public void AllViews_OnMouseClick_Enabled_False_Does_Not_Set_Handled (View view, { Flags = MouseFlags.Button1Clicked }; - view.OnMouseEvent (me); + view.NewMouseEvent (me); Assert.False (me.Handled); view.Dispose (); } @@ -322,15 +345,14 @@ public void AllViews_OnMouseClick_Enabled_False_Does_Not_Set_Handled (View view, [InlineData (MouseFlags.Button2Pressed, MouseFlags.Button2Released, MouseFlags.Button2Clicked)] [InlineData (MouseFlags.Button3Pressed, MouseFlags.Button3Released, MouseFlags.Button3Clicked)] [InlineData (MouseFlags.Button4Pressed, MouseFlags.Button4Released, MouseFlags.Button4Clicked)] - public void WantContinuousButtonPressed_False_Button1Press_Release_DoesNotClick (MouseFlags pressed, MouseFlags released, MouseFlags clicked) + public void WantContinuousButtonPressed_False_Button_Press_Release_DoesNotClick (MouseFlags pressed, MouseFlags released, MouseFlags clicked) { - var me = new MouseEvent () - { - Flags = pressed - }; + var me = new MouseEvent (); var view = new View () { + Width = 1, + Height = 1, WantContinuousButtonPressed = false }; @@ -338,22 +360,23 @@ public void WantContinuousButtonPressed_False_Button1Press_Release_DoesNotClick view.MouseClick += (s, e) => clickedCount++; - - view.OnMouseEvent (me); + me.Flags = pressed; + view.NewMouseEvent (me); Assert.Equal (0, clickedCount); me.Handled = false; - view.OnMouseEvent (me); + me.Flags = pressed; + view.NewMouseEvent (me); Assert.Equal (0, clickedCount); me.Handled = false; me.Flags = released; - view.OnMouseEvent (me); + view.NewMouseEvent (me); Assert.Equal (0, clickedCount); me.Handled = false; me.Flags =clicked; - view.OnMouseEvent (me); + view.NewMouseEvent (me); Assert.Equal (1, clickedCount); view.Dispose (); @@ -364,15 +387,14 @@ public void WantContinuousButtonPressed_False_Button1Press_Release_DoesNotClick [InlineData (MouseFlags.Button2Pressed, MouseFlags.Button2Released, MouseFlags.Button2Clicked)] [InlineData (MouseFlags.Button3Pressed, MouseFlags.Button3Released, MouseFlags.Button3Clicked)] [InlineData (MouseFlags.Button4Pressed, MouseFlags.Button4Released, MouseFlags.Button4Clicked)] - public void WantContinuousButtonPressed_True_Button1Press_Release_Clicks_Repeatedly (MouseFlags pressed, MouseFlags released, MouseFlags clicked) + public void WantContinuousButtonPressed_True_Button_Press_Release_Clicks_Repeatedly (MouseFlags pressed, MouseFlags released, MouseFlags clicked) { - var me = new MouseEvent () - { - Flags = pressed - }; + var me = new MouseEvent (); var view = new View () { + Width = 1, + Height = 1, WantContinuousButtonPressed = true }; @@ -380,66 +402,179 @@ public void WantContinuousButtonPressed_True_Button1Press_Release_Clicks_Repeate view.MouseClick += (s, e) => clickedCount++; - view.OnMouseEvent (me); - Assert.Equal (0, clickedCount); + me.Flags = pressed; + view.NewMouseEvent (me); + Assert.Equal (1, clickedCount); me.Handled = false; - view.OnMouseEvent (me); - Assert.Equal (1, clickedCount); + me.Flags = pressed; + view.NewMouseEvent (me); + Assert.Equal (2, clickedCount); me.Handled = false; me.Flags = released; - view.OnMouseEvent (me); + view.NewMouseEvent (me); Assert.Equal (2, clickedCount); me.Handled = false; me.Flags = clicked; - view.OnMouseEvent (me); + view.NewMouseEvent (me); Assert.Equal (2, clickedCount); view.Dispose (); } [Fact] - public void HighlightOnPress_False_No_Highlights () + public void WantContinuousButtonPressed_True_Move_InViewport_OutOfViewport_Keeps_Counting () + { + var me = new MouseEvent (); + + var view = new View () + { + Width = 1, + Height = 1, + WantContinuousButtonPressed = true + }; + + var clickedCount = 0; + + view.MouseClick += (s, e) => clickedCount++; + + // Start in Viewport + me.Flags = MouseFlags.Button1Pressed; + me.X = 0; + view.NewMouseEvent (me); + Assert.Equal (1, clickedCount); + me.Handled = false; + + // Move out of Viewport + me.Flags = MouseFlags.Button1Pressed; + me.X = 1; + view.NewMouseEvent (me); + Assert.Equal (2, clickedCount); + me.Handled = false; + + // Move into Viewport + me.Flags = MouseFlags.Button1Pressed; + me.X = 0; + view.NewMouseEvent (me); + Assert.Equal (3, clickedCount); + me.Handled = false; + + view.Dispose (); + } + + [Theory] + [InlineData(false, 0, 0)] + [InlineData (true, 1, 1)] + public void HighlightOnPress_Fires_Events_And_Highlights (bool highlightOnPress, int expectedEnabling, int expectedDisabling) { var view = new View () { - HighlightOnPress = false + HighlightOnPress = highlightOnPress, + Height = 1, + Width = 1 }; + + int enablingHighlight = 0; + int disablingHighlight = 0; + view.EnablingHighlight += View_EnablingHighlight; + view.DisablingHighlight += View_DisablingHighlight; view.ColorScheme = new ColorScheme (new Attribute (ColorName.Red, ColorName.Blue)); ColorScheme originalColorScheme = view.ColorScheme; - var me = new MouseEvent () + view.NewMouseEvent (new () { Flags = MouseFlags.Button1Pressed, }); + + if (highlightOnPress) { - Flags = MouseFlags.Button1Pressed - }; + Assert.NotEqual (originalColorScheme, view.ColorScheme); + } + else + { + Assert.Equal (originalColorScheme, view.ColorScheme); + } - view.OnMouseEvent (me); + view.NewMouseEvent (new () { Flags = MouseFlags.Button1Released, }); Assert.Equal (originalColorScheme, view.ColorScheme); + Assert.Equal (expectedEnabling, enablingHighlight); + Assert.Equal (expectedDisabling, disablingHighlight); view.Dispose (); - } + return; - [Fact] - public void HighlightOnPress_False_Highlights () + void View_DisablingHighlight (object sender, System.ComponentModel.CancelEventArgs e) + { + disablingHighlight++; + } + void View_EnablingHighlight (object sender, System.ComponentModel.CancelEventArgs e) + { + enablingHighlight++; + } + } + + [Theory] + [InlineData (0)] + [InlineData (1)] + [InlineData (10)] + public void HighlightOnPress_Move_Keeps_Highlight (int x) { var view = new View () { - HighlightOnPress = true + HighlightOnPress = true, + Height = 1, + Width = 1 }; - view.ColorScheme = new ColorScheme (new Attribute (ColorName.Red, ColorName.Blue)); - ColorScheme originalColorScheme = view.ColorScheme; + int enablingHighlight = 0; + int disablingHighlight = 0; + view.EnablingHighlight += View_EnablingHighlight; + view.DisablingHighlight += View_DisablingHighlight; + bool inViewport = view.Bounds.Contains (x, 0); - var me = new MouseEvent () + // Start at 0,0 ; in viewport + view.NewMouseEvent (new () { X = 0, Flags = MouseFlags.Button1Pressed }); + Assert.Equal (1, enablingHighlight); + Assert.Equal (0, disablingHighlight); + + // Move to x,0 + view.NewMouseEvent (new () { X = x, Flags = MouseFlags.Button1Pressed }); + + if (inViewport) { - Flags = MouseFlags.Button1Pressed - }; + Assert.Equal (2, enablingHighlight); + Assert.Equal (0, disablingHighlight); + } + else + { + Assert.Equal (1, enablingHighlight); + Assert.Equal (1, disablingHighlight); + } - view.OnMouseEvent (me); - Assert.NotEqual (originalColorScheme, view.ColorScheme); + // Move backto 0,0 ; in viewport + view.NewMouseEvent (new () { X = 0, Flags = MouseFlags.Button1Pressed }); + if (inViewport) + { + Assert.Equal (3, enablingHighlight); + Assert.Equal (0, disablingHighlight); + } + else + { + Assert.Equal (2, enablingHighlight); + Assert.Equal (1, disablingHighlight); + } view.Dispose (); + + return; + + void View_DisablingHighlight (object sender, System.ComponentModel.CancelEventArgs e) + { + disablingHighlight++; + } + void View_EnablingHighlight (object sender, System.ComponentModel.CancelEventArgs e) + { + enablingHighlight++; + } } + } diff --git a/UnitTests/View/NavigationTests.cs b/UnitTests/View/NavigationTests.cs index 773ab0f776..3b5fefc940 100644 --- a/UnitTests/View/NavigationTests.cs +++ b/UnitTests/View/NavigationTests.cs @@ -452,7 +452,7 @@ public void Enabled_False_Sets_HasFocus_To_False () view.NewKeyDownEvent (Key.Space); Assert.True (wasClicked); - view.OnMouseEvent (new MouseEvent { Flags = MouseFlags.Button1Clicked }); + view.NewMouseEvent (new MouseEvent { Flags = MouseFlags.Button1Clicked }); Assert.False (wasClicked); Assert.True (view.Enabled); Assert.True (view.CanFocus); @@ -461,7 +461,7 @@ public void Enabled_False_Sets_HasFocus_To_False () view.Enabled = false; view.NewKeyDownEvent (Key.Space); Assert.False (wasClicked); - view.OnMouseEvent (new MouseEvent { Flags = MouseFlags.Button1Clicked }); + view.NewMouseEvent (new MouseEvent { Flags = MouseFlags.Button1Clicked }); Assert.False (wasClicked); Assert.False (view.Enabled); Assert.True (view.CanFocus); @@ -491,7 +491,7 @@ public void Enabled_Sets_Also_Sets_Subviews () win.NewKeyDownEvent (Key.Enter); Assert.True (wasClicked); - button.OnMouseEvent (new MouseEvent { Flags = MouseFlags.Button1Clicked }); + button.NewMouseEvent (new MouseEvent { Flags = MouseFlags.Button1Clicked }); Assert.False (wasClicked); Assert.True (button.Enabled); Assert.True (button.CanFocus); @@ -503,7 +503,7 @@ public void Enabled_Sets_Also_Sets_Subviews () win.Enabled = false; button.NewKeyDownEvent (Key.Enter); Assert.False (wasClicked); - button.OnMouseEvent (new MouseEvent { Flags = MouseFlags.Button1Clicked }); + button.NewMouseEvent (new MouseEvent { Flags = MouseFlags.Button1Clicked }); Assert.False (wasClicked); Assert.False (button.Enabled); Assert.True (button.CanFocus); diff --git a/UnitTests/View/ViewTests.cs b/UnitTests/View/ViewTests.cs index de9de98c3e..ae6c82c3d4 100644 --- a/UnitTests/View/ViewTests.cs +++ b/UnitTests/View/ViewTests.cs @@ -865,7 +865,7 @@ public void New_Methods_Return_False () //Assert.False (r.OnKeyDown (new KeyEventArgs () { Key = Key.Unknown })); Assert.False (r.OnKeyUp (new Key { KeyCode = KeyCode.Null })); - Assert.False (r.OnMouseEvent (new MouseEvent { Flags = MouseFlags.AllEvents })); + Assert.False (r.NewMouseEvent (new MouseEvent { Flags = MouseFlags.AllEvents })); Assert.False (r.OnMouseEnter (new MouseEvent { Flags = MouseFlags.AllEvents })); Assert.False (r.OnMouseLeave (new MouseEvent { Flags = MouseFlags.AllEvents })); diff --git a/UnitTests/Views/CheckBoxTests.cs b/UnitTests/Views/CheckBoxTests.cs index aeec6b8218..88e2afe9ae 100644 --- a/UnitTests/Views/CheckBoxTests.cs +++ b/UnitTests/Views/CheckBoxTests.cs @@ -47,7 +47,7 @@ public void AllowNullChecked_Get_Set () Assert.False (checkBox.Checked); Assert.True (checkBox.NewKeyDownEvent (Key.Space)); Assert.True (checkBox.Checked); - Assert.True (checkBox.OnMouseEvent (new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Clicked })); + Assert.True (checkBox.NewMouseEvent (new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Clicked })); Assert.False (checkBox.Checked); checkBox.AllowNullChecked = true; @@ -60,11 +60,11 @@ public void AllowNullChecked_Get_Set () {CM.Glyphs.NullChecked} Check this out 你", _output ); - Assert.True (checkBox.OnMouseEvent (new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Clicked })); + Assert.True (checkBox.NewMouseEvent (new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Clicked })); Assert.True (checkBox.Checked); Assert.True (checkBox.NewKeyDownEvent (Key.Space)); Assert.False (checkBox.Checked); - Assert.True (checkBox.OnMouseEvent (new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Clicked })); + Assert.True (checkBox.NewMouseEvent (new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Clicked })); Assert.Null (checkBox.Checked); checkBox.AllowNullChecked = false; diff --git a/UnitTests/Views/ColorPickerTests.cs b/UnitTests/Views/ColorPickerTests.cs index bdf05a84b6..d222f2cd4d 100644 --- a/UnitTests/Views/ColorPickerTests.cs +++ b/UnitTests/Views/ColorPickerTests.cs @@ -52,9 +52,9 @@ public void MouseEvents () top.Add (colorPicker); Application.Begin (top); - Assert.False (colorPicker.OnMouseEvent (new MouseEvent ())); + Assert.False (colorPicker.NewMouseEvent (new MouseEvent ())); - Assert.True (colorPicker.OnMouseEvent (new MouseEvent { Flags = MouseFlags.Button1Clicked, X = 4, Y = 1 })); + Assert.True (colorPicker.NewMouseEvent (new MouseEvent { Flags = MouseFlags.Button1Clicked, X = 4, Y = 1 })); Assert.Equal (ColorName.Blue, colorPicker.SelectedColor); } diff --git a/UnitTests/Views/ComboBoxTests.cs b/UnitTests/Views/ComboBoxTests.cs index 88285ef89a..a50e43cc22 100644 --- a/UnitTests/Views/ComboBoxTests.cs +++ b/UnitTests/Views/ComboBoxTests.cs @@ -146,7 +146,7 @@ public void HideDropdownListOnClick_False_OpenSelectedItem_With_Mouse_And_Key_Cu Assert.Equal ("", cb.Text); Assert.True ( - cb.OnMouseEvent ( + cb.NewMouseEvent ( new MouseEvent { X = cb.Bounds.Right - 1, Y = 0, Flags = MouseFlags.Button1Pressed } ) ); @@ -203,7 +203,7 @@ public void HideDropdownListOnClick_False_OpenSelectedItem_With_Mouse_And_Key_F4 Assert.Equal ("", cb.Text); Assert.True ( - cb.OnMouseEvent ( + cb.NewMouseEvent ( new MouseEvent { X = cb.Bounds.Right - 1, Y = 0, Flags = MouseFlags.Button1Pressed } ) ); @@ -240,7 +240,7 @@ public void Assert.Equal ("", cb.Text); Assert.True ( - cb.OnMouseEvent ( + cb.NewMouseEvent ( new MouseEvent { X = cb.Bounds.Right - 1, Y = 0, Flags = MouseFlags.Button1Pressed } ) ); @@ -297,7 +297,7 @@ public void HideDropdownListOnClick_Gets_Sets () Assert.Equal ("", cb.Text); Assert.True ( - cb.OnMouseEvent ( + cb.NewMouseEvent ( new MouseEvent { X = cb.Bounds.Right - 1, Y = 0, Flags = MouseFlags.Button1Pressed } ) ); @@ -308,7 +308,7 @@ public void HideDropdownListOnClick_Gets_Sets () Assert.True ( cb.Subviews [1] - .OnMouseEvent ( + .NewMouseEvent ( new MouseEvent { X = 0, Y = 1, Flags = MouseFlags.Button1Clicked } ) ); @@ -319,7 +319,7 @@ cb.Subviews [1] Assert.True ( cb.Subviews [1] - .OnMouseEvent ( + .NewMouseEvent ( new MouseEvent { X = 0, Y = 1, Flags = MouseFlags.Button1Clicked } ) ); @@ -332,7 +332,7 @@ cb.Subviews [1] Assert.True ( cb.Subviews [1] - .OnMouseEvent ( + .NewMouseEvent ( new MouseEvent { X = 0, Y = 2, Flags = MouseFlags.Button1Clicked } ) ); @@ -342,14 +342,14 @@ cb.Subviews [1] Assert.Equal ("Three", cb.Text); Assert.True ( - cb.OnMouseEvent ( + cb.NewMouseEvent ( new MouseEvent { X = cb.Bounds.Right - 1, Y = 0, Flags = MouseFlags.Button1Pressed } ) ); Assert.True ( cb.Subviews [1] - .OnMouseEvent ( + .NewMouseEvent ( new MouseEvent { X = 0, Y = 2, Flags = MouseFlags.Button1Clicked } ) ); @@ -359,7 +359,7 @@ cb.Subviews [1] Assert.Equal ("Three", cb.Text); Assert.True ( - cb.OnMouseEvent ( + cb.NewMouseEvent ( new MouseEvent { X = cb.Bounds.Right - 1, Y = 0, Flags = MouseFlags.Button1Pressed } ) ); @@ -370,7 +370,7 @@ cb.Subviews [1] Assert.True ( cb.Subviews [1] - .OnMouseEvent ( + .NewMouseEvent ( new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Clicked } ) ); @@ -398,14 +398,14 @@ public void HideDropdownListOnClick_True_Colapse_On_Click_Outside_Frame () Assert.Equal ("", cb.Text); Assert.True ( - cb.OnMouseEvent ( + cb.NewMouseEvent ( new MouseEvent { X = cb.Bounds.Right - 1, Y = 0, Flags = MouseFlags.Button1Pressed } ) ); Assert.True ( cb.Subviews [1] - .OnMouseEvent ( + .NewMouseEvent ( new MouseEvent { X = cb.Bounds.Right - 1, Y = 0, Flags = MouseFlags.Button1Clicked } ) ); @@ -416,7 +416,7 @@ cb.Subviews [1] Assert.True ( cb.Subviews [1] - .OnMouseEvent ( + .NewMouseEvent ( new MouseEvent { X = -1, Y = 0, Flags = MouseFlags.Button1Clicked } ) ); @@ -429,7 +429,7 @@ cb.Subviews [1] Assert.True ( cb.Subviews [1] - .OnMouseEvent ( + .NewMouseEvent ( new MouseEvent { X = cb.Bounds.Right - 1, Y = 0, Flags = MouseFlags.Button1Clicked } ) ); @@ -440,7 +440,7 @@ cb.Subviews [1] Assert.True ( cb.Subviews [1] - .OnMouseEvent ( + .NewMouseEvent ( new MouseEvent { X = 0, Y = -1, Flags = MouseFlags.Button1Clicked } ) ); @@ -453,7 +453,7 @@ cb.Subviews [1] Assert.True ( cb.Subviews [1] - .OnMouseEvent ( + .NewMouseEvent ( new MouseEvent { X = cb.Bounds.Right - 1, Y = 0, Flags = MouseFlags.Button1Clicked } ) ); @@ -464,7 +464,7 @@ cb.Subviews [1] Assert.True ( cb.Subviews [1] - .OnMouseEvent ( + .NewMouseEvent ( new MouseEvent { X = cb.Frame.Width, Y = 0, Flags = MouseFlags.Button1Clicked } ) ); @@ -477,7 +477,7 @@ cb.Subviews [1] Assert.True ( cb.Subviews [1] - .OnMouseEvent ( + .NewMouseEvent ( new MouseEvent { X = cb.Bounds.Right - 1, Y = 0, Flags = MouseFlags.Button1Clicked } ) ); @@ -488,7 +488,7 @@ cb.Subviews [1] Assert.True ( cb.Subviews [1] - .OnMouseEvent ( + .NewMouseEvent ( new MouseEvent { X = 0, Y = cb.Frame.Height, Flags = MouseFlags.Button1Clicked } ) ); @@ -516,7 +516,7 @@ public void HideDropdownListOnClick_True_Highlight_Current_Item () Assert.Equal ("", cb.Text); Assert.True ( - cb.OnMouseEvent ( + cb.NewMouseEvent ( new MouseEvent { X = cb.Bounds.Right - 1, Y = 0, Flags = MouseFlags.Button1Pressed } ) ); @@ -673,7 +673,7 @@ public void HideDropdownListOnClick_True_OpenSelectedItem_With_Mouse_And_Key_And Assert.Equal ("", cb.Text); Assert.True ( - cb.OnMouseEvent ( + cb.NewMouseEvent ( new MouseEvent { X = cb.Bounds.Right - 1, Y = 0, Flags = MouseFlags.Button1Pressed } ) ); @@ -685,7 +685,7 @@ public void HideDropdownListOnClick_True_OpenSelectedItem_With_Mouse_And_Key_And Assert.True (cb.Subviews [1].NewKeyDownEvent (Key.CursorDown)); Assert.True ( - cb.OnMouseEvent ( + cb.NewMouseEvent ( new MouseEvent { X = cb.Bounds.Right - 1, Y = 0, Flags = MouseFlags.Button1Pressed } ) ); @@ -695,7 +695,7 @@ public void HideDropdownListOnClick_True_OpenSelectedItem_With_Mouse_And_Key_And Assert.Equal ("", cb.Text); Assert.True ( - cb.OnMouseEvent ( + cb.NewMouseEvent ( new MouseEvent { X = cb.Bounds.Right - 1, Y = 0, Flags = MouseFlags.Button1Pressed } ) ); @@ -707,7 +707,7 @@ public void HideDropdownListOnClick_True_OpenSelectedItem_With_Mouse_And_Key_And Assert.True (cb.Subviews [1].NewKeyDownEvent (Key.CursorUp)); Assert.True ( - cb.OnMouseEvent ( + cb.NewMouseEvent ( new MouseEvent { X = cb.Bounds.Right - 1, Y = 0, Flags = MouseFlags.Button1Pressed } ) ); @@ -735,7 +735,7 @@ public void HideDropdownListOnClick_True_OpenSelectedItem_With_Mouse_And_Key_Cur Assert.Equal ("", cb.Text); Assert.True ( - cb.OnMouseEvent ( + cb.NewMouseEvent ( new MouseEvent { X = cb.Bounds.Right - 1, Y = 0, Flags = MouseFlags.Button1Pressed } ) ); @@ -792,7 +792,7 @@ public void HideDropdownListOnClick_True_OpenSelectedItem_With_Mouse_And_Key_F4 Assert.Equal ("", cb.Text); Assert.True ( - cb.OnMouseEvent ( + cb.NewMouseEvent ( new MouseEvent { X = cb.Bounds.Right - 1, Y = 0, Flags = MouseFlags.Button1Pressed } ) ); diff --git a/UnitTests/Views/ContextMenuTests.cs b/UnitTests/Views/ContextMenuTests.cs index 239dca482e..bd3f5e4882 100644 --- a/UnitTests/Views/ContextMenuTests.cs +++ b/UnitTests/Views/ContextMenuTests.cs @@ -107,11 +107,11 @@ public void ContextMenu_Is_Closed_If_Another_MenuBar_Is_Open_Or_Vice_Versa () Assert.True (ContextMenu.IsShow); Assert.Equal (cm.MenuBar, Application.MouseGrabView); Assert.False (menu.IsMenuOpen); - Assert.False (menu.OnMouseEvent (new MouseEvent { X = 1, Flags = MouseFlags.ReportMousePosition, View = menu })); + Assert.False (menu.NewMouseEvent(new MouseEvent { X = 1, Flags = MouseFlags.ReportMousePosition, View = menu })); Assert.True (ContextMenu.IsShow); Assert.Equal (cm.MenuBar, Application.MouseGrabView); Assert.False (menu.IsMenuOpen); - Assert.True (menu.OnMouseEvent (new MouseEvent { X = 1, Flags = MouseFlags.Button1Clicked, View = menu })); + Assert.True (menu.NewMouseEvent(new MouseEvent { X = 1, Flags = MouseFlags.Button1Clicked, View = menu })); Assert.False (ContextMenu.IsShow); Assert.Equal (menu, Application.MouseGrabView); Assert.True (menu.IsMenuOpen); @@ -269,11 +269,7 @@ public void Draw_A_ContextMenu_Over_A_Borderless_Top () _output ); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 8, Y = 2, Flags = MouseFlags.Button3Clicked } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 8, Y = 2, Flags = MouseFlags.Button3Clicked }); var firstIteration = false; Application.RunIteration (ref rs, ref firstIteration); @@ -355,11 +351,7 @@ public void Draw_A_ContextMenu_Over_A_Dialog () _output ); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 9, Y = 3, Flags = MouseFlags.Button3Clicked } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 9, Y = 3, Flags = MouseFlags.Button3Clicked }); var firstIteration = false; Application.RunIteration (ref rsDialog, ref firstIteration); @@ -414,11 +406,7 @@ public void Draw_A_ContextMenu_Over_A_Top_Dialog () _output ); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 9, Y = 3, Flags = MouseFlags.Button3Clicked } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 9, Y = 3, Flags = MouseFlags.Button3Clicked }); var firstIteration = false; Application.RunIteration (ref rs, ref firstIteration); @@ -517,7 +505,7 @@ public void Hide_Is_Invoke_At_Container_Closing () top.RequestStop (); Assert.False (ContextMenu.IsShow); } - + [Fact] [AutoInitShutdown] public void Key_Open_And_Close_The_ContextMenu () @@ -653,7 +641,7 @@ public void Menus_And_SubMenus_Always_Try_To_Be_On_Screen () Assert.True ( top.Subviews [0] - .OnMouseEvent ( + .NewMouseEvent ( new MouseEvent { X = 0, Y = 3, Flags = MouseFlags.ReportMousePosition, View = top.Subviews [0] } ) ); @@ -701,7 +689,7 @@ top.Subviews [0] Assert.True ( top.Subviews [0] - .OnMouseEvent ( + .NewMouseEvent ( new MouseEvent { X = 30, Y = 3, Flags = MouseFlags.ReportMousePosition, View = top.Subviews [0] } ) ); @@ -748,7 +736,7 @@ top.Subviews [0] Assert.True ( top.Subviews [0] - .OnMouseEvent ( + .NewMouseEvent ( new MouseEvent { X = 30, Y = 3, Flags = MouseFlags.ReportMousePosition, View = top.Subviews [0] } ) ); @@ -792,7 +780,7 @@ top.Subviews [0] Assert.True ( top.Subviews [0] - .OnMouseEvent ( + .NewMouseEvent ( new MouseEvent { X = 30, Y = 3, Flags = MouseFlags.ReportMousePosition, View = top.Subviews [0] } ) ); @@ -836,7 +824,7 @@ top.Subviews [0] Assert.True ( top.Subviews [0] - .OnMouseEvent ( + .NewMouseEvent ( new MouseEvent { X = 30, Y = 3, Flags = MouseFlags.ReportMousePosition, View = top.Subviews [0] } ) ); @@ -879,12 +867,12 @@ public void MouseFlags_Changing () top.Add (lbl); Application.Begin (top); - Assert.True (lbl.OnMouseEvent (new MouseEvent { Flags = cm.MouseFlags })); + Assert.True (lbl.NewMouseEvent (new MouseEvent { Flags = cm.MouseFlags })); Assert.Equal ("Replaced", lbl.Text); lbl.Text = "Original"; cm.MouseFlags = MouseFlags.Button2Clicked; - Assert.True (lbl.OnMouseEvent (new MouseEvent { Flags = cm.MouseFlags })); + Assert.True (lbl.NewMouseEvent (new MouseEvent { Flags = cm.MouseFlags })); Assert.Equal ("Replaced", lbl.Text); } @@ -1326,11 +1314,7 @@ public void UseSubMenusSingleFrame_True_By_Mouse () ); // X=5 is the border and so need to use at least one more - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 6, Y = 13, Flags = MouseFlags.Button1Clicked } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 6, Y = 13, Flags = MouseFlags.Button1Clicked }); var firstIteration = false; Application.RunIteration (ref rs, ref firstIteration); @@ -1348,11 +1332,7 @@ public void UseSubMenusSingleFrame_True_By_Mouse () _output ); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 6, Y = 12, Flags = MouseFlags.Button1Clicked } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 6, Y = 12, Flags = MouseFlags.Button1Clicked }); firstIteration = false; Application.RunIteration (ref rs, ref firstIteration); @@ -1371,7 +1351,7 @@ public void UseSubMenusSingleFrame_True_By_Mouse () Application.End (rs); } - [Fact] + [Fact] [AutoInitShutdown] public void UseSubMenusSingleFrame_False_By_Mouse () { @@ -1423,11 +1403,7 @@ public void UseSubMenusSingleFrame_False_By_Mouse () _output ); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 6, Y = 13, Flags = MouseFlags.ReportMousePosition } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 6, Y = 13, Flags = MouseFlags.ReportMousePosition }); var firstIteration = false; Application.RunIteration (ref rs, ref firstIteration); @@ -1444,11 +1420,7 @@ public void UseSubMenusSingleFrame_False_By_Mouse () _output ); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 6, Y = 14, Flags = MouseFlags.ReportMousePosition } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 6, Y = 14, Flags = MouseFlags.ReportMousePosition }); firstIteration = false; Application.RunIteration (ref rs, ref firstIteration); @@ -1466,11 +1438,7 @@ public void UseSubMenusSingleFrame_False_By_Mouse () _output ); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 6, Y = 13, Flags = MouseFlags.ReportMousePosition } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 6, Y = 13, Flags = MouseFlags.ReportMousePosition }); firstIteration = false; Application.RunIteration (ref rs, ref firstIteration); diff --git a/UnitTests/Views/LabelTests.cs b/UnitTests/Views/LabelTests.cs index 6a7d10df64..c309b16cf8 100644 --- a/UnitTests/Views/LabelTests.cs +++ b/UnitTests/Views/LabelTests.cs @@ -67,7 +67,7 @@ public void MouseClick_SetsFocus_OnNextSubview () Assert.False (label.HasFocus); Assert.False (nextSubview.HasFocus); - label.OnMouseEvent (new MouseEvent () { X = 0, Y = 0, Flags = MouseFlags.Button1Clicked }); + label.NewMouseEvent (new MouseEvent () { X = 0, Y = 0, Flags = MouseFlags.Button1Clicked }); Assert.False (label.HasFocus); Assert.True (nextSubview.HasFocus); } diff --git a/UnitTests/Views/ListViewTests.cs b/UnitTests/Views/ListViewTests.cs index 71193de12e..a7ee74fc7c 100644 --- a/UnitTests/Views/ListViewTests.cs +++ b/UnitTests/Views/ListViewTests.cs @@ -425,7 +425,7 @@ public void HotKey_Command_Does_Not_Accept () public void Accept_Command_Accepts_and_Opens_Selected_Item () { List source = ["One", "Two", "Three"]; - var listView = new ListView {Source = new ListWrapper (source) }; + var listView = new ListView { Source = new ListWrapper (source) }; listView.SelectedItem = 0; var accepted = false; @@ -719,48 +719,43 @@ public void Clicking_On_Border_Is_Ignored () │Three│ └─────┘", _output); - Application.OnMouseEvent (new (new () - { - X = 0, - Y = 0, - Flags = MouseFlags.Button1Clicked - })); + Application.OnMouseEvent (new () { X = 0, Y = 0, Flags = MouseFlags.Button1Clicked }); Assert.Equal ("", selected); Assert.Equal (-1, lv.SelectedItem); - Application.OnMouseEvent (new (new () + Application.OnMouseEvent (new () { X = 1, Y = 1, Flags = MouseFlags.Button1Clicked - })); + }); Assert.Equal ("One", selected); Assert.Equal (0, lv.SelectedItem); - Application.OnMouseEvent (new (new () + Application.OnMouseEvent (new () { X = 1, Y = 2, Flags = MouseFlags.Button1Clicked - })); + }); Assert.Equal ("Two", selected); Assert.Equal (1, lv.SelectedItem); - Application.OnMouseEvent (new (new () + Application.OnMouseEvent (new () { X = 1, Y = 3, Flags = MouseFlags.Button1Clicked - })); + }); Assert.Equal ("Three", selected); Assert.Equal (2, lv.SelectedItem); - Application.OnMouseEvent (new (new () + Application.OnMouseEvent (new () { X = 1, Y = 4, Flags = MouseFlags.Button1Clicked - })); + }); Assert.Equal ("Three", selected); Assert.Equal (2, lv.SelectedItem); } diff --git a/UnitTests/Views/MenuBarTests.cs b/UnitTests/Views/MenuBarTests.cs index ddd216bd58..99b9dc42e6 100644 --- a/UnitTests/Views/MenuBarTests.cs +++ b/UnitTests/Views/MenuBarTests.cs @@ -37,13 +37,13 @@ public void AllowNullChecked_Get_Set () Assert.True (mi.Checked); Assert.True ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu } ) ); Assert.True ( - menu._openMenu.OnMouseEvent ( + menu._openMenu.NewMouseEvent ( new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Clicked, View = menu._openMenu } ) ); @@ -57,7 +57,7 @@ public void AllowNullChecked_Get_Set () Assert.Null (mi.Checked); Assert.True ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu } ) ); @@ -75,7 +75,7 @@ Nullable Checked ); Assert.True ( - menu._openMenu.OnMouseEvent ( + menu._openMenu.NewMouseEvent ( new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Clicked, View = menu._openMenu } ) ); @@ -87,13 +87,13 @@ Nullable Checked Assert.False (mi.Checked); Assert.True ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu } ) ); Assert.True ( - menu._openMenu.OnMouseEvent ( + menu._openMenu.NewMouseEvent ( new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Clicked, View = menu._openMenu } ) ); @@ -296,7 +296,7 @@ public void Disabled_MenuItem_Is_Never_Selected () ); Assert.True ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu } ) ); @@ -317,7 +317,7 @@ public void Disabled_MenuItem_Is_Never_Selected () Assert.True ( top.Subviews [1] - .OnMouseEvent ( + .NewMouseEvent ( new MouseEvent { X = 0, Y = 2, Flags = MouseFlags.Button1Clicked, View = top.Subviews [1] } ) ); @@ -338,7 +338,7 @@ top.Subviews [1] Assert.True ( top.Subviews [1] - .OnMouseEvent ( + .NewMouseEvent ( new MouseEvent { X = 0, Y = 2, Flags = MouseFlags.ReportMousePosition, View = top.Subviews [1] } ) ); @@ -516,11 +516,7 @@ void ChangeMenuTitle (string title) _output ); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 20, Y = 5, Flags = MouseFlags.Button1Clicked } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 20, Y = 5, Flags = MouseFlags.Button1Clicked }); firstIteration = false; @@ -553,11 +549,7 @@ void ChangeMenuTitle (string title) { menu.OpenMenu (); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 20, Y = 5 + i, Flags = MouseFlags.Button1Clicked } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 20, Y = 5 + i, Flags = MouseFlags.Button1Clicked }); firstIteration = false; Application.RunIteration (ref rsDialog, ref firstIteration); @@ -712,11 +704,7 @@ void ChangeMenuTitle (string title) _output ); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 20, Y = 5, Flags = MouseFlags.Button1Clicked } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 20, Y = 5, Flags = MouseFlags.Button1Clicked }); firstIteration = false; @@ -738,11 +726,7 @@ void ChangeMenuTitle (string title) { menu.OpenMenu (); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 20, Y = 5 + i, Flags = MouseFlags.Button1Clicked } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 20, Y = 5 + i, Flags = MouseFlags.Button1Clicked }); firstIteration = false; Application.RunIteration (ref rs, ref firstIteration); @@ -1473,13 +1457,13 @@ .Children [0] top.Add (menu); Application.Begin (top); - Assert.True (menu.OnMouseEvent (new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu })); + Assert.True (menu.NewMouseEvent (new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu })); Assert.True (menu.IsMenuOpen); top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (0), _output); - Assert.True (menu.OnMouseEvent (new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu })); + Assert.True (menu.NewMouseEvent (new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu })); Assert.False (menu.IsMenuOpen); top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ClosedMenuText, _output); @@ -2189,7 +2173,7 @@ public void MenuOpened_On_Disabled_MenuItem () // open the menu Assert.True ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu } ) ); @@ -2198,7 +2182,7 @@ public void MenuOpened_On_Disabled_MenuItem () Assert.Equal ("_New", miCurrent.Title); Assert.True ( - mCurrent.OnMouseEvent ( + mCurrent.NewMouseEvent ( new MouseEvent { X = 1, Y = 1, Flags = MouseFlags.ReportMousePosition, View = mCurrent } ) ); @@ -2207,7 +2191,7 @@ public void MenuOpened_On_Disabled_MenuItem () Assert.Equal ("_New", miCurrent.Title); Assert.True ( - mCurrent.OnMouseEvent ( + mCurrent.NewMouseEvent ( new MouseEvent { X = 1, Y = 1, Flags = MouseFlags.ReportMousePosition, View = mCurrent } ) ); @@ -2216,7 +2200,7 @@ public void MenuOpened_On_Disabled_MenuItem () Assert.Equal ("_New", miCurrent.Title); Assert.True ( - mCurrent.OnMouseEvent ( + mCurrent.NewMouseEvent ( new MouseEvent { X = 1, Y = 2, Flags = MouseFlags.ReportMousePosition, View = mCurrent } ) ); @@ -2226,7 +2210,7 @@ public void MenuOpened_On_Disabled_MenuItem () // close the menu Assert.True ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu } ) ); @@ -2394,7 +2378,7 @@ public void MouseEvent_Test () // Click on Edit Assert.True ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 10, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu } ) ); @@ -2404,7 +2388,7 @@ public void MouseEvent_Test () // Click on Paste Assert.True ( - mCurrent.OnMouseEvent ( + mCurrent.NewMouseEvent ( new MouseEvent { X = 10, Y = 2, Flags = MouseFlags.ReportMousePosition, View = mCurrent } ) ); @@ -2418,7 +2402,7 @@ public void MouseEvent_Test () { // Edit menu is open. Click on the menu at Y = -1, which is outside the menu. Assert.False ( - mCurrent.OnMouseEvent ( + mCurrent.NewMouseEvent ( new MouseEvent { X = 10, Y = i, Flags = MouseFlags.ReportMousePosition, View = menu } ) ); @@ -2427,7 +2411,7 @@ public void MouseEvent_Test () { // Edit menu is open. Click on the menu at Y = i. Assert.True ( - mCurrent.OnMouseEvent ( + mCurrent.NewMouseEvent ( new MouseEvent { X = 10, Y = i, Flags = MouseFlags.ReportMousePosition, View = mCurrent } ) ); @@ -2590,14 +2574,14 @@ public void Parent_MenuItem_Stay_Focused_If_Child_MenuItem_Is_Empty_By_Mouse () Application.Begin (top); Assert.True (tf.HasFocus); - Assert.True (menu.OnMouseEvent (new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu })); + Assert.True (menu.NewMouseEvent (new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu })); Assert.True (menu.IsMenuOpen); Assert.False (tf.HasFocus); top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (0), _output); Assert.True ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 8, Y = 0, Flags = MouseFlags.ReportMousePosition, View = menu } ) ); @@ -2607,7 +2591,7 @@ public void Parent_MenuItem_Stay_Focused_If_Child_MenuItem_Is_Empty_By_Mouse () TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (1), _output); Assert.True ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 15, Y = 0, Flags = MouseFlags.ReportMousePosition, View = menu } ) ); @@ -2617,7 +2601,7 @@ public void Parent_MenuItem_Stay_Focused_If_Child_MenuItem_Is_Empty_By_Mouse () TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (2), _output); Assert.True ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 8, Y = 0, Flags = MouseFlags.ReportMousePosition, View = menu } ) ); @@ -2627,7 +2611,7 @@ public void Parent_MenuItem_Stay_Focused_If_Child_MenuItem_Is_Empty_By_Mouse () TestHelpers.AssertDriverContentsAre (expectedMenu.ClosedMenuText, _output); Assert.True ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.ReportMousePosition, View = menu } ) ); @@ -2636,7 +2620,7 @@ public void Parent_MenuItem_Stay_Focused_If_Child_MenuItem_Is_Empty_By_Mouse () top.Draw (); TestHelpers.AssertDriverContentsAre (expectedMenu.ExpectedSubMenuOpen (0), _output); - Assert.True (menu.OnMouseEvent (new MouseEvent { X = 8, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu })); + Assert.True (menu.NewMouseEvent (new MouseEvent { X = 8, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu })); Assert.False (menu.IsMenuOpen); Assert.True (tf.HasFocus); top.Draw (); @@ -2969,7 +2953,7 @@ public void UseSubMenusSingleFrame_False_By_Mouse () Assert.Equal (new Rectangle (1, 0, 8, 1), pos); Assert.True ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu } ) ); @@ -2988,7 +2972,7 @@ public void UseSubMenusSingleFrame_False_By_Mouse () Assert.Equal (new Rectangle (1, 0, 10, 6), pos); Assert.False ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 1, Y = 2, Flags = MouseFlags.ReportMousePosition, View = Application.Top.Subviews [1] @@ -3011,7 +2995,7 @@ public void UseSubMenusSingleFrame_False_By_Mouse () Assert.Equal (new Rectangle (1, 0, 25, 7), pos); Assert.False ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 1, Y = 1, Flags = MouseFlags.ReportMousePosition, View = Application.Top.Subviews [1] @@ -3033,7 +3017,7 @@ public void UseSubMenusSingleFrame_False_By_Mouse () Assert.Equal (new Rectangle (1, 0, 10, 6), pos); Assert.False ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 70, Y = 2, Flags = MouseFlags.Button1Clicked, View = Application.Top } ) ); @@ -3279,7 +3263,7 @@ public void UseSubMenusSingleFrame_True_By_Mouse () Assert.Equal (new Rectangle (1, 0, 8, 1), pos); Assert.True ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu } ) ); @@ -3298,7 +3282,7 @@ public void UseSubMenusSingleFrame_True_By_Mouse () Assert.Equal (new Rectangle (1, 0, 10, 6), pos); Assert.False ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 1, Y = 2, Flags = MouseFlags.Button1Clicked, View = Application.Top.Subviews [1] } ) ); @@ -3318,7 +3302,7 @@ public void UseSubMenusSingleFrame_True_By_Mouse () Assert.Equal (new Rectangle (1, 0, 15, 7), pos); Assert.False ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 1, Y = 1, Flags = MouseFlags.Button1Clicked, View = Application.Top.Subviews [2] } ) ); @@ -3337,7 +3321,7 @@ public void UseSubMenusSingleFrame_True_By_Mouse () Assert.Equal (new Rectangle (1, 0, 10, 6), pos); Assert.False ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 70, Y = 2, Flags = MouseFlags.Button1Clicked, View = Application.Top } ) ); @@ -3475,7 +3459,7 @@ public void UseSubMenusSingleFrame_True_Without_Border () Assert.Equal (new Rectangle (1, 0, 8, 1), pos); Assert.True ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1Pressed, View = menu } ) ); @@ -3492,7 +3476,7 @@ public void UseSubMenusSingleFrame_True_Without_Border () Assert.Equal (new Rectangle (1, 0, 8, 4), pos); Assert.False ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 1, Y = 2, Flags = MouseFlags.Button1Clicked, View = Application.Top.Subviews [1] } ) ); @@ -3510,7 +3494,7 @@ public void UseSubMenusSingleFrame_True_Without_Border () Assert.Equal (new Rectangle (1, 0, 13, 5), pos); Assert.False ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 1, Y = 1, Flags = MouseFlags.Button1Clicked, View = Application.Top.Subviews [2] } ) ); @@ -3527,7 +3511,7 @@ public void UseSubMenusSingleFrame_True_Without_Border () Assert.Equal (new Rectangle (1, 0, 8, 4), pos); Assert.False ( - menu.OnMouseEvent ( + menu.NewMouseEvent ( new MouseEvent { X = 70, Y = 2, Flags = MouseFlags.Button1Clicked, View = Application.Top } ) ); @@ -3710,7 +3694,7 @@ public void Click_Another_View_Close_An_Open_Menu () top.Add (menu, btn); Application.Begin (top); - Application.OnMouseEvent (new (new () { X = 0, Y = 4, Flags = MouseFlags.Button1Clicked })); + Application.OnMouseEvent (new () { X = 0, Y = 4, Flags = MouseFlags.Button1Clicked }); Assert.True (btnClicked); } } diff --git a/UnitTests/Views/OverlappedTests.cs b/UnitTests/Views/OverlappedTests.cs index 87bbebe3ed..0e66eb74cd 100644 --- a/UnitTests/Views/OverlappedTests.cs +++ b/UnitTests/Views/OverlappedTests.cs @@ -944,11 +944,7 @@ Colors.ColorSchemes ["Base"].Normal attributes ); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 1, Y = 1, Flags = MouseFlags.Button1Pressed } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 1, Y = 1, Flags = MouseFlags.Button1Pressed }); Assert.Equal (win2.Border, Application.MouseGrabView); Application.RunIteration (ref rsOverlapped, ref firstIteration); @@ -960,17 +956,13 @@ Colors.ColorSchemes ["Base"].Normal Assert.Equal (win2, Application.Current); Assert.Equal (win1, rsWin1.Toplevel); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent - { - X = 2, - Y = 2, - Flags = MouseFlags.Button1Pressed - | MouseFlags.ReportMousePosition - } - ) - ); + Application.OnMouseEvent (new MouseEvent + { + X = 2, + Y = 2, + Flags = MouseFlags.Button1Pressed + | MouseFlags.ReportMousePosition + }); Application.RunIteration (ref rsOverlapped, ref firstIteration); diff --git a/UnitTests/Views/ScrollBarViewTests.cs b/UnitTests/Views/ScrollBarViewTests.cs index 7ef271ac87..d3c3e2ab3a 100644 --- a/UnitTests/Views/ScrollBarViewTests.cs +++ b/UnitTests/Views/ScrollBarViewTests.cs @@ -1154,11 +1154,7 @@ This is a test _output ); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 15, Y = 0, Flags = MouseFlags.Button1Clicked } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 15, Y = 0, Flags = MouseFlags.Button1Clicked }); Assert.Null (Application.MouseGrabView); Assert.True (clicked); @@ -1186,11 +1182,7 @@ This is a test _output ); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 15, Y = 0, Flags = MouseFlags.Button1Clicked } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 15, Y = 0, Flags = MouseFlags.Button1Clicked }); Assert.Null (Application.MouseGrabView); Assert.True (clicked); diff --git a/UnitTests/Views/TabViewTests.cs b/UnitTests/Views/TabViewTests.cs index 200f9638e5..e798fda2de 100644 --- a/UnitTests/Views/TabViewTests.cs +++ b/UnitTests/Views/TabViewTests.cs @@ -141,32 +141,26 @@ public void MouseClick_ChangesTab () top.Add (tv); Application.Begin (top); - MouseEventEventArgs args; + MouseEvent args; // Waving mouse around does not trigger click for (var i = 0; i < 100; i++) { - args = new MouseEventEventArgs ( - new MouseEvent { X = i, Y = 1, Flags = MouseFlags.ReportMousePosition } - ); + args = new MouseEvent { X = i, Y = 1, Flags = MouseFlags.ReportMousePosition }; Application.OnMouseEvent (args); Application.Refresh (); Assert.Null (clicked); Assert.Equal (tab1, tv.SelectedTab); } - args = new MouseEventEventArgs ( - new MouseEvent { X = 3, Y = 1, Flags = MouseFlags.Button1Clicked } - ); + args = new MouseEvent { X = 3, Y = 1, Flags = MouseFlags.Button1Clicked }; Application.OnMouseEvent (args); Application.Refresh (); Assert.Equal (tab1, clicked); Assert.Equal (tab1, tv.SelectedTab); // Click to tab2 - args = new MouseEventEventArgs ( - new MouseEvent { X = 6, Y = 1, Flags = MouseFlags.Button1Clicked } - ); + args = new MouseEvent { X = 6, Y = 1, Flags = MouseFlags.Button1Clicked }; Application.OnMouseEvent (args); Application.Refresh (); Assert.Equal (tab2, clicked); @@ -179,9 +173,7 @@ public void MouseClick_ChangesTab () e.MouseEvent.Handled = true; }; - args = new MouseEventEventArgs ( - new MouseEvent { X = 3, Y = 1, Flags = MouseFlags.Button1Clicked } - ); + args = new MouseEvent { X = 3, Y = 1, Flags = MouseFlags.Button1Clicked }; Application.OnMouseEvent (args); Application.Refresh (); @@ -189,9 +181,7 @@ public void MouseClick_ChangesTab () Assert.Equal (tab1, clicked); Assert.Equal (tab2, tv.SelectedTab); - args = new MouseEventEventArgs ( - new MouseEvent { X = 12, Y = 1, Flags = MouseFlags.Button1Clicked } - ); + args = new MouseEvent { X = 12, Y = 1, Flags = MouseFlags.Button1Clicked }; Application.OnMouseEvent (args); Application.Refresh (); @@ -245,9 +235,7 @@ public void MouseClick_Right_Left_Arrows_ChangesTab () Application.Begin (top); // Click the right arrow - var args = new MouseEventEventArgs ( - new MouseEvent { X = 6, Y = 2, Flags = MouseFlags.Button1Clicked } - ); + var args = new MouseEvent { X = 6, Y = 2, Flags = MouseFlags.Button1Clicked }; Application.OnMouseEvent (args); Application.Refresh (); Assert.Null (clicked); @@ -267,9 +255,7 @@ public void MouseClick_Right_Left_Arrows_ChangesTab () ); // Click the left arrow - args = new MouseEventEventArgs ( - new MouseEvent { X = 0, Y = 2, Flags = MouseFlags.Button1Clicked } - ); + args = new MouseEvent { X = 0, Y = 2, Flags = MouseFlags.Button1Clicked }; Application.OnMouseEvent (args); Application.Refresh (); Assert.Null (clicked); @@ -339,9 +325,7 @@ public void MouseClick_Right_Left_Arrows_ChangesTab_With_Border () Application.Begin (top); // Click the right arrow - var args = new MouseEventEventArgs ( - new MouseEvent { X = 7, Y = 3, Flags = MouseFlags.Button1Clicked } - ); + var args = new MouseEvent { X = 7, Y = 3, Flags = MouseFlags.Button1Clicked }; Application.OnMouseEvent (args); Application.Refresh (); Assert.Null (clicked); @@ -363,9 +347,7 @@ public void MouseClick_Right_Left_Arrows_ChangesTab_With_Border () ); // Click the left arrow - args = new MouseEventEventArgs ( - new MouseEvent { X = 1, Y = 3, Flags = MouseFlags.Button1Clicked } - ); + args = new MouseEvent { X = 1, Y = 3, Flags = MouseFlags.Button1Clicked }; Application.OnMouseEvent (args); Application.Refresh (); Assert.Null (clicked); diff --git a/UnitTests/Views/TextFieldTests.cs b/UnitTests/Views/TextFieldTests.cs index 3418de10d8..7794837edd 100644 --- a/UnitTests/Views/TextFieldTests.cs +++ b/UnitTests/Views/TextFieldTests.cs @@ -1039,13 +1039,13 @@ public void MouseEvent_Handled_Prevents_RightClick () var mouseEvent = new MouseEvent { Flags = MouseFlags.Button1Clicked, View = tf }; - Application.OnMouseEvent (new MouseEventEventArgs (mouseEvent)); + Application.OnMouseEvent (mouseEvent); Assert.Equal (1, clickCounter); // Get a fresh instance that represents a right click. // Should be ignored because of SuppressRightClick callback mouseEvent = new MouseEvent { Flags = MouseFlags.Button3Clicked, View = tf }; - Application.OnMouseEvent (new MouseEventEventArgs (mouseEvent)); + Application.OnMouseEvent (mouseEvent); Assert.Equal (1, clickCounter); Application.MouseEvent -= HandleRightClick; @@ -1058,14 +1058,14 @@ public void MouseEvent_Handled_Prevents_RightClick () // This call causes the context menu to pop, and MouseEvent() returns true. // Thus, the clickCounter is NOT incremented. // Which is correct, because the user did NOT click with the left mouse button. - Application.OnMouseEvent (new MouseEventEventArgs (mouseEvent)); + Application.OnMouseEvent (mouseEvent); Assert.Equal (1, clickCounter); return; - void HandleRightClick (object sender, MouseEventEventArgs arg) + void HandleRightClick (object sender, MouseEvent arg) { - if (arg.MouseEvent.Flags.HasFlag (MouseFlags.Button3Clicked)) + if (arg.Flags.HasFlag (MouseFlags.Button3Clicked)) { arg.Handled = true; } diff --git a/UnitTests/Views/ToplevelTests.cs b/UnitTests/Views/ToplevelTests.cs index 6ae1a33ec7..4dfce26ece 100644 --- a/UnitTests/Views/ToplevelTests.cs +++ b/UnitTests/Views/ToplevelTests.cs @@ -274,7 +274,7 @@ public void Internal_Tests () Assert.NotNull (top.MenuBar); // Application.Top with a menu and without status bar. - View.GetLocationEnsuringFullVisibility (top, 2, 2, out nx, out ny, out sb); + View.GetLocationEnsuringFullVisibility (top, 2, 2, out nx, out ny, out sb); Assert.Equal (0, nx); Assert.Equal (1, ny); Assert.Null (sb); @@ -383,7 +383,7 @@ public void Internal_Tests () //Assert.Null (Toplevel._dragPosition); win.OnMouseEvent (new MouseEvent { X = 6, Y = 0, Flags = MouseFlags.Button1Pressed }); - // Assert.Equal (new Point (6, 0), Toplevel._dragPosition); + // Assert.Equal (new Point (6, 0), Toplevel._dragPosition); win.OnMouseEvent (new MouseEvent { X = 6, Y = 0, Flags = MouseFlags.Button1Released }); //Assert.Null (Toplevel._dragPosition); win.CanFocus = false; @@ -893,11 +893,7 @@ public void Mouse_Drag_On_Top_With_Superview_Null () Assert.Null (Application.MouseGrabView); // Grab the mouse - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 3, Y = 2, Flags = MouseFlags.Button1Pressed } - ) - ); + Application.OnMouseEvent (new () { X = 3, Y = 2, Flags = MouseFlags.Button1Pressed }); Assert.Equal (Application.Current.Border, Application.MouseGrabView); Assert.Equal (new Rectangle (2, 2, 10, 3), Application.Current.Frame); @@ -907,17 +903,13 @@ public void Mouse_Drag_On_Top_With_Superview_Null () Assert.Equal (Application.Current.Border, Application.MouseGrabView); // Drag to left - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent - { - X = 2, - Y = 2, - Flags = MouseFlags.Button1Pressed - | MouseFlags.ReportMousePosition - } - ) - ); + Application.OnMouseEvent (new () + { + X = 2, + Y = 2, + Flags = MouseFlags.Button1Pressed + | MouseFlags.ReportMousePosition + }); Application.Refresh (); Assert.Equal (Application.Current.Border, Application.MouseGrabView); @@ -946,17 +938,13 @@ public void Mouse_Drag_On_Top_With_Superview_Null () Assert.Equal (Application.Current.Border, Application.MouseGrabView); // Drag up - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent - { - X = 2, - Y = 1, - Flags = MouseFlags.Button1Pressed - | MouseFlags.ReportMousePosition - } - ) - ); + Application.OnMouseEvent (new () + { + X = 2, + Y = 1, + Flags = MouseFlags.Button1Pressed + | MouseFlags.ReportMousePosition + }); Application.Refresh (); Assert.Equal (Application.Current.Border, Application.MouseGrabView); @@ -986,11 +974,7 @@ public void Mouse_Drag_On_Top_With_Superview_Null () Assert.Equal (Application.Current.Border, Application.MouseGrabView); // Ungrab the mouse - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 2, Y = 1, Flags = MouseFlags.Button1Released } - ) - ); + Application.OnMouseEvent (new () { X = 2, Y = 1, Flags = MouseFlags.Button1Released }); Application.Refresh (); Assert.Null (Application.MouseGrabView); @@ -1038,15 +1022,11 @@ public void Mouse_Drag_On_Top_With_Superview_Not_Null () Assert.Null (Application.MouseGrabView); // Grab the mouse - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent - { - X = win.Frame.X, Y = win.Frame.Y, - Flags = MouseFlags.Button1Pressed - } - ) - ); + Application.OnMouseEvent (new MouseEvent + { + X = win.Frame.X, Y = win.Frame.Y, + Flags = MouseFlags.Button1Pressed + }); Assert.Equal (win.Border, Application.MouseGrabView); } @@ -1058,17 +1038,13 @@ public void Mouse_Drag_On_Top_With_Superview_Not_Null () movex = 1; movey = 0; - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent - { - X = win.Frame.X + movex, - Y = win.Frame.Y + movey, - Flags = MouseFlags.Button1Pressed - | MouseFlags.ReportMousePosition - } - ) - ); + Application.OnMouseEvent (new MouseEvent + { + X = win.Frame.X + movex, + Y = win.Frame.Y + movey, + Flags = MouseFlags.Button1Pressed + | MouseFlags.ReportMousePosition + }); Assert.Equal (win.Border, Application.MouseGrabView); } @@ -1087,17 +1063,13 @@ public void Mouse_Drag_On_Top_With_Superview_Not_Null () movex = 0; movey = -1; - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent - { - X = win.Frame.X + movex, - Y = win.Frame.Y + movey, - Flags = MouseFlags.Button1Pressed - | MouseFlags.ReportMousePosition - } - ) - ); + Application.OnMouseEvent (new MouseEvent + { + X = win.Frame.X + movex, + Y = win.Frame.Y + movey, + Flags = MouseFlags.Button1Pressed + | MouseFlags.ReportMousePosition + }); Assert.Equal (win.Border, Application.MouseGrabView); } @@ -1116,15 +1088,11 @@ public void Mouse_Drag_On_Top_With_Superview_Not_Null () movex = 0; movey = 0; - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent - { - X = win.Frame.X + movex, Y = win.Frame.Y + movey, - Flags = MouseFlags.Button1Released - } - ) - ); + Application.OnMouseEvent (new MouseEvent + { + X = win.Frame.X + movex, Y = win.Frame.Y + movey, + Flags = MouseFlags.Button1Released + }); Assert.Null (Application.MouseGrabView); } @@ -1427,25 +1395,11 @@ public void Toplevel_Inside_ScrollView_MouseGrabView () _output ); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 6, Y = 6, Flags = MouseFlags.Button1Pressed } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 6, Y = 6, Flags = MouseFlags.Button1Pressed }); Assert.Equal (win.Border, Application.MouseGrabView); Assert.Equal (new (3, 3, 194, 94), win.Frame); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent - { - X = 9, - Y = 9, - Flags = MouseFlags.Button1Pressed - | MouseFlags.ReportMousePosition - } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 9, Y = 9, Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition }); Assert.Equal (win.Border, Application.MouseGrabView); top.SetNeedsLayout (); top.LayoutSubviews (); @@ -1473,17 +1427,13 @@ public void Toplevel_Inside_ScrollView_MouseGrabView () _output ); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent - { - X = 5, - Y = 5, - Flags = MouseFlags.Button1Pressed - | MouseFlags.ReportMousePosition - } - ) - ); + Application.OnMouseEvent (new MouseEvent + { + X = 5, + Y = 5, + Flags = MouseFlags.Button1Pressed + | MouseFlags.ReportMousePosition + }); Assert.Equal (win.Border, Application.MouseGrabView); top.SetNeedsLayout (); top.LayoutSubviews (); @@ -1511,19 +1461,11 @@ public void Toplevel_Inside_ScrollView_MouseGrabView () _output ); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 5, Y = 5, Flags = MouseFlags.Button1Released } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 5, Y = 5, Flags = MouseFlags.Button1Released }); // ScrollView always grab the mouse when the container's subview OnMouseEnter don't want grab the mouse Assert.Equal (scrollView, Application.MouseGrabView); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 4, Y = 4, Flags = MouseFlags.ReportMousePosition } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 4, Y = 4, Flags = MouseFlags.ReportMousePosition }); Assert.Equal (scrollView, Application.MouseGrabView); } @@ -1551,25 +1493,17 @@ public void Window_Bounds_Bigger_Than_Driver_Cols_And_Rows_Allow_Drag_Beyond_Lef Assert.Null (Application.MouseGrabView); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Pressed } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Pressed }); Assert.Equal (window.Border, Application.MouseGrabView); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent - { - X = -11, - Y = -4, - Flags = MouseFlags.Button1Pressed - | MouseFlags.ReportMousePosition - } - ) - ); + Application.OnMouseEvent (new MouseEvent + { + X = -11, + Y = -4, + Flags = MouseFlags.Button1Pressed + | MouseFlags.ReportMousePosition + }); Application.Refresh (); Assert.Equal (new Rectangle (0, 0, 40, 10), top.Frame); @@ -1587,17 +1521,13 @@ public void Window_Bounds_Bigger_Than_Driver_Cols_And_Rows_Allow_Drag_Beyond_Lef // Changes Top size to same size as Dialog more menu and scroll bar ((FakeDriver)Application.Driver).SetBufferSize (20, 3); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent - { - X = -1, - Y = -1, - Flags = MouseFlags.Button1Pressed - | MouseFlags.ReportMousePosition - } - ) - ); + Application.OnMouseEvent (new MouseEvent + { + X = -1, + Y = -1, + Flags = MouseFlags.Button1Pressed + | MouseFlags.ReportMousePosition + }); Application.Refresh (); Assert.Equal (new Rectangle (0, 0, 20, 3), top.Frame); @@ -1615,17 +1545,13 @@ public void Window_Bounds_Bigger_Than_Driver_Cols_And_Rows_Allow_Drag_Beyond_Lef // Changes Top size smaller than Dialog size ((FakeDriver)Application.Driver).SetBufferSize (19, 2); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent - { - X = -1, - Y = -1, - Flags = MouseFlags.Button1Pressed - | MouseFlags.ReportMousePosition - } - ) - ); + Application.OnMouseEvent (new MouseEvent + { + X = -1, + Y = -1, + Flags = MouseFlags.Button1Pressed + | MouseFlags.ReportMousePosition + }); Application.Refresh (); Assert.Equal (new Rectangle (0, 0, 19, 2), top.Frame); @@ -1639,17 +1565,13 @@ public void Window_Bounds_Bigger_Than_Driver_Cols_And_Rows_Allow_Drag_Beyond_Lef _output ); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent - { - X = 18, - Y = 1, - Flags = MouseFlags.Button1Pressed - | MouseFlags.ReportMousePosition - } - ) - ); + Application.OnMouseEvent (new MouseEvent + { + X = 18, + Y = 1, + Flags = MouseFlags.Button1Pressed + | MouseFlags.ReportMousePosition + }); Application.Refresh (); Assert.Equal (new Rectangle (0, 0, 19, 2), top.Frame); @@ -1662,17 +1584,13 @@ public void Window_Bounds_Bigger_Than_Driver_Cols_And_Rows_Allow_Drag_Beyond_Lef ); // On a real app we can't go beyond the SuperView bounds - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent - { - X = 19, - Y = 2, - Flags = MouseFlags.Button1Pressed - | MouseFlags.ReportMousePosition - } - ) - ); + Application.OnMouseEvent (new MouseEvent + { + X = 19, + Y = 2, + Flags = MouseFlags.Button1Pressed + | MouseFlags.ReportMousePosition + }); Application.Refresh (); Assert.Equal (new Rectangle (0, 0, 19, 2), top.Frame); @@ -1717,11 +1635,7 @@ public void Modal_As_Top_Will_Drag_Cleanly () _output ); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Pressed } - ) - ); + Application.OnMouseEvent (new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Pressed }); var firstIteration = false; Application.RunIteration (ref rs, ref firstIteration); @@ -1737,17 +1651,13 @@ public void Modal_As_Top_Will_Drag_Cleanly () _output ); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent - { - X = 1, - Y = 1, - Flags = MouseFlags.Button1Pressed - | MouseFlags.ReportMousePosition - } - ) - ); + Application.OnMouseEvent (new MouseEvent + { + X = 1, + Y = 1, + Flags = MouseFlags.Button1Pressed + | MouseFlags.ReportMousePosition + }); firstIteration = false; Application.RunIteration (ref rs, ref firstIteration); @@ -1868,11 +1778,7 @@ void OnDrawContentComplete (object sender, DrawEventArgs e) @$" ┌──────────────────┐ │ ┌─────────────┐ │ -│ │{ - CM.Glyphs.LeftBracket -} Popup { - CM.Glyphs.RightBracket -} │ │ +│ │{CM.Glyphs.LeftBracket} Popup {CM.Glyphs.RightBracket} │ │ │ │ │ │ │ │ │ │ │ │ │ │ @@ -1893,11 +1799,7 @@ void OnDrawContentComplete (object sender, DrawEventArgs e) _output ); - Application.OnMouseEvent ( - new MouseEventEventArgs ( - new MouseEvent { X = 5, Y = 2, Flags = MouseFlags.Button1Clicked } - ) - ); + Application.OnMouseEvent (new () { X = 5, Y = 2, Flags = MouseFlags.Button1Clicked }); Application.Top.Draw (); var firstIteration = false; @@ -1907,11 +1809,7 @@ void OnDrawContentComplete (object sender, DrawEventArgs e) @$" ┌──────────────────┐ │ ┌─────────────┐ │ -│ │{ - CM.Glyphs.LeftBracket -} Popup { - CM.Glyphs.RightBracket -} │ │ +│ │{CM.Glyphs.LeftBracket} Popup {CM.Glyphs.RightBracket} │ │ │┌────────────────┐│ ││viewAddedToTop ││ ││ ││ diff --git a/UnitTests/Views/TreeTableSourceTests.cs b/UnitTests/Views/TreeTableSourceTests.cs index b6708f1b31..f8db3a53c3 100644 --- a/UnitTests/Views/TreeTableSourceTests.cs +++ b/UnitTests/Views/TreeTableSourceTests.cs @@ -108,7 +108,7 @@ public void TestTreeTableSource_BasicExpanding_WithMouse () Assert.Equal (0, tv.SelectedRow); Assert.Equal (0, tv.SelectedColumn); - Assert.True (tv.OnMouseEvent (new MouseEvent { X = 2, Y = 2, Flags = MouseFlags.Button1Clicked })); + Assert.True (tv.NewMouseEvent (new MouseEvent { X = 2, Y = 2, Flags = MouseFlags.Button1Clicked })); tv.Draw (); @@ -125,15 +125,15 @@ public void TestTreeTableSource_BasicExpanding_WithMouse () TestHelpers.AssertDriverContentsAre (expected, _output); // Clicking to the right/left of the expand/collapse does nothing - tv.OnMouseEvent (new MouseEvent { X = 3, Y = 2, Flags = MouseFlags.Button1Clicked }); + tv.NewMouseEvent (new MouseEvent { X = 3, Y = 2, Flags = MouseFlags.Button1Clicked }); tv.Draw (); TestHelpers.AssertDriverContentsAre (expected, _output); - tv.OnMouseEvent (new MouseEvent { X = 1, Y = 2, Flags = MouseFlags.Button1Clicked }); + tv.NewMouseEvent (new MouseEvent { X = 1, Y = 2, Flags = MouseFlags.Button1Clicked }); tv.Draw (); TestHelpers.AssertDriverContentsAre (expected, _output); // Clicking on the + again should collapse - tv.OnMouseEvent (new MouseEvent { X = 2, Y = 2, Flags = MouseFlags.Button1Clicked }); + tv.NewMouseEvent (new MouseEvent { X = 2, Y = 2, Flags = MouseFlags.Button1Clicked }); tv.Draw (); expected = From e1a2793c5cf2f5a20fd5447615c4d6e08d0ccb6c Mon Sep 17 00:00:00 2001 From: Tig Date: Thu, 4 Apr 2024 19:34:39 -0400 Subject: [PATCH 25/32] Fixed fragile toplevel drag unit tests --- UnitTests/Application/ApplicationTests.cs | 71 +------ UnitTests/Views/OverlappedTests.cs | 63 +------ UnitTests/Views/ToplevelTests.cs | 215 +--------------------- 3 files changed, 12 insertions(+), 337 deletions(-) diff --git a/UnitTests/Application/ApplicationTests.cs b/UnitTests/Application/ApplicationTests.cs index 9569c99b79..779c127254 100644 --- a/UnitTests/Application/ApplicationTests.cs +++ b/UnitTests/Application/ApplicationTests.cs @@ -812,77 +812,16 @@ public void Run_A_Modal_Toplevel_Refresh_Background_On_Moving () ((FakeDriver)Application.Driver).SetBufferSize (10, 10); RunState rs = Application.Begin (w); - TestHelpers.AssertDriverContentsWithFrameAre ( - @" -┌───┐ -│ │ -│ │ -│ │ -└───┘", - _output - ); - - Attribute [] attributes = - { - // 0 - new (ColorName.White, ColorName.Black), - - // 1 - Colors.ColorSchemes ["Base"].Normal - }; - - TestHelpers.AssertDriverAttributesAre ( - @" -1111100000 -1111100000 -1111100000 -1111100000 -1111100000 -", - null, - attributes - ); - - // TODO: In PR #2920 this breaks because the mouse is not grabbed anymore. - // TODO: Move the mouse grap/drag mode from Toplevel to Border. + // Don't use visuals to test as style of border can change over time. + Assert.Equal (new Point (0, 0), w.Frame.Location); + Application.OnMouseEvent (new () { X = 0, Y = 0, Flags = MouseFlags.Button1Pressed }); Assert.Equal (w.Border, Application.MouseGrabView); + Assert.Equal (new Point (0,0), w.Frame.Location); // Move down and to the right. Application.OnMouseEvent (new () { X = 1, Y = 1, Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition }); - Application.Refresh (); - - TestHelpers.AssertDriverContentsWithFrameAre ( - @" - ┌───┐ - │ │ - │ │ - │ │ - └───┘", - _output - ); - - attributes = new [] - { - // 0 - new (ColorName.White, ColorName.Black), - - // 1 - Colors.ColorSchemes ["Base"].Normal - }; - - TestHelpers.AssertDriverAttributesAre ( - @" -0000000000 -0111110000 -0111110000 -0111110000 -0111110000 -0111110000 -", - null, - attributes - ); + Assert.Equal (new Point (1, 1), w.Frame.Location); Application.End (rs); w.Dispose (); diff --git a/UnitTests/Views/OverlappedTests.cs b/UnitTests/Views/OverlappedTests.cs index 0e66eb74cd..0283a73bbd 100644 --- a/UnitTests/Views/OverlappedTests.cs +++ b/UnitTests/Views/OverlappedTests.cs @@ -909,40 +909,8 @@ public void Visible_False_Does_Not_Clear () Assert.Equal (win2, Application.Current); Assert.Equal (win1, rsWin1.Toplevel); - TestHelpers.AssertDriverContentsWithFrameAre ( - @" - ┌───┐ - │ │ - │ │ - │ │ - └───┘", - _output - ); - - Attribute [] attributes = - { - // 0 - Colors.ColorSchemes ["TopLevel"].Normal, - - // 1 - Colors.ColorSchemes ["Base"].Normal - }; - - TestHelpers.AssertDriverAttributesAre ( - @" -0000000000 -0111110000 -0111110000 -0111110000 -0111110000 -0111110000 -0000000000 -0000000000 -0000000000 -0000000000", - null, - attributes - ); + // Tests that rely on visuals are too fragile. If border style changes they break. + // Instead we should just rely on the test above. Application.OnMouseEvent (new MouseEvent { X = 1, Y = 1, Flags = MouseFlags.Button1Pressed }); Assert.Equal (win2.Border, Application.MouseGrabView); @@ -973,31 +941,8 @@ Colors.ColorSchemes ["Base"].Normal Assert.Equal (win2, Application.Current); Assert.Equal (win1, rsWin1.Toplevel); - TestHelpers.AssertDriverContentsWithFrameAre ( - @" - ┌───┐ - │ │ - │ │ - │ │ - └───┘", - _output - ); - - TestHelpers.AssertDriverAttributesAre ( - @" -0000000000 -0000000000 -0011111000 -0011111000 -0011111000 -0011111000 -0011111000 -0000000000 -0000000000 -0000000000", - null, - attributes - ); + // Tests that rely on visuals are too fragile. If border style changes they break. + // Instead we should just rely on the test above. // This will end the win2 and not the overlapped Application.End (rsOverlapped); diff --git a/UnitTests/Views/ToplevelTests.cs b/UnitTests/Views/ToplevelTests.cs index 4dfce26ece..601c5925c4 100644 --- a/UnitTests/Views/ToplevelTests.cs +++ b/UnitTests/Views/ToplevelTests.cs @@ -875,18 +875,7 @@ public void Mouse_Drag_On_Top_With_Superview_Null () } else if (iterations == 1) { - TestHelpers.AssertDriverContentsWithFrameAre ( - @" -┌─────────────┐ -│ │ -│ ┌────────┐ │ -│ │Hello │ │ -│ └────────┘ │ -│ │ -└─────────────┘ -", - _output - ); + Assert.Equal(new Point(2,2), Application.Current.Frame.Location); } else if (iterations == 2) { @@ -918,18 +907,7 @@ public void Mouse_Drag_On_Top_With_Superview_Null () else if (iterations == 4) { Assert.Equal (Application.Current.Border, Application.MouseGrabView); - - TestHelpers.AssertDriverContentsWithFrameAre ( - @" -┌─────────────┐ -│ │ -│┌────────┐ │ -││Hello │ │ -│└────────┘ │ -│ │ -└─────────────┘", - _output - ); + Assert.Equal (new Point (1, 2), Application.Current.Frame.Location); Assert.Equal (Application.Current.Border, Application.MouseGrabView); } @@ -953,18 +931,8 @@ public void Mouse_Drag_On_Top_With_Superview_Null () else if (iterations == 6) { Assert.Equal (Application.Current.Border, Application.MouseGrabView); + Assert.Equal (new Point (1, 1), Application.Current.Frame.Location); - TestHelpers.AssertDriverContentsWithFrameAre ( - @" -┌─────────────┐ -│┌────────┐ │ -││Hello │ │ -│└────────┘ │ -│ │ -│ │ -└─────────────┘", - _output - ); Assert.Equal (Application.Current.Border, Application.MouseGrabView); Assert.Equal (new Rectangle (1, 1, 10, 3), Application.Current.Frame); @@ -1374,26 +1342,6 @@ public void Toplevel_Inside_ScrollView_MouseGrabView () Assert.Equal (new (0, 0, 200, 100), scrollView.Subviews [0].Frame); Assert.Equal (new (3, 3, 194, 94), win.Frame); - TestHelpers.AssertDriverContentsWithFrameAre ( - @" - ▲ - ┬ - │ - ┌───────────────────────────────────┴ - │ ░ - │ ░ - │ ░ - │ ░ - │ ░ - │ ░ - │ ░ - │ ░ - │ ░ - │ ░ - │ ▼ - ◄├──────┤░░░░░░░░░░░░░░░░░░░░░░░░░░░░░► ", - _output - ); Application.OnMouseEvent (new MouseEvent { X = 6, Y = 6, Flags = MouseFlags.Button1Pressed }); Assert.Equal (win.Border, Application.MouseGrabView); @@ -1406,27 +1354,6 @@ public void Toplevel_Inside_ScrollView_MouseGrabView () Assert.Equal (new Rectangle (6, 6, 191, 91), win.Frame); Application.Refresh (); - TestHelpers.AssertDriverContentsWithFrameAre ( - @" - ▲ - ┬ - │ - ┴ - ░ - ░ - ┌────────────────────────────────░ - │ ░ - │ ░ - │ ░ - │ ░ - │ ░ - │ ░ - │ ░ - │ ▼ - ◄├──────┤░░░░░░░░░░░░░░░░░░░░░░░░░░░░░► ", - _output - ); - Application.OnMouseEvent (new MouseEvent { X = 5, @@ -1440,27 +1367,6 @@ public void Toplevel_Inside_ScrollView_MouseGrabView () Assert.Equal (new Rectangle (2, 2, 195, 95), win.Frame); Application.Refresh (); - TestHelpers.AssertDriverContentsWithFrameAre ( - @" - ▲ - ┬ - ┌────────────────────────────────────│ - │ ┴ - │ ░ - │ ░ - │ ░ - │ ░ - │ ░ - │ ░ - │ ░ - │ ░ - │ ░ - │ ░ - │ ▼ - ◄├──────┤░░░░░░░░░░░░░░░░░░░░░░░░░░░░░► ", - _output - ); - Application.OnMouseEvent (new MouseEvent { X = 5, Y = 5, Flags = MouseFlags.Button1Released }); // ScrollView always grab the mouse when the container's subview OnMouseEnter don't want grab the mouse Assert.Equal (scrollView, Application.MouseGrabView); @@ -1482,15 +1388,6 @@ public void Window_Bounds_Bigger_Than_Driver_Cols_And_Rows_Allow_Drag_Beyond_Lef Assert.Equal (new Rectangle (0, 0, 40, 10), top.Frame); Assert.Equal (new Rectangle (0, 0, 20, 3), window.Frame); - TestHelpers.AssertDriverContentsWithFrameAre ( - @" -┌──────────────────┐ -│ │ -└──────────────────┘ -", - _output - ); - Assert.Null (Application.MouseGrabView); Application.OnMouseEvent (new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Pressed }); @@ -1509,15 +1406,6 @@ public void Window_Bounds_Bigger_Than_Driver_Cols_And_Rows_Allow_Drag_Beyond_Lef Assert.Equal (new Rectangle (0, 0, 40, 10), top.Frame); Assert.Equal (new Rectangle (0, 0, 20, 3), window.Frame); - TestHelpers.AssertDriverContentsWithFrameAre ( - @" -┌──────────────────┐ -│ │ -└──────────────────┘ -", - _output - ); - // Changes Top size to same size as Dialog more menu and scroll bar ((FakeDriver)Application.Driver).SetBufferSize (20, 3); @@ -1533,15 +1421,6 @@ public void Window_Bounds_Bigger_Than_Driver_Cols_And_Rows_Allow_Drag_Beyond_Lef Assert.Equal (new Rectangle (0, 0, 20, 3), top.Frame); Assert.Equal (new Rectangle (0, 0, 20, 3), window.Frame); - TestHelpers.AssertDriverContentsWithFrameAre ( - @" -┌──────────────────┐ -│ │ -└──────────────────┘ -", - _output - ); - // Changes Top size smaller than Dialog size ((FakeDriver)Application.Driver).SetBufferSize (19, 2); @@ -1557,14 +1436,6 @@ public void Window_Bounds_Bigger_Than_Driver_Cols_And_Rows_Allow_Drag_Beyond_Lef Assert.Equal (new Rectangle (0, 0, 19, 2), top.Frame); Assert.Equal (new Rectangle (-1, 0, 20, 3), window.Frame); - TestHelpers.AssertDriverContentsWithFrameAre ( - @" -──────────────────┐ - │ -", - _output - ); - Application.OnMouseEvent (new MouseEvent { X = 18, @@ -1577,12 +1448,6 @@ public void Window_Bounds_Bigger_Than_Driver_Cols_And_Rows_Allow_Drag_Beyond_Lef Assert.Equal (new Rectangle (0, 0, 19, 2), top.Frame); Assert.Equal (new Rectangle (18, 1, 20, 3), window.Frame); - TestHelpers.AssertDriverContentsWithFrameAre ( - @" - ┌", - _output - ); - // On a real app we can't go beyond the SuperView bounds Application.OnMouseEvent (new MouseEvent { @@ -1627,14 +1492,6 @@ public void Modal_As_Top_Will_Drag_Cleanly () Assert.Null (Application.MouseGrabView); Assert.Equal (new Rectangle (0, 0, 10, 3), window.Frame); - TestHelpers.AssertDriverContentsWithFrameAre ( - @" -┌────────┐ -│ Test │ -└────────┘", - _output - ); - Application.OnMouseEvent (new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1Pressed }); var firstIteration = false; @@ -1643,14 +1500,6 @@ public void Modal_As_Top_Will_Drag_Cleanly () Assert.Equal (new Rectangle (0, 0, 10, 3), window.Frame); - TestHelpers.AssertDriverContentsWithFrameAre ( - @" -┌────────┐ -│ Test │ -└────────┘", - _output - ); - Application.OnMouseEvent (new MouseEvent { X = 1, @@ -1664,14 +1513,6 @@ public void Modal_As_Top_Will_Drag_Cleanly () Assert.Equal (window.Border, Application.MouseGrabView); Assert.Equal (new Rectangle (1, 1, 10, 3), window.Frame); - TestHelpers.AssertDriverContentsWithFrameAre ( - @" - ┌────────┐ - │ Test │ - └────────┘", - _output - ); - Application.End (rs); } @@ -1706,31 +1547,6 @@ public void Draw_A_Top_Subview_On_A_Window () Assert.Equal (new Rectangle (0, 0, 20, 20), win.Frame); - TestHelpers.AssertDriverContentsWithFrameAre ( - @" -┌──────────────────┐ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────┘", - _output - ); - var btnPopup = new Button { Text = "Popup" }; var testWindow = new Window { X = 2, Y = 1, Width = 15, Height = 10 }; testWindow.Add (btnPopup); @@ -1774,31 +1590,6 @@ void OnDrawContentComplete (object sender, DrawEventArgs e) Assert.Equal (new Rectangle (2, 1, 15, 10), testWindow.Frame); - TestHelpers.AssertDriverContentsWithFrameAre ( - @$" -┌──────────────────┐ -│ ┌─────────────┐ │ -│ │{CM.Glyphs.LeftBracket} Popup {CM.Glyphs.RightBracket} │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ └─────────────┘ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────┘", - _output - ); - Application.OnMouseEvent (new () { X = 5, Y = 2, Flags = MouseFlags.Button1Clicked }); Application.Top.Draw (); From dceed59a5fae2aaaa24d48e56c80683e183951b7 Mon Sep 17 00:00:00 2001 From: Tig Date: Fri, 5 Apr 2024 12:27:04 -0400 Subject: [PATCH 26/32] Fixed more unit tests --- UnitTests/Text/AutocompleteTests.cs | 2 +- UnitTests/Views/StatusBarTests.cs | 2 +- UnitTests/Views/TableViewTests.cs | 14 +++++----- UnitTests/Views/TextFieldTests.cs | 16 +++++------ UnitTests/Views/TextValidateFieldTests.cs | 2 +- UnitTests/Views/TextViewTests.cs | 34 +++++++++++------------ UnitTests/Views/ToplevelTests.cs | 6 ++-- UnitTests/Views/TreeViewTests.cs | 8 +++--- 8 files changed, 42 insertions(+), 42 deletions(-) diff --git a/UnitTests/Text/AutocompleteTests.cs b/UnitTests/Text/AutocompleteTests.cs index e3cf22218a..6072d4126e 100644 --- a/UnitTests/Text/AutocompleteTests.cs +++ b/UnitTests/Text/AutocompleteTests.cs @@ -50,7 +50,7 @@ This a long line and against TextView. } Assert.True ( - tv.OnMouseEvent ( + tv.NewMouseEvent ( new MouseEvent { X = 6, Y = 0, Flags = MouseFlags.Button1Pressed } ) ); diff --git a/UnitTests/Views/StatusBarTests.cs b/UnitTests/Views/StatusBarTests.cs index b2a9dfdc3a..1c94dec0ec 100644 --- a/UnitTests/Views/StatusBarTests.cs +++ b/UnitTests/Views/StatusBarTests.cs @@ -163,7 +163,7 @@ public void Run_Action_With_Key_And_Mouse () { Assert.Equal ("Quiting...", msg); msg = ""; - sb.OnMouseEvent (new MouseEvent { X = 1, Y = 24, Flags = MouseFlags.Button1Clicked }); + sb.NewMouseEvent (new MouseEvent { X = 1, Y = 24, Flags = MouseFlags.Button1Clicked }); } else { diff --git a/UnitTests/Views/TableViewTests.cs b/UnitTests/Views/TableViewTests.cs index 574ad85a83..4706c695b7 100644 --- a/UnitTests/Views/TableViewTests.cs +++ b/UnitTests/Views/TableViewTests.cs @@ -2196,7 +2196,7 @@ public void TestControlClick_MultiSelect_ThreeRowTable_FullRowSelect () tv.MultiSelect = true; // Clicking in bottom row - tv.OnMouseEvent ( + tv.NewMouseEvent ( new MouseEvent { X = 1, Y = 4, Flags = MouseFlags.Button1Clicked } ); @@ -2204,7 +2204,7 @@ public void TestControlClick_MultiSelect_ThreeRowTable_FullRowSelect () Assert.Equal (2, tv.SelectedRow); // shift clicking top row - tv.OnMouseEvent ( + tv.NewMouseEvent ( new MouseEvent { X = 1, Y = 2, Flags = MouseFlags.Button1Clicked | MouseFlags.ButtonCtrl } ); @@ -2268,7 +2268,7 @@ public void TestFullRowSelect_AlwaysUseNormalColorForVerticalCellLines () tv.Style.AlwaysUseNormalColorForVerticalCellLines = true; // Clicking in bottom row - tv.OnMouseEvent ( + tv.NewMouseEvent ( new MouseEvent { X = 1, Y = 4, Flags = MouseFlags.Button1Clicked } ); @@ -2323,7 +2323,7 @@ public void TestFullRowSelect_SelectionColorDoesNotStop_WhenShowVerticalCellLine tv.Style.ShowVerticalHeaderLines = false; // Clicking in bottom row - tv.OnMouseEvent ( + tv.NewMouseEvent ( new MouseEvent { X = 1, Y = 4, Flags = MouseFlags.Button1Clicked } ); @@ -2376,7 +2376,7 @@ public void TestFullRowSelect_SelectionColorStopsAtTableEdge_WithCellLines () tv.Style.ShowHorizontalBottomline = true; // Clicking in bottom row - tv.OnMouseEvent ( + tv.NewMouseEvent ( new MouseEvent { X = 1, Y = 4, Flags = MouseFlags.Button1Clicked } ); @@ -2557,7 +2557,7 @@ public void TestShiftClick_MultiSelect_TwoRowTable_FullRowSelect () tv.MultiSelect = true; // Clicking in bottom row - tv.OnMouseEvent ( + tv.NewMouseEvent ( new MouseEvent { X = 1, Y = 3, Flags = MouseFlags.Button1Clicked } ); @@ -2565,7 +2565,7 @@ public void TestShiftClick_MultiSelect_TwoRowTable_FullRowSelect () Assert.Equal (1, tv.SelectedRow); // shift clicking top row - tv.OnMouseEvent ( + tv.NewMouseEvent ( new MouseEvent { X = 1, Y = 2, Flags = MouseFlags.Button1Clicked | MouseFlags.ButtonShift } ); diff --git a/UnitTests/Views/TextFieldTests.cs b/UnitTests/Views/TextFieldTests.cs index 7794837edd..5c3b3bd681 100644 --- a/UnitTests/Views/TextFieldTests.cs +++ b/UnitTests/Views/TextFieldTests.cs @@ -122,7 +122,7 @@ public void CanFocus_False_Wont_Focus_With_Mouse () Assert.False (fv.CanFocus); Assert.False (fv.HasFocus); - tf.OnMouseEvent ( + tf.NewMouseEvent ( new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1DoubleClicked } ); @@ -136,7 +136,7 @@ public void CanFocus_False_Wont_Focus_With_Mouse () fv.CanFocus = true; tf.CanFocus = true; - tf.OnMouseEvent ( + tf.NewMouseEvent ( new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1DoubleClicked } ); @@ -148,7 +148,7 @@ public void CanFocus_False_Wont_Focus_With_Mouse () fv.CanFocus = false; - tf.OnMouseEvent ( + tf.NewMouseEvent ( new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1DoubleClicked } ); @@ -484,7 +484,7 @@ public void DeleteSelectedText_InsertText_DeleteCharLeft_DeleteCharRight_Cut () tf.Text = "Les Misérables movie."; Assert.True ( - tf.OnMouseEvent ( + tf.NewMouseEvent ( new MouseEvent { X = 7, Y = 1, Flags = MouseFlags.Button1DoubleClicked, View = tf } ) ); @@ -1152,12 +1152,12 @@ public void SpaceHandling () var ev = new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1DoubleClicked }; - tf.OnMouseEvent (ev); + tf.NewMouseEvent (ev); Assert.Equal (1, tf.SelectedLength); ev = new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1DoubleClicked }; - tf.OnMouseEvent (ev); + tf.NewMouseEvent (ev); Assert.Equal (1, tf.SelectedLength); } @@ -1537,14 +1537,14 @@ public void WordBackward_WordForward_SelectedText_With_Accent () Assert.Equal ("m", runes [idx].ToString ()); Assert.True ( - tf.OnMouseEvent ( + tf.NewMouseEvent ( new MouseEvent { X = idx, Y = 1, Flags = MouseFlags.Button1DoubleClicked, View = tf } ) ); Assert.Equal ("movie.", tf.SelectedText); Assert.True ( - tf.OnMouseEvent ( + tf.NewMouseEvent ( new MouseEvent { X = idx + 1, Y = 1, Flags = MouseFlags.Button1DoubleClicked, View = tf } ) ); diff --git a/UnitTests/Views/TextValidateFieldTests.cs b/UnitTests/Views/TextValidateFieldTests.cs index 981c83a279..de5f6274c5 100644 --- a/UnitTests/Views/TextValidateFieldTests.cs +++ b/UnitTests/Views/TextValidateFieldTests.cs @@ -322,7 +322,7 @@ public void MouseClick_Right_X_Greater_Than_Text_Width_Goes_To_Last_Editable_Pos Assert.False (field.IsValid); Assert.Equal ("--(1 )--", field.Provider.Text); - field.OnMouseEvent (new MouseEvent { X = 25, Flags = MouseFlags.Button1Pressed }); + field.NewMouseEvent (new MouseEvent { X = 25, Flags = MouseFlags.Button1Pressed }); field.NewKeyDownEvent (Key.D1); diff --git a/UnitTests/Views/TextViewTests.cs b/UnitTests/Views/TextViewTests.cs index 2eb28a06dd..7f35dd4ce4 100644 --- a/UnitTests/Views/TextViewTests.cs +++ b/UnitTests/Views/TextViewTests.cs @@ -160,7 +160,7 @@ public void CanFocus_False_Wont_Focus_With_Mouse () Assert.False (fv.CanFocus); Assert.False (fv.HasFocus); - tv.OnMouseEvent (new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1DoubleClicked }); + tv.NewMouseEvent (new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1DoubleClicked }); Assert.Empty (tv.SelectedText); Assert.False (tv.CanFocus); @@ -171,7 +171,7 @@ public void CanFocus_False_Wont_Focus_With_Mouse () Assert.Throws (() => tv.CanFocus = true); fv.CanFocus = true; tv.CanFocus = true; - tv.OnMouseEvent (new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1DoubleClicked }); + tv.NewMouseEvent (new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1DoubleClicked }); Assert.Equal ("some ", tv.SelectedText); Assert.True (tv.CanFocus); @@ -180,7 +180,7 @@ public void CanFocus_False_Wont_Focus_With_Mouse () Assert.True (fv.HasFocus); fv.CanFocus = false; - tv.OnMouseEvent (new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1DoubleClicked }); + tv.NewMouseEvent (new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1DoubleClicked }); Assert.Equal ("some ", tv.SelectedText); // Setting CanFocus to false don't change the SelectedText Assert.False (tv.CanFocus); @@ -1072,7 +1072,7 @@ public void DesiredCursorVisibility_Horizontal_Navigation () for (var i = 0; i < 12; i++) { - tv.OnMouseEvent (new MouseEvent { Flags = MouseFlags.WheeledRight }); + tv.NewMouseEvent (new MouseEvent { Flags = MouseFlags.WheeledRight }); tv.PositionCursor (); Assert.Equal (Math.Min (i + 1, 11), tv.LeftColumn); Assert.Equal (CursorVisibility.Invisible, tv.DesiredCursorVisibility); @@ -1080,7 +1080,7 @@ public void DesiredCursorVisibility_Horizontal_Navigation () for (var i = 11; i > 0; i--) { - tv.OnMouseEvent (new MouseEvent { Flags = MouseFlags.WheeledLeft }); + tv.NewMouseEvent (new MouseEvent { Flags = MouseFlags.WheeledLeft }); tv.PositionCursor (); Assert.Equal (i - 1, tv.LeftColumn); @@ -1115,7 +1115,7 @@ public void DesiredCursorVisibility_Vertical_Navigation () for (var i = 0; i < 12; i++) { - tv.OnMouseEvent (new MouseEvent { Flags = MouseFlags.WheeledDown }); + tv.NewMouseEvent (new MouseEvent { Flags = MouseFlags.WheeledDown }); tv.PositionCursor (); Assert.Equal (i + 1, tv.TopRow); Assert.Equal (CursorVisibility.Invisible, tv.DesiredCursorVisibility); @@ -1123,7 +1123,7 @@ public void DesiredCursorVisibility_Vertical_Navigation () for (var i = 12; i > 0; i--) { - tv.OnMouseEvent (new MouseEvent { Flags = MouseFlags.WheeledUp }); + tv.NewMouseEvent (new MouseEvent { Flags = MouseFlags.WheeledUp }); tv.PositionCursor (); Assert.Equal (i - 1, tv.TopRow); @@ -6788,7 +6788,7 @@ public void Mouse_Button_Shift_Preserves_Selection () Assert.Equal ("TAB to jump between text fields.", _textView.Text); Assert.True ( - _textView.OnMouseEvent ( + _textView.NewMouseEvent ( new MouseEvent { X = 12, Y = 0, Flags = MouseFlags.Button1Pressed | MouseFlags.ButtonShift } ) ); @@ -6798,7 +6798,7 @@ public void Mouse_Button_Shift_Preserves_Selection () Assert.True (_textView.Selecting); Assert.Equal ("TAB to jump ", _textView.SelectedText); - Assert.True (_textView.OnMouseEvent (new MouseEvent { X = 12, Y = 0, Flags = MouseFlags.Button1Clicked })); + Assert.True (_textView.NewMouseEvent (new MouseEvent { X = 12, Y = 0, Flags = MouseFlags.Button1Clicked })); Assert.Equal (0, _textView.SelectionStartRow); Assert.Equal (0, _textView.SelectionStartRow); Assert.Equal (new Point (12, 0), _textView.CursorPosition); @@ -6806,7 +6806,7 @@ public void Mouse_Button_Shift_Preserves_Selection () Assert.Equal ("TAB to jump ", _textView.SelectedText); Assert.True ( - _textView.OnMouseEvent ( + _textView.NewMouseEvent ( new MouseEvent { X = 19, Y = 0, Flags = MouseFlags.Button1Pressed | MouseFlags.ButtonShift } ) ); @@ -6816,7 +6816,7 @@ public void Mouse_Button_Shift_Preserves_Selection () Assert.True (_textView.Selecting); Assert.Equal ("TAB to jump between", _textView.SelectedText); - Assert.True (_textView.OnMouseEvent (new MouseEvent { X = 19, Y = 0, Flags = MouseFlags.Button1Clicked })); + Assert.True (_textView.NewMouseEvent (new MouseEvent { X = 19, Y = 0, Flags = MouseFlags.Button1Clicked })); Assert.Equal (0, _textView.SelectionStartRow); Assert.Equal (0, _textView.SelectionStartRow); Assert.Equal (new Point (19, 0), _textView.CursorPosition); @@ -6824,7 +6824,7 @@ public void Mouse_Button_Shift_Preserves_Selection () Assert.Equal ("TAB to jump between", _textView.SelectedText); Assert.True ( - _textView.OnMouseEvent ( + _textView.NewMouseEvent ( new MouseEvent { X = 24, Y = 0, Flags = MouseFlags.Button1Pressed | MouseFlags.ButtonShift } ) ); @@ -6834,14 +6834,14 @@ public void Mouse_Button_Shift_Preserves_Selection () Assert.True (_textView.Selecting); Assert.Equal ("TAB to jump between text", _textView.SelectedText); - Assert.True (_textView.OnMouseEvent (new MouseEvent { X = 24, Y = 0, Flags = MouseFlags.Button1Clicked })); + Assert.True (_textView.NewMouseEvent (new MouseEvent { X = 24, Y = 0, Flags = MouseFlags.Button1Clicked })); Assert.Equal (0, _textView.SelectionStartRow); Assert.Equal (0, _textView.SelectionStartRow); Assert.Equal (new Point (24, 0), _textView.CursorPosition); Assert.True (_textView.Selecting); Assert.Equal ("TAB to jump between text", _textView.SelectedText); - Assert.True (_textView.OnMouseEvent (new MouseEvent { X = 24, Y = 0, Flags = MouseFlags.Button1Pressed })); + Assert.True (_textView.NewMouseEvent (new MouseEvent { X = 24, Y = 0, Flags = MouseFlags.Button1Pressed })); Assert.Equal (0, _textView.SelectionStartRow); Assert.Equal (0, _textView.SelectionStartRow); Assert.Equal (new Point (24, 0), _textView.CursorPosition); @@ -7624,12 +7624,12 @@ public void TextView_SpaceHandling () var ev = new MouseEvent { X = 0, Y = 0, Flags = MouseFlags.Button1DoubleClicked }; - tv.OnMouseEvent (ev); + tv.NewMouseEvent (ev); Assert.Equal (1, tv.SelectedLength); ev = new MouseEvent { X = 1, Y = 0, Flags = MouseFlags.Button1DoubleClicked }; - tv.OnMouseEvent (ev); + tv.NewMouseEvent (ev); Assert.Equal (1, tv.SelectedLength); } @@ -7744,7 +7744,7 @@ This is the second line. _output ); - Assert.True (tv.OnMouseEvent (new MouseEvent { X = 0, Y = 3, Flags = MouseFlags.Button1Pressed })); + Assert.True (tv.NewMouseEvent (new MouseEvent { X = 0, Y = 3, Flags = MouseFlags.Button1Pressed })); tv.Draw (); Assert.Equal (new Point (0, 3), tv.CursorPosition); Assert.Equal (new Point (13, 0), cp); diff --git a/UnitTests/Views/ToplevelTests.cs b/UnitTests/Views/ToplevelTests.cs index 601c5925c4..8c9f270b82 100644 --- a/UnitTests/Views/ToplevelTests.cs +++ b/UnitTests/Views/ToplevelTests.cs @@ -382,12 +382,12 @@ public void Internal_Tests () Assert.Equal (new Rectangle (0, 1, 60, 15), win.Frame); //Assert.Null (Toplevel._dragPosition); - win.OnMouseEvent (new MouseEvent { X = 6, Y = 0, Flags = MouseFlags.Button1Pressed }); + win.NewMouseEvent (new MouseEvent { X = 6, Y = 0, Flags = MouseFlags.Button1Pressed }); // Assert.Equal (new Point (6, 0), Toplevel._dragPosition); - win.OnMouseEvent (new MouseEvent { X = 6, Y = 0, Flags = MouseFlags.Button1Released }); + win.NewMouseEvent (new MouseEvent { X = 6, Y = 0, Flags = MouseFlags.Button1Released }); //Assert.Null (Toplevel._dragPosition); win.CanFocus = false; - win.OnMouseEvent (new MouseEvent { X = 6, Y = 0, Flags = MouseFlags.Button1Pressed }); + win.NewMouseEvent (new MouseEvent { X = 6, Y = 0, Flags = MouseFlags.Button1Pressed }); //Assert.Null (Toplevel._dragPosition); } diff --git a/UnitTests/Views/TreeViewTests.cs b/UnitTests/Views/TreeViewTests.cs index 6a2805d40d..dfa4e1e3bd 100644 --- a/UnitTests/Views/TreeViewTests.cs +++ b/UnitTests/Views/TreeViewTests.cs @@ -453,7 +453,7 @@ public void ObjectActivationButton_DoubleClick () Assert.False (called); // double click triggers activation - tree.OnMouseEvent (new MouseEvent { Y = 0, Flags = MouseFlags.Button1DoubleClicked }); + tree.NewMouseEvent (new MouseEvent { Y = 0, Flags = MouseFlags.Button1DoubleClicked }); Assert.True (called); Assert.Same (f, activated); @@ -485,12 +485,12 @@ public void ObjectActivationButton_RightClick () Assert.False (called); // double click does nothing because we changed button binding to right click - tree.OnMouseEvent (new MouseEvent { Y = 1, Flags = MouseFlags.Button1DoubleClicked }); + tree.NewMouseEvent (new MouseEvent { Y = 1, Flags = MouseFlags.Button1DoubleClicked }); Assert.Null (activated); Assert.False (called); - tree.OnMouseEvent (new MouseEvent { Y = 1, Flags = MouseFlags.Button2Clicked }); + tree.NewMouseEvent (new MouseEvent { Y = 1, Flags = MouseFlags.Button2Clicked }); Assert.True (called); Assert.Same (car1, activated); @@ -522,7 +522,7 @@ public void ObjectActivationButton_SetToNull () Assert.False (called); // double click does nothing because we changed button to null - tree.OnMouseEvent (new MouseEvent { Y = 0, Flags = MouseFlags.Button1DoubleClicked }); + tree.NewMouseEvent (new MouseEvent { Y = 0, Flags = MouseFlags.Button1DoubleClicked }); Assert.False (called); Assert.Null (activated); From cca32726fc3c3082c63f1765270ac85af06963d9 Mon Sep 17 00:00:00 2001 From: Tig Date: Fri, 5 Apr 2024 17:25:23 -0400 Subject: [PATCH 27/32] Refactored API to support extensibilty... eg Hover (not implemented yet). --- Terminal.Gui/View/Adornment/Border.cs | 28 +-- Terminal.Gui/View/ViewMouse.cs | 277 ++++++++++++++++---------- Terminal.Gui/Views/Button.cs | 30 ++- Terminal.Gui/Views/CheckBox.cs | 2 +- Terminal.Gui/Views/ColorPicker.cs | 2 +- Terminal.Gui/Views/RadioGroup.cs | 2 +- UICatalog/Scenarios/Mouse.cs | 10 +- UnitTests/View/MouseTests.cs | 58 +++--- 8 files changed, 259 insertions(+), 150 deletions(-) diff --git a/Terminal.Gui/View/Adornment/Border.cs b/Terminal.Gui/View/Adornment/Border.cs index 8e32edde27..a45c3f7d2d 100644 --- a/Terminal.Gui/View/Adornment/Border.cs +++ b/Terminal.Gui/View/Adornment/Border.cs @@ -57,8 +57,8 @@ public Border (View parent) : base (parent) Application.GrabbingMouse += Application_GrabbingMouse; Application.UnGrabbingMouse += Application_UnGrabbingMouse; - EnablingHighlight += Border_EnablingHighlight; - DisablingHighlight += Border_DisablingHighlight; + HighlightStyle = HighlightStyle.Pressed; + Highlight += Border_Highlight; } #if SUBVIEW_BASED_BORDER @@ -192,17 +192,17 @@ public LineStyle LineStyle private LineStyle _savedHighlightLineStyle; - private void Border_EnablingHighlight (object sender, System.ComponentModel.CancelEventArgs e) + private void Border_Highlight (object sender, HighlightEventArgs e) { - _savedHighlightLineStyle = Parent?.BorderStyle ?? LineStyle; - LineStyle = LineStyle.Heavy; - Parent?.SetNeedsDisplay (); - e.Cancel = true; - } - - private void Border_DisablingHighlight (object sender, System.ComponentModel.CancelEventArgs e) - { - LineStyle = _savedHighlightLineStyle; + if (e.HighlightStyle == HighlightStyle) + { + _savedHighlightLineStyle = Parent?.BorderStyle ?? LineStyle; + LineStyle = LineStyle.Heavy; + } + else + { + LineStyle = _savedHighlightLineStyle; + } Parent?.SetNeedsDisplay (); e.Cancel = true; } @@ -242,7 +242,7 @@ protected internal override bool OnMouseEvent (MouseEvent mouseEvent) _startGrabPoint = new (mouseEvent.X + Frame.X, mouseEvent.Y + Frame.Y); _dragPosition = new (mouseEvent.X, mouseEvent.Y); Application.GrabMouse (this); - EnableHighlight (); + SetHighlight (HighlightStyle); } return true; @@ -286,7 +286,7 @@ out _ { _dragPosition = null; Application.UngrabMouse (); - DisableHighlight(); + SetHighlight (HighlightStyle.None); return true; } diff --git a/Terminal.Gui/View/ViewMouse.cs b/Terminal.Gui/View/ViewMouse.cs index 9f3dac4f28..944928c8c8 100644 --- a/Terminal.Gui/View/ViewMouse.cs +++ b/Terminal.Gui/View/ViewMouse.cs @@ -1,15 +1,51 @@ using System.ComponentModel; -using System.Diagnostics; namespace Terminal.Gui; +/// +/// Describes the highlight style of a view. +/// +[Flags] +public enum HighlightStyle +{ + /// + /// No highlight. + /// + None = 0, + + /// + /// The mouse is hovering over the view. + /// + Hover = 1, + + /// + /// The mouse is pressed within the . + /// + Pressed = 2, + + /// + /// The mouse is pressed but moved outside the . + /// + PressedOutside = 4 +} + +public class HighlightEventArgs : CancelEventArgs +{ + public HighlightEventArgs (HighlightStyle style) + { + HighlightStyle = style; + } + + public HighlightStyle HighlightStyle { get; } +} + public partial class View { /// /// Gets or sets whether the will be highlighted visually while the mouse button is /// pressed. /// - public bool HighlightOnPress { get; set; } + public HighlightStyle HighlightStyle { get; set; } /// Gets or sets whether the wants continuous button pressed events. public virtual bool WantContinuousButtonPressed { get; set; } @@ -93,9 +129,7 @@ protected internal virtual bool OnMouseLeave (MouseEvent mouseEvent) /// mouse buttons was clicked, it calls to process the click. /// /// - /// If is , the view will be highlighted when the mouse is - /// pressed. - /// See and for more information. + /// See and for more information. /// /// /// If is , the event @@ -124,18 +158,41 @@ protected internal virtual bool OnMouseLeave (MouseEvent mouseEvent) return mouseEvent.Handled = true; } - if ((HighlightOnPress || WantContinuousButtonPressed) && Highlight (mouseEvent)) + if (HighlightStyle != Gui.HighlightStyle.None || WantContinuousButtonPressed) { - Debug.Assert (mouseEvent.Handled); + if (HandlePressed (mouseEvent)) + { + return mouseEvent.Handled; + } + + if (HandleReleased (mouseEvent)) + { + return mouseEvent.Handled; + } - return mouseEvent.Handled; + if (HandleClicked (mouseEvent)) + { + return mouseEvent.Handled; + } } if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked) || mouseEvent.Flags.HasFlag (MouseFlags.Button2Clicked) || mouseEvent.Flags.HasFlag (MouseFlags.Button3Clicked) - || mouseEvent.Flags.HasFlag (MouseFlags.Button4Clicked)) + || mouseEvent.Flags.HasFlag (MouseFlags.Button4Clicked) + || mouseEvent.Flags.HasFlag (MouseFlags.Button1DoubleClicked) + || mouseEvent.Flags.HasFlag (MouseFlags.Button2DoubleClicked) + || mouseEvent.Flags.HasFlag (MouseFlags.Button3DoubleClicked) + || mouseEvent.Flags.HasFlag (MouseFlags.Button4DoubleClicked) + || mouseEvent.Flags.HasFlag (MouseFlags.Button1TripleClicked) + || mouseEvent.Flags.HasFlag (MouseFlags.Button2TripleClicked) + || mouseEvent.Flags.HasFlag (MouseFlags.Button3TripleClicked) + || mouseEvent.Flags.HasFlag (MouseFlags.Button4TripleClicked) + ) { + // If it's a click, and we didn't handle it, then we'll call OnMouseClick + // We get here if the view did not handle the mouse event via OnMouseEvent/MouseEvent and + // it did not handle the press/release/clicked events via HandlePress/HandleRelease/HandleClicked return OnMouseClick (new (mouseEvent)); } @@ -143,43 +200,18 @@ protected internal virtual bool OnMouseLeave (MouseEvent mouseEvent) } /// - /// Highlight the view when the mouse is pressed. + /// For cases where the view is grabbed and the mouse is clicked, this method handles the released event (typically + /// when or are set). /// /// /// - /// Set to to have the view highlighted when the mouse is - /// pressed. - /// - /// - /// Calls which fires the event. - /// - /// - /// Calls which fires the event. + /// Marked internal just to support unit tests /// /// /// /// , if the event was handled, otherwise. - private bool Highlight (MouseEvent mouseEvent) + private bool HandlePressed (MouseEvent mouseEvent) { - if (Application.MouseGrabView == this - && (mouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked) - || mouseEvent.Flags.HasFlag (MouseFlags.Button2Clicked) - || mouseEvent.Flags.HasFlag (MouseFlags.Button3Clicked) - || mouseEvent.Flags.HasFlag (MouseFlags.Button4Clicked))) - { - // We're grabbed. Clicked event comes after the last Release. This is our signal to ungrab - Application.UngrabMouse (); - DisableHighlight (); - - // If mouse is still in bounds, click - if (!WantContinuousButtonPressed && Bounds.Contains (mouseEvent.X, mouseEvent.Y)) - { - return OnMouseClick (new (mouseEvent)); - } - - return mouseEvent.Handled = true; - } - if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Pressed) || mouseEvent.Flags.HasFlag (MouseFlags.Button2Pressed) || mouseEvent.Flags.HasFlag (MouseFlags.Button3Pressed) @@ -199,11 +231,11 @@ private bool Highlight (MouseEvent mouseEvent) if (Bounds.Contains (mouseEvent.X, mouseEvent.Y)) { - EnableHighlight (); + SetHighlight (HighlightStyle.HasFlag(HighlightStyle.Pressed) ? HighlightStyle.Pressed : HighlightStyle.None); } else { - DisableHighlight (); + SetHighlight (HighlightStyle.HasFlag (HighlightStyle.PressedOutside) ? HighlightStyle.PressedOutside : HighlightStyle.None); } if (WantContinuousButtonPressed && Application.MouseGrabView == this) @@ -215,6 +247,20 @@ private bool Highlight (MouseEvent mouseEvent) return mouseEvent.Handled = true; } + return false; + } + + /// + /// For cases where the view is grabbed and the mouse is clicked, this method handles the released event (typically + /// when or are set). + /// + /// + /// Marked internal just to support unit tests + /// + /// + /// , if the event was handled, otherwise. + internal bool HandleReleased (MouseEvent mouseEvent) + { if (mouseEvent.Flags.HasFlag (MouseFlags.Button1Released) || mouseEvent.Flags.HasFlag (MouseFlags.Button2Released) || mouseEvent.Flags.HasFlag (MouseFlags.Button3Released) @@ -222,108 +268,129 @@ private bool Highlight (MouseEvent mouseEvent) { if (Application.MouseGrabView == this) { - DisableHighlight (); + SetHighlight (HighlightStyle.None); } return mouseEvent.Handled = true; } - return mouseEvent.Handled; + return false; } - [CanBeNull] - private ColorScheme _savedHighlightColorScheme; - /// - /// Enables the highlight for the view. Called from OnMouseEvent. + /// For cases where the view is grabbed and the mouse is clicked, this method handles the click event (typically + /// when or are set). /// - public void EnableHighlight () + /// + /// Marked internal just to support unit tests + /// + /// + /// , if the event was handled, otherwise. + internal bool HandleClicked (MouseEvent mouseEvent) { - if (OnEnablingHighlight () == true) - { - return; - } - - if (_savedHighlightColorScheme is null && ColorScheme is { }) + if (Application.MouseGrabView == this + && (mouseEvent.Flags.HasFlag (MouseFlags.Button1Clicked) + || mouseEvent.Flags.HasFlag (MouseFlags.Button2Clicked) + || mouseEvent.Flags.HasFlag (MouseFlags.Button3Clicked) + || mouseEvent.Flags.HasFlag (MouseFlags.Button4Clicked))) { - _savedHighlightColorScheme ??= ColorScheme; - - if (CanFocus) - { - // TODO: Make the inverted color configurable - var cs = new ColorScheme (ColorScheme) - { - // For Buttons etc... - Focus = new (ColorScheme.Normal.Foreground, ColorScheme.Focus.Background), + // We're grabbed. Clicked event comes after the last Release. This is our signal to ungrab + Application.UngrabMouse (); + SetHighlight (HighlightStyle.None); - // For Adornments - Normal = new (ColorScheme.Focus.Foreground, ColorScheme.Normal.Background) - }; - ColorScheme = cs; - } - else + // If mouse is still in bounds, click + if (!WantContinuousButtonPressed && Bounds.Contains (mouseEvent.X, mouseEvent.Y)) { - var cs = new ColorScheme (ColorScheme) - { - // For Buttons etc... that can't focus (like up/down). - Normal = new (ColorScheme.Focus.Background, ColorScheme.Normal.Foreground) - }; - ColorScheme = cs; + return OnMouseClick (new (mouseEvent)); } - } - } - /// - /// Fired when the view is highlighted. Set to - /// to implement a custom highlight scheme or prevent the view from being highlighted. - /// - public event EventHandler EnablingHighlight; - - /// - /// Called when the view is to be highlighted. - /// - /// , if the event was handled, otherwise. - protected virtual bool? OnEnablingHighlight () - { - CancelEventArgs args = new (); - EnablingHighlight?.Invoke (this, args); + return mouseEvent.Handled = true; + } - return args.Cancel; + return false; } + [CanBeNull] + private ColorScheme _savedHighlightColorScheme; + /// - /// Disables the highlight for the view. Called from OnMouseEvent. + /// Enables the highlight for the view when the mouse is pressed. Called from OnMouseEvent. /// - public void DisableHighlight () + /// + /// + /// Set to have the view highlighted based on the mouse. + /// + /// + /// Calls which fires the event. + /// + /// + /// Marked internal just to support unit tests + /// + /// + internal void SetHighlight (HighlightStyle style) { - if (OnDisablingHighlight () == true) + // Enable override via virtual method and/or event + if (OnHighlight (style) == true) { return; } - // Unhighlight - if (_savedHighlightColorScheme is { }) + if (style.HasFlag (HighlightStyle.Pressed) || style.HasFlag (HighlightStyle.PressedOutside)) + { + + if (_savedHighlightColorScheme is null && ColorScheme is { }) + { + _savedHighlightColorScheme ??= ColorScheme; + + if (CanFocus) + { + // TODO: Make the inverted color configurable + var cs = new ColorScheme (ColorScheme) + { + // For Buttons etc... + Focus = new (ColorScheme.Normal.Foreground, ColorScheme.Focus.Background), + + // For Adornments + Normal = new (ColorScheme.Focus.Foreground, ColorScheme.Normal.Background) + }; + ColorScheme = cs; + } + else + { + var cs = new ColorScheme (ColorScheme) + { + // For Buttons etc... that can't focus (like up/down). + Normal = new (ColorScheme.Focus.Background, ColorScheme.Normal.Foreground) + }; + ColorScheme = cs; + } + } + } + else { - ColorScheme = _savedHighlightColorScheme; - _savedHighlightColorScheme = null; + // Unhighlight + if (_savedHighlightColorScheme is { }) + { + ColorScheme = _savedHighlightColorScheme; + _savedHighlightColorScheme = null; + } } } /// - /// Fired when the view is no longer to be highlighted. Set to - /// + /// Fired when the view is highlighted. Set to /// to implement a custom highlight scheme or prevent the view from being highlighted. /// - public event EventHandler DisablingHighlight; + public event EventHandler Highlight; /// - /// Called when the view is no longer to be highlighted. + /// Called when the view is to be highlighted. /// /// , if the event was handled, otherwise. - protected virtual bool? OnDisablingHighlight () + protected virtual bool? OnHighlight (HighlightStyle highlight) { - CancelEventArgs args = new (); - DisablingHighlight?.Invoke (this, args); + HighlightEventArgs args = new (highlight); + Highlight?.Invoke (this, args); return args.Cancel; } diff --git a/Terminal.Gui/Views/Button.cs b/Terminal.Gui/Views/Button.cs index 0ab379b7df..cfeed66250 100644 --- a/Terminal.Gui/Views/Button.cs +++ b/Terminal.Gui/Views/Button.cs @@ -33,6 +33,9 @@ public class Button : View private readonly Rune _rightDefault; private bool _isDefault; + /// + private bool _wantContinuousButtonPressed; + /// Initializes a new instance of using layout. /// The width of the is computed based on the text length. The height will always be 1. public Button () @@ -50,7 +53,7 @@ public Button () CanFocus = true; AutoSize = true; - HighlightOnPress = true; + HighlightStyle |= HighlightStyle.Pressed; // Override default behavior of View AddCommand (Command.HotKey, () => @@ -65,6 +68,31 @@ public Button () TitleChanged += Button_TitleChanged; MouseClick += Button_MouseClick; } + + /// + public override bool WantContinuousButtonPressed + { + get => _wantContinuousButtonPressed; + set + { + if (value == _wantContinuousButtonPressed) + { + return; + } + + _wantContinuousButtonPressed = value; + + if (_wantContinuousButtonPressed) + { + HighlightStyle |= HighlightStyle.PressedOutside; + } + else + { + HighlightStyle &= ~HighlightStyle.PressedOutside; + } + } + } + private void Button_MouseClick (object sender, MouseEventEventArgs e) { e.Handled = InvokeCommand (Command.HotKey) == true; diff --git a/Terminal.Gui/Views/CheckBox.cs b/Terminal.Gui/Views/CheckBox.cs index bcf41f2c13..7b8dc08a8c 100644 --- a/Terminal.Gui/Views/CheckBox.cs +++ b/Terminal.Gui/Views/CheckBox.cs @@ -35,7 +35,7 @@ public CheckBox () TitleChanged += Checkbox_TitleChanged; - HighlightOnPress = true; + HighlightStyle = Gui.HighlightStyle.PressedOutside | Gui.HighlightStyle.Pressed; MouseClick += CheckBox_MouseClick; } diff --git a/Terminal.Gui/Views/ColorPicker.cs b/Terminal.Gui/Views/ColorPicker.cs index 61c41d4e63..ece096699d 100644 --- a/Terminal.Gui/Views/ColorPicker.cs +++ b/Terminal.Gui/Views/ColorPicker.cs @@ -31,7 +31,7 @@ public class ColorPicker : View private void SetInitialProperties () { - HighlightOnPress = true; + HighlightStyle = Gui.HighlightStyle.PressedOutside | Gui.HighlightStyle.Pressed; CanFocus = true; AddCommands (); diff --git a/Terminal.Gui/Views/RadioGroup.cs b/Terminal.Gui/Views/RadioGroup.cs index 13c7d53fd6..6f10c3bc03 100644 --- a/Terminal.Gui/Views/RadioGroup.cs +++ b/Terminal.Gui/Views/RadioGroup.cs @@ -77,7 +77,7 @@ public RadioGroup () LayoutStarted += RadioGroup_LayoutStarted; - HighlightOnPress = true; + HighlightStyle = Gui.HighlightStyle.PressedOutside | Gui.HighlightStyle.Pressed; MouseClick += RadioGroup_MouseClick; } diff --git a/UICatalog/Scenarios/Mouse.cs b/UICatalog/Scenarios/Mouse.cs index 7291ba92c8..c6c5734f57 100644 --- a/UICatalog/Scenarios/Mouse.cs +++ b/UICatalog/Scenarios/Mouse.cs @@ -76,9 +76,17 @@ public override void Main () Y = Pos.Bottom (cbWantContinuousPresses), Title = "_Highlight on Press", }; + cbHighlightOnPress.Checked = win.HighlightStyle == (HighlightStyle.Pressed | HighlightStyle.PressedOutside); cbHighlightOnPress.Toggled += (s, e) => { - win.HighlightOnPress = !win.HighlightOnPress; + if (e.NewValue == true) + { + win.HighlightStyle = HighlightStyle.Pressed | HighlightStyle.PressedOutside; + } + else + { + win.HighlightStyle = HighlightStyle.None; + } }; win.Add (cbHighlightOnPress); diff --git a/UnitTests/View/MouseTests.cs b/UnitTests/View/MouseTests.cs index 5e6b7ef61d..339e738784 100644 --- a/UnitTests/View/MouseTests.cs +++ b/UnitTests/View/MouseTests.cs @@ -465,27 +465,26 @@ public void WantContinuousButtonPressed_True_Move_InViewport_OutOfViewport_Keeps } [Theory] - [InlineData(false, 0, 0)] - [InlineData (true, 1, 1)] - public void HighlightOnPress_Fires_Events_And_Highlights (bool highlightOnPress, int expectedEnabling, int expectedDisabling) + [InlineData (HighlightStyle.None, 0, 0)] + [InlineData (HighlightStyle.Pressed | HighlightStyle.PressedOutside, 1, 1)] + public void HighlightOnPress_Fires_Events_And_Highlights (HighlightStyle highlightOnPress, int expectedEnabling, int expectedDisabling) { var view = new View () { - HighlightOnPress = highlightOnPress, + HighlightStyle = highlightOnPress, Height = 1, Width = 1 }; int enablingHighlight = 0; int disablingHighlight = 0; - view.EnablingHighlight += View_EnablingHighlight; - view.DisablingHighlight += View_DisablingHighlight; + view.Highlight += View_Highlight; view.ColorScheme = new ColorScheme (new Attribute (ColorName.Red, ColorName.Blue)); ColorScheme originalColorScheme = view.ColorScheme; view.NewMouseEvent (new () { Flags = MouseFlags.Button1Pressed, }); - if (highlightOnPress) + if (highlightOnPress != HighlightStyle.None) { Assert.NotEqual (originalColorScheme, view.ColorScheme); } @@ -503,16 +502,21 @@ public void HighlightOnPress_Fires_Events_And_Highlights (bool highlightOnPress, return; - void View_DisablingHighlight (object sender, System.ComponentModel.CancelEventArgs e) + void View_Highlight (object sender, HighlightEventArgs e) { - disablingHighlight++; - } - void View_EnablingHighlight (object sender, System.ComponentModel.CancelEventArgs e) - { - enablingHighlight++; + if (e.HighlightStyle == HighlightStyle.None) + { + disablingHighlight++; + } + else + { + enablingHighlight++; + } } } + // TODO: Add tests for each combination of HighlightFlags + [Theory] [InlineData (0)] [InlineData (1)] @@ -521,14 +525,13 @@ public void HighlightOnPress_Move_Keeps_Highlight (int x) { var view = new View () { - HighlightOnPress = true, + HighlightStyle = HighlightStyle.Pressed | HighlightStyle.PressedOutside, Height = 1, Width = 1 }; int enablingHighlight = 0; int disablingHighlight = 0; - view.EnablingHighlight += View_EnablingHighlight; - view.DisablingHighlight += View_DisablingHighlight; + view.Highlight += View_Highlight; bool inViewport = view.Bounds.Contains (x, 0); // Start at 0,0 ; in viewport @@ -546,8 +549,8 @@ public void HighlightOnPress_Move_Keeps_Highlight (int x) } else { - Assert.Equal (1, enablingHighlight); - Assert.Equal (1, disablingHighlight); + Assert.Equal (2, enablingHighlight); + Assert.Equal (0, disablingHighlight); } // Move backto 0,0 ; in viewport @@ -559,21 +562,24 @@ public void HighlightOnPress_Move_Keeps_Highlight (int x) } else { - Assert.Equal (2, enablingHighlight); - Assert.Equal (1, disablingHighlight); + Assert.Equal (3, enablingHighlight); + Assert.Equal (0, disablingHighlight); } view.Dispose (); return; - void View_DisablingHighlight (object sender, System.ComponentModel.CancelEventArgs e) - { - disablingHighlight++; - } - void View_EnablingHighlight (object sender, System.ComponentModel.CancelEventArgs e) + void View_Highlight (object sender, HighlightEventArgs e) { - enablingHighlight++; + if (e.HighlightStyle == HighlightStyle.None) + { + disablingHighlight++; + } + else + { + enablingHighlight++; + } } } From 40ae2729442c93770e1e6448526b0122ba71a39b Mon Sep 17 00:00:00 2001 From: Tig Date: Sat, 6 Apr 2024 08:15:57 -0400 Subject: [PATCH 28/32] Refactored MouseEnter/Leave APIs to match design guidelines --- Terminal.Gui/Application.cs | 8 +-- Terminal.Gui/View/ViewMouse.cs | 89 +++++++++++++++++++++++++++---- Terminal.Gui/Views/Toplevel.cs | 2 +- UnitTests/Input/ResponderTests.cs | 4 +- UnitTests/View/ViewTests.cs | 4 +- 5 files changed, 89 insertions(+), 18 deletions(-) diff --git a/Terminal.Gui/Application.cs b/Terminal.Gui/Application.cs index b8cbb7f1f7..1901bba2ac 100644 --- a/Terminal.Gui/Application.cs +++ b/Terminal.Gui/Application.cs @@ -1486,7 +1486,7 @@ internal static void OnMouseEvent (MouseEvent mouseEvent) if (MouseGrabView.Bounds.Contains (viewRelativeMouseEvent.X, viewRelativeMouseEvent.Y) is false) { // The mouse has moved outside the bounds of the view that grabbed the mouse - _mouseEnteredView?.OnMouseLeave (mouseEvent); + _mouseEnteredView?.NewMouseLeaveEvent (mouseEvent); } //System.Diagnostics.Debug.WriteLine ($"{nme.Flags};{nme.X};{nme.Y};{mouseGrabView}"); @@ -1568,12 +1568,12 @@ internal static void OnMouseEvent (MouseEvent mouseEvent) if (_mouseEnteredView is null) { _mouseEnteredView = view; - view.OnMouseEnter (me); + view.NewMouseEnterEvent (me); } else if (_mouseEnteredView != view) { - _mouseEnteredView.OnMouseLeave (me); - view.OnMouseEnter (me); + _mouseEnteredView.NewMouseLeaveEvent (me); + view.NewMouseEnterEvent (me); _mouseEnteredView = view; } diff --git a/Terminal.Gui/View/ViewMouse.cs b/Terminal.Gui/View/ViewMouse.cs index 944928c8c8..4b7e4f1464 100644 --- a/Terminal.Gui/View/ViewMouse.cs +++ b/Terminal.Gui/View/ViewMouse.cs @@ -29,6 +29,9 @@ public enum HighlightStyle PressedOutside = 4 } +/// +/// Event arguments for the event. +/// public class HighlightEventArgs : CancelEventArgs { public HighlightEventArgs (HighlightStyle style) @@ -36,6 +39,9 @@ public HighlightEventArgs (HighlightStyle style) HighlightStyle = style; } + /// + /// The highlight style. + /// public HighlightStyle HighlightStyle { get; } } @@ -55,16 +61,24 @@ public partial class View public virtual bool WantMousePositionReports { get; set; } /// - /// 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. + /// Called by when the mouse enters . The view will + /// then receive mouse events until is called indicating the mouse has left + /// the view. /// /// - /// The coordinates are relative to . + /// + /// A view must be both enabled and visible to receive mouse events. + /// + /// + /// This method calls to fire the event. + /// + /// + /// See for more information. + /// /// /// - /// , if the event was handled, otherwise. - protected internal virtual bool OnMouseEnter (MouseEvent mouseEvent) + /// if the event was handled, otherwise. + internal bool? NewMouseEnterEvent (MouseEvent mouseEvent) { if (!Enabled) { @@ -76,6 +90,27 @@ protected internal virtual bool OnMouseEnter (MouseEvent mouseEvent) return false; } + return OnMouseEnter (mouseEvent); + } + + /// + /// Called by when the mouse enters . The view will + /// then receive mouse events until is called indicating the mouse has left + /// the view. + /// + /// + /// + /// Override this method or subscribe to to change the default enter behavior. + /// + /// + /// The coordinates are relative to . + /// + /// + /// + /// , if the event was handled, otherwise. + protected internal virtual bool OnMouseEnter (MouseEvent mouseEvent) + { + var args = new MouseEventEventArgs (mouseEvent); MouseEnter?.Invoke (this, args); @@ -85,13 +120,49 @@ protected internal virtual bool OnMouseEnter (MouseEvent mouseEvent) /// Event fired when the mouse moves into the View's . public event EventHandler MouseEnter; + + /// + /// Called by when the mouse leaves . The view will + /// then no longer receive mouse events. + /// + /// + /// + /// A view must be both enabled and visible to receive mouse events. + /// + /// + /// This method calls to fire the event. + /// + /// + /// See for more information. + /// + /// + /// + /// if the event was handled, otherwise. + internal bool? NewMouseLeaveEvent (MouseEvent mouseEvent) + { + if (!Enabled) + { + return true; + } + + if (!CanBeVisible (this)) + { + return false; + } + + return OnMouseLeave (mouseEvent); + } /// - /// 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). + /// Called by when a mouse leaves . The view will + /// no longer receive mouse events. /// /// + /// + /// Override this method or subscribe to to change the default leave behavior. + /// + /// /// The coordinates are relative to . + /// /// /// /// , if the event was handled, otherwise. diff --git a/Terminal.Gui/Views/Toplevel.cs b/Terminal.Gui/Views/Toplevel.cs index 4bc5b111da..69bcb2d4db 100644 --- a/Terminal.Gui/Views/Toplevel.cs +++ b/Terminal.Gui/Views/Toplevel.cs @@ -444,7 +444,7 @@ out StatusBar sb /// perform tasks when the has been laid out and focus has been set. changes. /// /// A Ready event handler is a good place to finalize initialization after calling - /// on this . + /// on this . /// /// public event EventHandler Ready; diff --git a/UnitTests/Input/ResponderTests.cs b/UnitTests/Input/ResponderTests.cs index 3a1d530766..6801aa991a 100644 --- a/UnitTests/Input/ResponderTests.cs +++ b/UnitTests/Input/ResponderTests.cs @@ -235,8 +235,8 @@ public void New_Methods_Return_False () Assert.False (r.OnKeyDown (new Key { KeyCode = KeyCode.Null })); Assert.False (r.OnKeyUp (new Key { KeyCode = KeyCode.Null })); Assert.False (r.NewMouseEvent (new MouseEvent { Flags = MouseFlags.AllEvents })); - Assert.False (r.OnMouseEnter (new MouseEvent { Flags = MouseFlags.AllEvents })); - Assert.False (r.OnMouseLeave (new MouseEvent { Flags = MouseFlags.AllEvents })); + Assert.False (r.NewMouseEnterEvent (new MouseEvent { Flags = MouseFlags.AllEvents })); + Assert.False (r.NewMouseLeaveEvent (new MouseEvent { Flags = MouseFlags.AllEvents })); var v = new View (); Assert.False (r.OnEnter (v)); diff --git a/UnitTests/View/ViewTests.cs b/UnitTests/View/ViewTests.cs index ae6c82c3d4..87b9f5359a 100644 --- a/UnitTests/View/ViewTests.cs +++ b/UnitTests/View/ViewTests.cs @@ -866,8 +866,8 @@ public void New_Methods_Return_False () //Assert.False (r.OnKeyDown (new KeyEventArgs () { Key = Key.Unknown })); Assert.False (r.OnKeyUp (new Key { KeyCode = KeyCode.Null })); Assert.False (r.NewMouseEvent (new MouseEvent { Flags = MouseFlags.AllEvents })); - Assert.False (r.OnMouseEnter (new MouseEvent { Flags = MouseFlags.AllEvents })); - Assert.False (r.OnMouseLeave (new MouseEvent { Flags = MouseFlags.AllEvents })); + Assert.False (r.NewMouseEnterEvent (new MouseEvent { Flags = MouseFlags.AllEvents })); + Assert.False (r.NewMouseLeaveEvent (new MouseEvent { Flags = MouseFlags.AllEvents })); var v1 = new View (); Assert.False (r.OnEnter (v1)); From ac667dae2c1eef55e9fc2dd856f345d3199cb624 Mon Sep 17 00:00:00 2001 From: Tig Date: Sat, 6 Apr 2024 09:09:42 -0400 Subject: [PATCH 29/32] Got Hover working for all Views (Button) and Border. Still a bit of a prototype. --- Terminal.Gui/View/Adornment/Adornment.cs | 2 +- Terminal.Gui/View/Adornment/Border.cs | 34 ++++++++++++---- Terminal.Gui/View/ViewMouse.cs | 50 +++++++++++++++++++----- Terminal.Gui/Views/Button.cs | 1 + 4 files changed, 69 insertions(+), 18 deletions(-) diff --git a/Terminal.Gui/View/Adornment/Adornment.cs b/Terminal.Gui/View/Adornment/Adornment.cs index 5a99d7a303..307f3cb3e1 100644 --- a/Terminal.Gui/View/Adornment/Adornment.cs +++ b/Terminal.Gui/View/Adornment/Adornment.cs @@ -212,7 +212,7 @@ public override bool Contains (int x, int y) } /// - protected internal override bool OnMouseEnter (MouseEvent mouseEvent) + protected internal override bool? OnMouseEnter (MouseEvent mouseEvent) { // Invert Normal if (Diagnostics.HasFlag (ViewDiagnosticFlags.MouseEnter) && ColorScheme != null) diff --git a/Terminal.Gui/View/Adornment/Border.cs b/Terminal.Gui/View/Adornment/Border.cs index a45c3f7d2d..a67de3edd8 100644 --- a/Terminal.Gui/View/Adornment/Border.cs +++ b/Terminal.Gui/View/Adornment/Border.cs @@ -57,7 +57,7 @@ public Border (View parent) : base (parent) Application.GrabbingMouse += Application_GrabbingMouse; Application.UnGrabbingMouse += Application_UnGrabbingMouse; - HighlightStyle = HighlightStyle.Pressed; + HighlightStyle |= HighlightStyle.Pressed; Highlight += Border_Highlight; } @@ -73,6 +73,12 @@ public Border (View parent) : base (parent) /// public override void BeginInit () { + // TOOD: Hack - make Arragnement overidable + if ((Parent?.Arrangement & ViewArrangement.Movable) != 0) + { + HighlightStyle |= HighlightStyle.Hover; + } + base.BeginInit (); #if SUBVIEW_BASED_BORDER @@ -100,7 +106,7 @@ public override void BeginInit () LayoutStarted += OnLayoutStarted; } #endif -} + } #if SUBVIEW_BASED_BORDER private void OnLayoutStarted (object sender, LayoutEventArgs e) @@ -190,18 +196,30 @@ public LineStyle LineStyle #region Mouse Support - private LineStyle _savedHighlightLineStyle; + private LineStyle? _savedHighlightLineStyle; private void Border_Highlight (object sender, HighlightEventArgs e) { - if (e.HighlightStyle == HighlightStyle) + if (e.HighlightStyle.HasFlag (HighlightStyle.Pressed)) { - _savedHighlightLineStyle = Parent?.BorderStyle ?? LineStyle; + if (!_savedHighlightLineStyle.HasValue) + { + _savedHighlightLineStyle = Parent?.BorderStyle ?? LineStyle; + } LineStyle = LineStyle.Heavy; } - else + else if (e.HighlightStyle.HasFlag (HighlightStyle.Hover)) + { + if (!_savedHighlightLineStyle.HasValue) + { + _savedHighlightLineStyle = Parent?.BorderStyle ?? LineStyle; + } + LineStyle = LineStyle.Double; + } + + if (e.HighlightStyle == HighlightStyle.None && _savedHighlightLineStyle.HasValue) { - LineStyle = _savedHighlightLineStyle; + LineStyle = _savedHighlightLineStyle.Value; } Parent?.SetNeedsDisplay (); e.Cancel = true; @@ -321,7 +339,7 @@ private void Application_UnGrabbingMouse (object sender, GrabMouseEventArgs e) } } -#endregion Mouse Support + #endregion Mouse Support /// public override void OnDrawContent (Rectangle contentArea) diff --git a/Terminal.Gui/View/ViewMouse.cs b/Terminal.Gui/View/ViewMouse.cs index 4b7e4f1464..ec0f999424 100644 --- a/Terminal.Gui/View/ViewMouse.cs +++ b/Terminal.Gui/View/ViewMouse.cs @@ -90,7 +90,17 @@ public partial class View return false; } - return OnMouseEnter (mouseEvent); + if (OnMouseEnter (mouseEvent) == true) + { + return true; + } + + if (HighlightStyle.HasFlag(HighlightStyle.Hover)) + { + SetHighlight (HighlightStyle.Hover); + } + + return false; } /// @@ -108,7 +118,7 @@ public partial class View /// /// /// , if the event was handled, otherwise. - protected internal virtual bool OnMouseEnter (MouseEvent mouseEvent) + protected internal virtual bool? OnMouseEnter (MouseEvent mouseEvent) { var args = new MouseEventEventArgs (mouseEvent); @@ -150,7 +160,17 @@ protected internal virtual bool OnMouseEnter (MouseEvent mouseEvent) return false; } - return OnMouseLeave (mouseEvent); + if (OnMouseEnter (mouseEvent) == true) + { + return true; + } + + if (HighlightStyle.HasFlag (HighlightStyle.Hover)) + { + SetHighlight (HighlightStyle.None); + } + + return false; } /// /// Called by when a mouse leaves . The view will @@ -400,12 +420,28 @@ internal bool HandleClicked (MouseEvent mouseEvent) /// internal void SetHighlight (HighlightStyle style) { + // TODO: Make the highlight colors configurable + // Enable override via virtual method and/or event if (OnHighlight (style) == true) { return; } + if (style.HasFlag (HighlightStyle.Hover)) + { + if (_savedHighlightColorScheme is null && ColorScheme is { }) + { + _savedHighlightColorScheme ??= ColorScheme; + + var cs = new ColorScheme (ColorScheme) + { + Normal = new (ColorName.BrightRed, ColorName.Black), + }; + ColorScheme = cs; + } + } + if (style.HasFlag (HighlightStyle.Pressed) || style.HasFlag (HighlightStyle.PressedOutside)) { @@ -415,14 +451,9 @@ internal void SetHighlight (HighlightStyle style) if (CanFocus) { - // TODO: Make the inverted color configurable var cs = new ColorScheme (ColorScheme) { - // For Buttons etc... Focus = new (ColorScheme.Normal.Foreground, ColorScheme.Focus.Background), - - // For Adornments - Normal = new (ColorScheme.Focus.Foreground, ColorScheme.Normal.Background) }; ColorScheme = cs; } @@ -437,7 +468,8 @@ internal void SetHighlight (HighlightStyle style) } } } - else + + if (style == HighlightStyle.None) { // Unhighlight if (_savedHighlightColorScheme is { }) diff --git a/Terminal.Gui/Views/Button.cs b/Terminal.Gui/Views/Button.cs index cfeed66250..f770639344 100644 --- a/Terminal.Gui/Views/Button.cs +++ b/Terminal.Gui/Views/Button.cs @@ -54,6 +54,7 @@ public Button () CanFocus = true; AutoSize = true; HighlightStyle |= HighlightStyle.Pressed; + HighlightStyle |= HighlightStyle.Hover; // Override default behavior of View AddCommand (Command.HotKey, () => From 6c296bb2991f0443850159f48b274e3b4aa44cd5 Mon Sep 17 00:00:00 2001 From: Tig Date: Mon, 8 Apr 2024 10:16:30 -0400 Subject: [PATCH 30/32] Disabled Hover (#define HOVER). Added Color.GetHighlightColor. Simple implementation for now. Needs to be more robust. --- Terminal.Gui/Drawing/Color.cs | 22 +++++++++++ Terminal.Gui/Terminal.Gui.csproj | 1 + Terminal.Gui/View/Adornment/Border.cs | 8 +++- Terminal.Gui/View/ViewMouse.cs | 55 ++++++++++++++++++++------- Terminal.Gui/Views/Button.cs | 3 +- UICatalog/Scenarios/TrueColors.cs | 32 +++++++++++++++- 6 files changed, 103 insertions(+), 18 deletions(-) diff --git a/Terminal.Gui/Drawing/Color.cs b/Terminal.Gui/Drawing/Color.cs index 82e4e361e9..001e8588be 100644 --- a/Terminal.Gui/Drawing/Color.cs +++ b/Terminal.Gui/Drawing/Color.cs @@ -6,6 +6,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text.Json.Serialization; +using ColorHelper; namespace Terminal.Gui; @@ -237,6 +238,27 @@ internal static ColorName GetClosestNamedColor (Color inputColor) [SkipLocalsInit] private static float CalculateColorDistance (in Vector4 color1, in Vector4 color2) { return Vector4.Distance (color1, color2); } + /// + /// Gets a color that is the same hue as the current color, but with a different lightness. + /// + /// + public Color GetHighlightColor () + { + // TODO: This is a temporary implementation; just enough to show how it could work. + var hsl = ColorHelper.ColorConverter.RgbToHsl(new RGB (R, G, B)); + + var amount = .7; + if (hsl.L < 50) + { + amount += 1; + } + hsl.L = (byte)(hsl.L * amount); + + var rgb = ColorHelper.ColorConverter.HslToRgb (hsl); + return new (rgb.R, rgb.G, rgb.B); + + } + #region Legacy Color Names /// The black color. diff --git a/Terminal.Gui/Terminal.Gui.csproj b/Terminal.Gui/Terminal.Gui.csproj index 2180f0334c..c2f39edb84 100644 --- a/Terminal.Gui/Terminal.Gui.csproj +++ b/Terminal.Gui/Terminal.Gui.csproj @@ -44,6 +44,7 @@ + diff --git a/Terminal.Gui/View/Adornment/Border.cs b/Terminal.Gui/View/Adornment/Border.cs index a67de3edd8..6eefd56261 100644 --- a/Terminal.Gui/View/Adornment/Border.cs +++ b/Terminal.Gui/View/Adornment/Border.cs @@ -73,11 +73,13 @@ public Border (View parent) : base (parent) /// public override void BeginInit () { +#if HOVER // TOOD: Hack - make Arragnement overidable if ((Parent?.Arrangement & ViewArrangement.Movable) != 0) { HighlightStyle |= HighlightStyle.Hover; - } + } +#endif base.BeginInit (); @@ -208,6 +210,7 @@ private void Border_Highlight (object sender, HighlightEventArgs e) } LineStyle = LineStyle.Heavy; } +#if HOVER else if (e.HighlightStyle.HasFlag (HighlightStyle.Hover)) { if (!_savedHighlightLineStyle.HasValue) @@ -216,6 +219,7 @@ private void Border_Highlight (object sender, HighlightEventArgs e) } LineStyle = LineStyle.Double; } +#endif if (e.HighlightStyle == HighlightStyle.None && _savedHighlightLineStyle.HasValue) { @@ -339,7 +343,7 @@ private void Application_UnGrabbingMouse (object sender, GrabMouseEventArgs e) } } - #endregion Mouse Support +#endregion Mouse Support /// public override void OnDrawContent (Rectangle contentArea) diff --git a/Terminal.Gui/View/ViewMouse.cs b/Terminal.Gui/View/ViewMouse.cs index ec0f999424..567cff39b0 100644 --- a/Terminal.Gui/View/ViewMouse.cs +++ b/Terminal.Gui/View/ViewMouse.cs @@ -13,10 +13,12 @@ public enum HighlightStyle /// None = 0, +#if HOVER /// /// The mouse is hovering over the view. /// Hover = 1, +#endif /// /// The mouse is pressed within the . @@ -95,11 +97,15 @@ public partial class View return true; } +#if HOVER if (HighlightStyle.HasFlag(HighlightStyle.Hover)) { - SetHighlight (HighlightStyle.Hover); + if (SetHighlight (HighlightStyle.Hover)) + { + return true; + } } - +#endif return false; } @@ -160,15 +166,16 @@ public partial class View return false; } - if (OnMouseEnter (mouseEvent) == true) + if (OnMouseLeave (mouseEvent) == true) { return true; } - +#if HOVER if (HighlightStyle.HasFlag (HighlightStyle.Hover)) { SetHighlight (HighlightStyle.None); } +#endif return false; } @@ -322,11 +329,18 @@ private bool HandlePressed (MouseEvent mouseEvent) if (Bounds.Contains (mouseEvent.X, mouseEvent.Y)) { - SetHighlight (HighlightStyle.HasFlag(HighlightStyle.Pressed) ? HighlightStyle.Pressed : HighlightStyle.None); + if (SetHighlight (HighlightStyle.HasFlag (HighlightStyle.Pressed) ? HighlightStyle.Pressed : HighlightStyle.None) == true) + { + return true; + } } else { - SetHighlight (HighlightStyle.HasFlag (HighlightStyle.PressedOutside) ? HighlightStyle.PressedOutside : HighlightStyle.None); + if (SetHighlight (HighlightStyle.HasFlag (HighlightStyle.PressedOutside) ? HighlightStyle.PressedOutside : HighlightStyle.None) == true) + + { + return true; + } } if (WantContinuousButtonPressed && Application.MouseGrabView == this) @@ -387,7 +401,11 @@ internal bool HandleClicked (MouseEvent mouseEvent) { // We're grabbed. Clicked event comes after the last Release. This is our signal to ungrab Application.UngrabMouse (); - SetHighlight (HighlightStyle.None); + + if (SetHighlight (HighlightStyle.None)) + { + return true; + } // If mouse is still in bounds, click if (!WantContinuousButtonPressed && Bounds.Contains (mouseEvent.X, mouseEvent.Y)) @@ -418,16 +436,18 @@ internal bool HandleClicked (MouseEvent mouseEvent) /// Marked internal just to support unit tests /// /// - internal void SetHighlight (HighlightStyle style) + /// , if the Highlight event was handled, otherwise. + + internal bool SetHighlight (HighlightStyle style) { // TODO: Make the highlight colors configurable // Enable override via virtual method and/or event if (OnHighlight (style) == true) { - return; + return true; } - +#if HOVER if (style.HasFlag (HighlightStyle.Hover)) { if (_savedHighlightColorScheme is null && ColorScheme is { }) @@ -436,15 +456,17 @@ internal void SetHighlight (HighlightStyle style) var cs = new ColorScheme (ColorScheme) { - Normal = new (ColorName.BrightRed, ColorName.Black), + Normal = GetFocusColor (), + HotNormal = ColorScheme.HotFocus }; ColorScheme = cs; } - } + return true; + } +#endif if (style.HasFlag (HighlightStyle.Pressed) || style.HasFlag (HighlightStyle.PressedOutside)) { - if (_savedHighlightColorScheme is null && ColorScheme is { }) { _savedHighlightColorScheme ??= ColorScheme; @@ -453,7 +475,7 @@ internal void SetHighlight (HighlightStyle style) { var cs = new ColorScheme (ColorScheme) { - Focus = new (ColorScheme.Normal.Foreground, ColorScheme.Focus.Background), + Focus = new (ColorScheme.Focus.Foreground.GetHighlightColor (), ColorScheme.Focus.Background.GetHighlightColor ()), }; ColorScheme = cs; } @@ -466,9 +488,12 @@ internal void SetHighlight (HighlightStyle style) }; ColorScheme = cs; } + + return true; } } + if (style == HighlightStyle.None) { // Unhighlight @@ -478,6 +503,8 @@ internal void SetHighlight (HighlightStyle style) _savedHighlightColorScheme = null; } } + + return false; } /// diff --git a/Terminal.Gui/Views/Button.cs b/Terminal.Gui/Views/Button.cs index f770639344..a710bc2d92 100644 --- a/Terminal.Gui/Views/Button.cs +++ b/Terminal.Gui/Views/Button.cs @@ -54,8 +54,9 @@ public Button () CanFocus = true; AutoSize = true; HighlightStyle |= HighlightStyle.Pressed; +#if HOVER HighlightStyle |= HighlightStyle.Hover; - +#endif // Override default behavior of View AddCommand (Command.HotKey, () => { diff --git a/UICatalog/Scenarios/TrueColors.cs b/UICatalog/Scenarios/TrueColors.cs index 7e89626173..a392f23476 100644 --- a/UICatalog/Scenarios/TrueColors.cs +++ b/UICatalog/Scenarios/TrueColors.cs @@ -67,6 +67,14 @@ public override void Setup () new Label { X = Pos.AnchorEnd (44), Y = 6, Text = "Blue:" } ); + Win.Add ( + new Label { X = Pos.AnchorEnd (44), Y = 8, Text = "Darker:" } + ); + + Win.Add ( + new Label { X = Pos.AnchorEnd (44), Y = 9, Text = "Lighter:" } + ); + var lblRed = new Label { X = Pos.AnchorEnd (32), Y = 4, Text = "na" }; Win.Add (lblRed); var lblGreen = new Label { X = Pos.AnchorEnd (32), Y = 5, Text = "na" }; @@ -74,9 +82,31 @@ public override void Setup () var lblBlue = new Label { X = Pos.AnchorEnd (32), Y = 6, Text = "na" }; Win.Add (lblBlue); + var lblDarker = new Label { X = Pos.AnchorEnd (32), Y = 8, Text = " " }; + Win.Add (lblDarker); + + var lblLighter = new Label { X = Pos.AnchorEnd (32), Y = 9, Text = " " }; + Win.Add (lblLighter); + Application.MouseEvent += (s, e) => { - if (e.View != null) + if (e.View == null) + { + return; + } + if (e.Flags == MouseFlags.Button1Clicked) + { + Attribute normal = e.View.GetNormalColor (); + + lblLighter.ColorScheme = new ColorScheme(e.View.ColorScheme) + { + Normal = new Attribute ( + normal.Foreground, + normal.Background.GetHighlightColor () + ) + }; + } + else { Attribute normal = e.View.GetNormalColor (); lblRed.Text = normal.Foreground.R.ToString (); From bd0f89f8b1bad86c0ca37d1f313098822e2a1d31 Mon Sep 17 00:00:00 2001 From: Tig Date: Mon, 8 Apr 2024 11:59:53 -0400 Subject: [PATCH 31/32] Border changes color, not line style on drag --- Terminal.Gui/Drawing/Color.cs | 4 ++-- Terminal.Gui/View/Adornment/Border.cs | 26 ++++++++++++++++++++------ Terminal.Gui/View/ViewMouse.cs | 3 ++- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/Terminal.Gui/Drawing/Color.cs b/Terminal.Gui/Drawing/Color.cs index 001e8588be..cd0944c374 100644 --- a/Terminal.Gui/Drawing/Color.cs +++ b/Terminal.Gui/Drawing/Color.cs @@ -248,9 +248,9 @@ public Color GetHighlightColor () var hsl = ColorHelper.ColorConverter.RgbToHsl(new RGB (R, G, B)); var amount = .7; - if (hsl.L < 50) + if (hsl.L <= 5) { - amount += 1; + return DarkGray; } hsl.L = (byte)(hsl.L * amount); diff --git a/Terminal.Gui/View/Adornment/Border.cs b/Terminal.Gui/View/Adornment/Border.cs index 6eefd56261..cee764c568 100644 --- a/Terminal.Gui/View/Adornment/Border.cs +++ b/Terminal.Gui/View/Adornment/Border.cs @@ -198,17 +198,27 @@ public LineStyle LineStyle #region Mouse Support - private LineStyle? _savedHighlightLineStyle; + private Color? _savedForeColor; private void Border_Highlight (object sender, HighlightEventArgs e) { + if (!Parent.Arrangement.HasFlag (ViewArrangement.Movable)) + { + return; + } + if (e.HighlightStyle.HasFlag (HighlightStyle.Pressed)) { - if (!_savedHighlightLineStyle.HasValue) + if (!_savedForeColor.HasValue) { - _savedHighlightLineStyle = Parent?.BorderStyle ?? LineStyle; + _savedForeColor = ColorScheme.Normal.Foreground; } - LineStyle = LineStyle.Heavy; + + ColorScheme cs = new ColorScheme (ColorScheme) + { + Normal = new Attribute (ColorScheme.Normal.Foreground.GetHighlightColor (), ColorScheme.Normal.Background) + }; + ColorScheme = cs; } #if HOVER else if (e.HighlightStyle.HasFlag (HighlightStyle.Hover)) @@ -221,9 +231,13 @@ private void Border_Highlight (object sender, HighlightEventArgs e) } #endif - if (e.HighlightStyle == HighlightStyle.None && _savedHighlightLineStyle.HasValue) + if (e.HighlightStyle == HighlightStyle.None && _savedForeColor.HasValue) { - LineStyle = _savedHighlightLineStyle.Value; + ColorScheme cs = new ColorScheme (ColorScheme) + { + Normal = new Attribute (_savedForeColor.Value, ColorScheme.Normal.Background) + }; + ColorScheme = cs; } Parent?.SetNeedsDisplay (); e.Cancel = true; diff --git a/Terminal.Gui/View/ViewMouse.cs b/Terminal.Gui/View/ViewMouse.cs index 567cff39b0..fa94be54f7 100644 --- a/Terminal.Gui/View/ViewMouse.cs +++ b/Terminal.Gui/View/ViewMouse.cs @@ -475,6 +475,7 @@ internal bool SetHighlight (HighlightStyle style) { var cs = new ColorScheme (ColorScheme) { + // Highlight the foreground focus color Focus = new (ColorScheme.Focus.Foreground.GetHighlightColor (), ColorScheme.Focus.Background.GetHighlightColor ()), }; ColorScheme = cs; @@ -483,7 +484,7 @@ internal bool SetHighlight (HighlightStyle style) { var cs = new ColorScheme (ColorScheme) { - // For Buttons etc... that can't focus (like up/down). + // Invert Focus color foreground/background. We can do this because we know the view is not going to be focused. Normal = new (ColorScheme.Focus.Background, ColorScheme.Normal.Foreground) }; ColorScheme = cs; From 102269ec2a83db07bde46d523b08af39109cd196 Mon Sep 17 00:00:00 2001 From: Tig Date: Mon, 8 Apr 2024 12:17:37 -0400 Subject: [PATCH 32/32] Temp fix for ProgressStyles scenario --- UICatalog/Scenarios/ProgressBarStyles.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/UICatalog/Scenarios/ProgressBarStyles.cs b/UICatalog/Scenarios/ProgressBarStyles.cs index 61fee87ae7..4a92e2a072 100644 --- a/UICatalog/Scenarios/ProgressBarStyles.cs +++ b/UICatalog/Scenarios/ProgressBarStyles.cs @@ -64,19 +64,25 @@ ColorName ChooseColor (string text, ColorName colorName) { var colorPicker = new ColorPicker { Title = text, SelectedColor = colorName }; - var dialog = new Dialog { Title = text }; + var dialog = new Dialog { AutoSize = false, Title = text }; - dialog.LayoutComplete += (sender, args) => + dialog.Initialized += (sender, args) => { // TODO: Replace with Dim.Auto dialog.X = pbList.Frame.X; dialog.Y = pbList.Frame.Height; - - dialog.Bounds = new Rectangle (0, 0, colorPicker.Frame.Width, colorPicker.Frame.Height); - - Top.LayoutSubviews (); }; + dialog.LayoutComplete += (sender, args) => + { + dialog.Bounds = Rectangle.Empty with + { + Width = colorPicker.Frame.Width, + Height = colorPicker.Frame.Height + }; + Application.Top.LayoutSubviews(); + }; + dialog.Add (colorPicker); colorPicker.ColorChanged += (s, e) => { dialog.RequestStop (); }; Application.Run (dialog);