mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-28 16:58:01 +01:00
Merge pull request #2438 from BDisp/v2_dialog-bigger-fix_2434
Fixes #2434. Dialog bounds bigger than Cols and Rows must be allowed to drag beyond left, right and bottom.
This commit is contained in:
@@ -210,7 +210,7 @@ namespace Terminal.Gui {
|
||||
|
||||
Application.GrabbingMouse += Application_GrabbingMouse;
|
||||
Application.UnGrabbingMouse += Application_UnGrabbingMouse;
|
||||
|
||||
|
||||
// TODO: v2 - ALL Views (Responders??!?!) should support the commands related to
|
||||
// - Focus
|
||||
// Move the appropriate AddCommand calls to `Responder`
|
||||
@@ -378,8 +378,7 @@ namespace Terminal.Gui {
|
||||
|
||||
/// <summary>
|
||||
/// <see langword="true"/> if was already loaded by the <see cref="Application.Begin(Toplevel)"/>
|
||||
/// <see langword="false"/>, otherwise. This is used to avoid the <see cref="View._needsDisplay"/>
|
||||
/// having wrong values while this was not yet loaded.
|
||||
/// <see langword="false"/>, otherwise.
|
||||
/// </summary>
|
||||
public bool IsLoaded { get; private set; }
|
||||
|
||||
@@ -627,11 +626,15 @@ namespace Terminal.Gui {
|
||||
l = top.SuperView.Frame.Width;
|
||||
superView = top.SuperView;
|
||||
}
|
||||
nx = Math.Max (x, 0);
|
||||
nx = nx + top.Frame.Width > l ? Math.Max (l - top.Frame.Width, 0) : nx;
|
||||
var mfLength = top.Border?.DrawMarginFrame == true ? 2 : 1;
|
||||
if (nx + mfLength > top.Frame.X + top.Frame.Width) {
|
||||
nx = Math.Max (top.Frame.Right - mfLength, 0);
|
||||
if (top.Frame.Width <= l) {
|
||||
nx = Math.Max (x, 0);
|
||||
nx = nx + top.Frame.Width > l ? Math.Max (l - top.Frame.Width, 0) : nx;
|
||||
if (nx + mfLength > top.Frame.X + top.Frame.Width) {
|
||||
nx = Math.Max (top.Frame.Right - mfLength, 0);
|
||||
}
|
||||
} else {
|
||||
nx = x;
|
||||
}
|
||||
//System.Diagnostics.Debug.WriteLine ($"nx:{nx}, rWidth:{rWidth}");
|
||||
bool m, s;
|
||||
@@ -640,7 +643,7 @@ namespace Terminal.Gui {
|
||||
mb = Application.Top.MenuBar;
|
||||
} else {
|
||||
var t = top.SuperView;
|
||||
while (!(t is Toplevel)) {
|
||||
while (t is not Toplevel) {
|
||||
t = t.SuperView;
|
||||
}
|
||||
m = ((Toplevel)t).MenuBar?.Visible == true;
|
||||
@@ -657,7 +660,7 @@ namespace Terminal.Gui {
|
||||
sb = Application.Top.StatusBar;
|
||||
} else {
|
||||
var t = top.SuperView;
|
||||
while (!(t is Toplevel)) {
|
||||
while (t is not Toplevel) {
|
||||
t = t.SuperView;
|
||||
}
|
||||
s = ((Toplevel)t).StatusBar?.Visible == true;
|
||||
@@ -669,9 +672,11 @@ namespace Terminal.Gui {
|
||||
l = s ? top.SuperView.Frame.Height - 1 : top.SuperView.Frame.Height;
|
||||
}
|
||||
ny = Math.Min (ny, l);
|
||||
ny = ny + top.Frame.Height >= l ? Math.Max (l - top.Frame.Height, m ? 1 : 0) : ny;
|
||||
if (ny + mfLength > top.Frame.Y + top.Frame.Height) {
|
||||
ny = Math.Max (top.Frame.Bottom - mfLength, 0);
|
||||
if (top.Frame.Height <= l) {
|
||||
ny = ny + top.Frame.Height >= l ? Math.Max (l - top.Frame.Height, m ? 1 : 0) : ny;
|
||||
if (ny + mfLength > top.Frame.Y + top.Frame.Height) {
|
||||
ny = Math.Max (top.Frame.Bottom - mfLength, 0);
|
||||
}
|
||||
}
|
||||
//System.Diagnostics.Debug.WriteLine ($"ny:{ny}, rHeight:{rHeight}");
|
||||
|
||||
@@ -698,15 +703,15 @@ namespace Terminal.Gui {
|
||||
var superView = EnsureVisibleBounds (top, top.Frame.X, top.Frame.Y,
|
||||
out int nx, out int ny, out _, out StatusBar sb);
|
||||
bool layoutSubviews = false;
|
||||
if ((top?.SuperView != null || (top != Application.Top && top.Modal)
|
||||
if ((superView != top || top?.SuperView != null || (top != Application.Top && top.Modal)
|
||||
|| (top?.SuperView == null && top.IsMdiChild))
|
||||
&& (nx > top.Frame.X || ny > top.Frame.Y) && top.LayoutStyle == LayoutStyle.Computed) {
|
||||
&& (top.Frame.X + top.Frame.Width > Driver.Cols || ny > top.Frame.Y) && top.LayoutStyle == LayoutStyle.Computed) {
|
||||
|
||||
if ((top.X == null || top.X is Pos.PosAbsolute) && top.Bounds.X != nx) {
|
||||
if ((top.X == null || top.X is Pos.PosAbsolute) && top.Frame.X != nx) {
|
||||
top.X = nx;
|
||||
layoutSubviews = true;
|
||||
}
|
||||
if ((top.Y == null || top.Y is Pos.PosAbsolute) && top.Bounds.Y != ny) {
|
||||
if ((top.Y == null || top.Y is Pos.PosAbsolute) && top.Frame.Y != ny) {
|
||||
top.Y = ny;
|
||||
layoutSubviews = true;
|
||||
}
|
||||
@@ -994,6 +999,13 @@ namespace Terminal.Gui {
|
||||
{
|
||||
return MostFocused?.OnLeave (view) ?? base.OnLeave (view);
|
||||
}
|
||||
|
||||
///<inheritdoc/>
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
dragPosition = null;
|
||||
base.Dispose (disposing);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -149,7 +149,6 @@ namespace Terminal.Gui.TopLevelTests {
|
||||
[AutoInitShutdown]
|
||||
public void Internal_Tests ()
|
||||
{
|
||||
Toplevel.dragPosition = null; // dragPosition is `static` and must be reset for each instance or unit tests will fail?
|
||||
var top = new Toplevel ();
|
||||
|
||||
var eventInvoked = "";
|
||||
@@ -200,7 +199,7 @@ namespace Terminal.Gui.TopLevelTests {
|
||||
Application.Begin (top);
|
||||
Assert.Equal (top, Application.Top);
|
||||
|
||||
// top is Application.Top without menu and status bar.
|
||||
// Application.Top without menu and status bar.
|
||||
var supView = top.EnsureVisibleBounds (top, 2, 2, out int nx, out int ny, out MenuBar mb, out StatusBar sb);
|
||||
Assert.Equal (Application.Top, supView);
|
||||
Assert.Equal (0, nx);
|
||||
@@ -211,7 +210,7 @@ namespace Terminal.Gui.TopLevelTests {
|
||||
top.AddMenuStatusBar (new MenuBar ());
|
||||
Assert.NotNull (top.MenuBar);
|
||||
|
||||
// top is Application.Top with a menu and without status bar.
|
||||
// Application.Top with a menu and without status bar.
|
||||
top.EnsureVisibleBounds (top, 2, 2, out nx, out ny, out mb, out sb);
|
||||
Assert.Equal (0, nx);
|
||||
Assert.Equal (1, ny);
|
||||
@@ -221,20 +220,24 @@ namespace Terminal.Gui.TopLevelTests {
|
||||
top.AddMenuStatusBar (new StatusBar ());
|
||||
Assert.NotNull (top.StatusBar);
|
||||
|
||||
// top is Application.Top with a menu and status bar.
|
||||
// Application.Top with a menu and status bar.
|
||||
top.EnsureVisibleBounds (top, 2, 2, out nx, out ny, out mb, out sb);
|
||||
Assert.Equal (0, nx);
|
||||
Assert.Equal (1, ny);
|
||||
// The available height is lower than the Application.Top height minus
|
||||
// the menu bar and status bar, then the top can go beyond the bottom
|
||||
Assert.Equal (2, ny);
|
||||
Assert.NotNull (mb);
|
||||
Assert.NotNull (sb);
|
||||
|
||||
top.RemoveMenuStatusBar (top.MenuBar);
|
||||
Assert.Null (top.MenuBar);
|
||||
|
||||
// top is Application.Top without a menu and with a status bar.
|
||||
// Application.Top without a menu and with a status bar.
|
||||
top.EnsureVisibleBounds (top, 2, 2, out nx, out ny, out mb, out sb);
|
||||
Assert.Equal (0, nx);
|
||||
Assert.Equal (0, ny);
|
||||
// The available height is lower than the Application.Top height minus
|
||||
// the status bar, then the top can go beyond the bottom
|
||||
Assert.Equal (2, ny);
|
||||
Assert.Null (mb);
|
||||
Assert.NotNull (sb);
|
||||
|
||||
@@ -252,7 +255,7 @@ namespace Terminal.Gui.TopLevelTests {
|
||||
supView = win.EnsureVisibleBounds (win, 0, 0, out nx, out ny, out mb, out sb);
|
||||
Assert.Equal (Application.Top, supView);
|
||||
|
||||
// top is Application.Top without menu and status bar.
|
||||
// Application.Top without menu and status bar.
|
||||
top.EnsureVisibleBounds (win, 0, 0, out nx, out ny, out mb, out sb);
|
||||
Assert.Equal (0, nx);
|
||||
Assert.Equal (0, ny);
|
||||
@@ -262,7 +265,7 @@ namespace Terminal.Gui.TopLevelTests {
|
||||
top.AddMenuStatusBar (new MenuBar ());
|
||||
Assert.NotNull (top.MenuBar);
|
||||
|
||||
// top is Application.Top with a menu and without status bar.
|
||||
// Application.Top with a menu and without status bar.
|
||||
top.EnsureVisibleBounds (win, 2, 2, out nx, out ny, out mb, out sb);
|
||||
Assert.Equal (0, nx);
|
||||
Assert.Equal (1, ny);
|
||||
@@ -272,10 +275,12 @@ namespace Terminal.Gui.TopLevelTests {
|
||||
top.AddMenuStatusBar (new StatusBar ());
|
||||
Assert.NotNull (top.StatusBar);
|
||||
|
||||
// top is Application.Top with a menu and status bar.
|
||||
// Application.Top with a menu and status bar.
|
||||
top.EnsureVisibleBounds (win, 30, 20, out nx, out ny, out mb, out sb);
|
||||
Assert.Equal (0, nx);
|
||||
Assert.Equal (1, ny);
|
||||
// The available height is lower than the Application.Top height minus
|
||||
// the menu bar and status bar, then the top can go beyond the bottom
|
||||
Assert.Equal (20, ny);
|
||||
Assert.NotNull (mb);
|
||||
Assert.NotNull (sb);
|
||||
|
||||
@@ -289,7 +294,7 @@ namespace Terminal.Gui.TopLevelTests {
|
||||
win = new Window () { Width = 60, Height = 15 };
|
||||
top.Add (win);
|
||||
|
||||
// top is Application.Top without menu and status bar.
|
||||
// Application.Top without menu and status bar.
|
||||
top.EnsureVisibleBounds (win, 0, 0, out nx, out ny, out mb, out sb);
|
||||
Assert.Equal (0, nx);
|
||||
Assert.Equal (0, ny);
|
||||
@@ -299,7 +304,7 @@ namespace Terminal.Gui.TopLevelTests {
|
||||
top.AddMenuStatusBar (new MenuBar ());
|
||||
Assert.NotNull (top.MenuBar);
|
||||
|
||||
// top is Application.Top with a menu and without status bar.
|
||||
// Application.Top with a menu and without status bar.
|
||||
top.EnsureVisibleBounds (win, 2, 2, out nx, out ny, out mb, out sb);
|
||||
Assert.Equal (2, nx);
|
||||
Assert.Equal (2, ny);
|
||||
@@ -309,7 +314,7 @@ namespace Terminal.Gui.TopLevelTests {
|
||||
top.AddMenuStatusBar (new StatusBar ());
|
||||
Assert.NotNull (top.StatusBar);
|
||||
|
||||
// top is Application.Top with a menu and status bar.
|
||||
// Application.Top with a menu and status bar.
|
||||
top.EnsureVisibleBounds (win, 30, 20, out nx, out ny, out mb, out sb);
|
||||
Assert.Equal (20, nx); // 20+60=80
|
||||
Assert.Equal (9, ny); // 9+15+1(mb)=25
|
||||
@@ -1213,5 +1218,151 @@ namespace Terminal.Gui.TopLevelTests {
|
||||
});
|
||||
Assert.Equal (scrollView, Application.MouseGrabView);
|
||||
}
|
||||
|
||||
[Fact, AutoInitShutdown]
|
||||
public void Dialog_Bounds_Bigger_Than_Driver_Cols_And_Rows_Allow_Drag_Beyond_Left_Right_And_Bottom ()
|
||||
{
|
||||
var menu = new MenuBar (new MenuBarItem [] {
|
||||
new MenuBarItem("File", new MenuItem [] {
|
||||
new MenuItem("New", "", null)
|
||||
})
|
||||
});
|
||||
|
||||
var sb = new StatusBar (new StatusItem [] {
|
||||
new StatusItem(Key.N, "~CTRL-N~ New", null)
|
||||
});
|
||||
var top = Application.Top;
|
||||
top.Add (menu, sb);
|
||||
var dialog = new Dialog ("Dialog", 20, 3, new Button ("Ok"));
|
||||
Application.Begin (top);
|
||||
((FakeDriver)Application.Driver).SetBufferSize (40, 10);
|
||||
Application.Begin (dialog);
|
||||
Application.Refresh ();
|
||||
Assert.Equal (new Rect (0, 0, 40, 10), top.Frame);
|
||||
Assert.Equal (new Rect (10, 3, 20, 3), dialog.Frame);
|
||||
TestHelpers.AssertDriverContentsWithFrameAre (@"
|
||||
File
|
||||
|
||||
|
||||
┌ Dialog ──────────┐
|
||||
│ [ Ok ] │
|
||||
└──────────────────┘
|
||||
|
||||
|
||||
|
||||
CTRL-N New ", output);
|
||||
|
||||
Assert.Null (Application.MouseGrabView);
|
||||
|
||||
ReflectionTools.InvokePrivate (
|
||||
typeof (Application),
|
||||
"ProcessMouseEvent",
|
||||
new MouseEvent () {
|
||||
X = 10,
|
||||
Y = 3,
|
||||
Flags = MouseFlags.Button1Pressed
|
||||
});
|
||||
|
||||
Assert.Equal (dialog, Application.MouseGrabView);
|
||||
|
||||
ReflectionTools.InvokePrivate (
|
||||
typeof (Application),
|
||||
"ProcessMouseEvent",
|
||||
new MouseEvent () {
|
||||
X = -11,
|
||||
Y = -4,
|
||||
Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
|
||||
});
|
||||
|
||||
Application.Refresh ();
|
||||
Assert.Equal (new Rect (0, 0, 40, 10), top.Frame);
|
||||
Assert.Equal (new Rect (0, 1, 20, 3), dialog.Frame);
|
||||
TestHelpers.AssertDriverContentsWithFrameAre (@"
|
||||
File
|
||||
┌ Dialog ──────────┐
|
||||
│ [ Ok ] │
|
||||
└──────────────────┘
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
CTRL-N New ", output);
|
||||
|
||||
// Changes Top size to same size as Dialog more menu and scroll bar
|
||||
((FakeDriver)Application.Driver).SetBufferSize (20, 5);
|
||||
ReflectionTools.InvokePrivate (
|
||||
typeof (Application),
|
||||
"ProcessMouseEvent",
|
||||
new MouseEvent () {
|
||||
X = -1,
|
||||
Y = -1,
|
||||
Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
|
||||
});
|
||||
|
||||
Application.Refresh ();
|
||||
Assert.Equal (new Rect (0, 0, 20, 5), top.Frame);
|
||||
Assert.Equal (new Rect (0, 1, 20, 3), dialog.Frame);
|
||||
TestHelpers.AssertDriverContentsWithFrameAre (@"
|
||||
File
|
||||
┌ Dialog ──────────┐
|
||||
│ [ Ok ] │
|
||||
└──────────────────┘
|
||||
CTRL-N New ", output);
|
||||
|
||||
// Changes Top size smaller than Dialog size
|
||||
((FakeDriver)Application.Driver).SetBufferSize (19, 3);
|
||||
ReflectionTools.InvokePrivate (
|
||||
typeof (Application),
|
||||
"ProcessMouseEvent",
|
||||
new MouseEvent () {
|
||||
X = -1,
|
||||
Y = -1,
|
||||
Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
|
||||
});
|
||||
|
||||
Application.Refresh ();
|
||||
Assert.Equal (new Rect (0, 0, 19, 3), top.Frame);
|
||||
Assert.Equal (new Rect (-1, 1, 20, 3), dialog.Frame);
|
||||
TestHelpers.AssertDriverContentsWithFrameAre (@"
|
||||
File
|
||||
Dialog ──────────┐
|
||||
[ Ok ] │", output);
|
||||
|
||||
ReflectionTools.InvokePrivate (
|
||||
typeof (Application),
|
||||
"ProcessMouseEvent",
|
||||
new MouseEvent () {
|
||||
X = 18,
|
||||
Y = 3,
|
||||
Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
|
||||
});
|
||||
|
||||
Application.Refresh ();
|
||||
Assert.Equal (new Rect (0, 0, 19, 3), top.Frame);
|
||||
Assert.Equal (new Rect (18, 2, 20, 3), dialog.Frame);
|
||||
TestHelpers.AssertDriverContentsWithFrameAre (@"
|
||||
File
|
||||
|
||||
CTRL-N New ┌", output);
|
||||
|
||||
// On a real app we can't go beyond the SuperView bounds
|
||||
ReflectionTools.InvokePrivate (
|
||||
typeof (Application),
|
||||
"ProcessMouseEvent",
|
||||
new MouseEvent () {
|
||||
X = 19,
|
||||
Y = 4,
|
||||
Flags = MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition
|
||||
});
|
||||
|
||||
Application.Refresh ();
|
||||
Assert.Equal (new Rect (0, 0, 19, 3), top.Frame);
|
||||
Assert.Equal (new Rect (19, 2, 20, 3), dialog.Frame);
|
||||
TestHelpers.AssertDriverContentsWithFrameAre (@"
|
||||
File
|
||||
|
||||
CTRL-N New", output);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user