Files
Terminal.Gui/UICatalog/Scenarios/CenteredWindowInsideWindow.cs
BDisp 3e1637aac8 Fixes #2775. Something in 1.13 broke centering child windows. (#2778)
* Fixes #2776. Pressing Alt key on a Window with only a MenuBar throws System.InvalidOperationException.

* Add unit test.

* Fix extra bracket.

* Prevents throw exception if Application.Current is null.

* Fix unit test because OnLeave is now invoked on toplevel removing, preventing two views having focus.

* Fix unit test method name.

* Fix Window by not layout on his subviews when adding a new view after the Application.Begin was already running.

* FindAndOpenMenuByHotkey now search inside Menus and inside his Children.

* Add unit test for Window LayoutSubviews and FindAndOpenChildrenMenuByHotkey menu method.

* Prevents button to be clear when it's invisible.

* Fixes 2780. Moving a Window that is Application.Top shouldn't be allowed.

* Fix condition if Window and Application.Top.

* Always LayoutSubviews and PositionToplevels after Clear.

* Fixes #2787. MenuItem with CanExecute returning false is select when a MenuBar is opened.

* Leveraging the power of CanExecute feature.

* Fixes #2789. StatusItem should have a disabled attribute if it can't execute.

* Allows positioning a child window outside the limits of the menu and the status bar.

* Change to a more appropriate name.

* Simplifies all the run actions.

* Prevents open menu bar if it's invisible and close all opened menus.

* Fix mdi run loop.

* Fix hot key on mdi toplevels.

* Fix position on mdi toplevels.

* Fix Top.Redraw by set state.Toplevel.SetNeedsDisplay if it's needed to redraw.

* Fix MdiTop by repainted when a keystroke is generated by keyboard.

* Rename local fields.

* Force redraw if application.Top needs display.

* Added more features to the scenario.

* Change the scenarios to run as Application.Top instead of sub-views.

* Add a new scenario similar but as Mdi Container.

* Add a bunch of new unit tests to prove all this PR.

* Only it's need to redraw Application.Top if it's a Mdi Container.

* Remove unnecessary code.

* Unit test that proves that a MDI child leaves no trace when the location is changed.

* Removes unnecessary Application.Init because theses uses Run<T> which already call it.

* Ensures a menu bar been closed after run an action.

* Ensures that another view can be focused if not IsMenuOpen and LastFocused is null, instead of focused the menu itself.

* Ensures a focused contentview subview being focused if MostFocused is null.

* Ensures a MdiTop subview to have priority if it's focused and thus  make it Current.

* Allow a MdiChild be closed when pressing Application.QuitKey.

* More unit tests proving the changes.

* Ensures the top.MostFocused is focused.

* Ensures MdiChild on the front if MdiTop.MostFocused isn't valid, like ContentView.

* Add unit test showing MdiChild on the front.

* Fix an issue where NullReferenceException can be throws everywhere while get the Application.MdiChildes property.

---------

Co-authored-by: Tig <tig@users.noreply.github.com>
2023-10-17 13:34:28 -04:00

314 lines
11 KiB
C#

using Terminal.Gui;
namespace UICatalog.Scenarios {
[ScenarioMetadata (Name: "CenteredWindowInsideWindow", Description: "Centered Window Inside Window")]
[ScenarioCategory ("Controls")]
public class CenteredWindowInsideWindow : Scenario {
public override void Init (ColorScheme colorScheme)
{
Application.Run<ParentWindowClass> ();
Application.Shutdown ();
}
public override void Run ()
{
}
}
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by:
// TerminalGuiDesigner v1.0.24.0
// You can make changes to this file and they will not be overwritten when saving.
// </auto-generated>
// -----------------------------------------------------------------------------
public partial class ParentWindowClass {
private ChildWindowClass _childWindow;
public ParentWindowClass ()
{
InitializeComponent ();
// MenuBar
createChildMenuItem.CanExecute = CanExecuteCreateChildWindow;
createChildMenuItem.Action = CreateChildWindow;
centerChildMenuItem.CanExecute = CanExecuteCenterChildWindow;
centerChildMenuItem.Action = CenterChildWindow;
hideShowChildMenuItem.CanExecute = CanExecuteHideShowChildWindow;
hideShowChildMenuItem.Action = HideShowChildWindow;
borderChildMenuItem.CanExecute = CanExecuteCenterChildWindow;
borderChildMenuItem.Action = BorderToggleChildWindow;
parentMenu.Action = BorderToggleParentWindow;
// StatusBar
createChildStatusItem.CanExecute = CanExecuteCreateChildWindow;
createChildStatusItem.Action = CreateChildWindow;
centerChildStatusItem.CanExecute = CanExecuteCenterChildWindow;
centerChildStatusItem.Action = CenterChildWindow;
hideShowChildStatusItem.CanExecute = CanExecuteHideShowChildWindow;
hideShowChildStatusItem.Action = HideShowChildWindow;
borderChildStatusItem.CanExecute = CanExecuteCenterChildWindow;
borderChildStatusItem.Action = BorderToggleChildWindow;
borderParentStatusItem.Action = BorderToggleParentWindow;
KeyPress += ParentWindowClass_KeyPress;
}
private void BorderToggleParentWindow ()
{
if (Border.BorderStyle == BorderStyle.None) {
Border.BorderStyle = BorderStyle.Single;
// MenuBar
parentMenu.Title = "Borderless _Parent";
// StatusBar
borderParentStatusItem.Title = "~CTRL-F1~ Borderless Parent";
} else {
Border.BorderStyle = BorderStyle.None;
Border.DrawMarginFrame = false;
// MenuBar
parentMenu.Title = "Border _Parent";
// StatusBar
borderParentStatusItem.Title = "~CTRL-F1~ Border Parent";
}
}
private void BorderToggleChildWindow ()
{
if (_childWindow.Border.BorderStyle == BorderStyle.None) {
_childWindow.Border.BorderStyle = BorderStyle.Single;
// MenuBar
borderChildMenuItem.Title = "_Borderless Child";
// StatusBar
borderChildStatusItem.Title = "~CTRL-F2~ Borderless Child";
} else {
_childWindow.Border.BorderStyle = BorderStyle.None;
_childWindow.Border.DrawMarginFrame = false;
// MenuBar
borderChildMenuItem.Title = "_Border Child";
// StatusBar
borderChildStatusItem.Title = "~CTRL-F2~ Border Child";
}
}
private void ParentWindowClass_KeyPress (KeyEventEventArgs obj)
{
switch (obj.KeyEvent.Key) {
case Key.F8:
menuBar.Visible = !menuBar.Visible;
obj.Handled = true;
break;
case Key.F10:
statusBar.Visible = !statusBar.Visible;
obj.Handled = true;
break;
}
}
private bool CanExecuteCreateChildWindow () => _childWindow == null;
private void CreateChildWindow ()
{
_childWindow ??= new ChildWindowClass ();
Add (_childWindow);
}
private bool CanExecuteCenterChildWindow () => _childWindow != null && _childWindow.Visible;
private void CenterChildWindow ()
{
_childWindow.X = Pos.Center ();
_childWindow.Y = Pos.Center ();
_childWindow.SetNeedsDisplay ();
}
private bool CanExecuteHideShowChildWindow () => _childWindow != null;
private void HideShowChildWindow ()
{
if (_childWindow.Visible) {
_childWindow.Visible = false;
// MenuBar
hideShowChildMenuItem.Title = "Un_Hide Child";
// StatusBar
hideShowChildStatusItem.Title = "~CTRL-F7~ UnHide Child";
} else {
_childWindow.Visible = true;
// MenuBar
hideShowChildMenuItem.Title = "_Hide Child";
// StatusBar
hideShowChildStatusItem.Title = "~CTRL-F7~ Hide Child";
}
}
}
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by:
// TerminalGuiDesigner v1.0.24.0
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
// -----------------------------------------------------------------------------
public partial class ParentWindowClass : Terminal.Gui.Window {
private Terminal.Gui.MenuBar menuBar;
private Terminal.Gui.MenuBarItem childMenu;
private Terminal.Gui.MenuItem createChildMenuItem;
private Terminal.Gui.MenuItem centerChildMenuItem;
private Terminal.Gui.MenuItem hideShowChildMenuItem;
private Terminal.Gui.MenuItem borderChildMenuItem;
private Terminal.Gui.MenuBarItem parentMenu;
private Terminal.Gui.StatusBar statusBar;
private Terminal.Gui.StatusItem createChildStatusItem;
private Terminal.Gui.StatusItem centerChildStatusItem;
private Terminal.Gui.StatusItem hideShowChildStatusItem;
private Terminal.Gui.StatusItem borderChildStatusItem;
private Terminal.Gui.StatusItem borderParentStatusItem;
private void InitializeComponent ()
{
this.menuBar = new Terminal.Gui.MenuBar ();
this.Width = Dim.Fill (0);
this.Height = Dim.Fill (0);
this.X = 0;
this.Y = 0;
this.Modal = false;
this.Border.BorderStyle = Terminal.Gui.BorderStyle.Single;
this.Border.BorderBrush = Terminal.Gui.Color.White;
this.Border.Effect3D = false;
this.Border.Effect3DBrush = null;
this.Border.DrawMarginFrame = true;
this.TextAlignment = Terminal.Gui.TextAlignment.Left;
this.Title = "Parent Window (Press F8 to Hide/Show MenuBar)(Press F10 to Hide/Show StatusBar)";
this.menuBar.Width = Dim.Fill (0);
this.menuBar.Height = 1;
this.menuBar.X = 0;
this.menuBar.Y = 0;
this.menuBar.Data = "menuBar";
this.menuBar.TextAlignment = Terminal.Gui.TextAlignment.Left;
this.childMenu = new Terminal.Gui.MenuBarItem ();
this.childMenu.Title = "Ch_ild";
this.parentMenu = new Terminal.Gui.MenuBarItem ();
this.parentMenu.Title = "Borderless _Parent";
this.menuBar.Menus = new Terminal.Gui.MenuBarItem [] {
this.childMenu, this.parentMenu};
this.createChildMenuItem = new Terminal.Gui.MenuItem ();
this.createChildMenuItem.Title = "_Create Child";
this.createChildMenuItem.Data = "createChildMenuItem";
this.centerChildMenuItem = new Terminal.Gui.MenuItem ();
this.centerChildMenuItem.Title = "C_enter Child";
this.centerChildMenuItem.Data = "centerChildMenuItem";
this.hideShowChildMenuItem = new Terminal.Gui.MenuItem ();
this.hideShowChildMenuItem.Title = "_Hide Child";
this.hideShowChildMenuItem.Data = "hideChildMenuItem";
this.borderChildMenuItem = new Terminal.Gui.MenuItem ();
this.borderChildMenuItem.Title = "_Borderless Child";
this.borderChildMenuItem.Data = "borderChildMenuItem";
this.childMenu.Children = new Terminal.Gui.MenuItem [] {
this.createChildMenuItem, this.centerChildMenuItem, this.hideShowChildMenuItem, this.borderChildMenuItem};
this.Add (this.menuBar);
this.statusBar = new Terminal.Gui.StatusBar ();
this.statusBar.Width = Dim.Fill ();
this.statusBar.Height = 1;
this.statusBar.X = 0;
this.statusBar.Y = Pos.AnchorEnd (1);
this.statusBar.Data = "statusBar";
this.statusBar.TextAlignment = Terminal.Gui.TextAlignment.Left;
this.createChildStatusItem = new Terminal.Gui.StatusItem (Key.F5 | Key.CtrlMask, "~CTRL-F5~ Create Child", null);
this.createChildStatusItem.Data = "createChildStatusItem";
this.centerChildStatusItem = new Terminal.Gui.StatusItem (Key.F6 | Key.CtrlMask, "~CTRL-F6~ Center Child", null);
this.centerChildStatusItem.Data = "centerChildStatusItem";
this.hideShowChildStatusItem = new Terminal.Gui.StatusItem (Key.F7 | Key.CtrlMask, "~CTRL-F7~ Hide Child", null);
this.hideShowChildStatusItem.Data = "hideChildStatusItem";
this.borderChildStatusItem = new Terminal.Gui.StatusItem (Key.F2 | Key.CtrlMask, "~CTRL-F2~ Borderless Child", null);
this.borderChildStatusItem.Data = "borderChildStatusItem";
this.borderParentStatusItem = new Terminal.Gui.StatusItem (Key.F1 | Key.CtrlMask, "~CTRL-F1~ Borderless Parent", null);
this.borderParentStatusItem.Data = "borderParentStatusItem";
this.statusBar.Items = new StatusItem [] {
this.createChildStatusItem, this.centerChildStatusItem, this.hideShowChildStatusItem, this.borderChildStatusItem, this.borderParentStatusItem};
this.Add (statusBar);
}
}
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by:
// TerminalGuiDesigner v1.0.24.0
// You can make changes to this file and they will not be overwritten when saving.
// </auto-generated>
// -----------------------------------------------------------------------------
public partial class ChildWindowClass {
public ChildWindowClass ()
{
InitializeComponent ();
this.button1.Clicked += Button1_Clicked;
}
private void Button1_Clicked ()
{
Terminal.Gui.MessageBox.Query ("Press Me", "I hope you like the child window behavior!", "Ok");
}
}
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by:
// TerminalGuiDesigner v1.0.24.0
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
// -----------------------------------------------------------------------------
public partial class ChildWindowClass : Terminal.Gui.Window {
private Terminal.Gui.Button button1;
private Terminal.Gui.Label Label1;
private Terminal.Gui.Label Label2;
private Terminal.Gui.Label Label3;
private Terminal.Gui.Label Label4;
private void InitializeComponent ()
{
this.Width = 80;
this.Height = 16;
this.X = Pos.Center ();
this.Y = Pos.Center ();
this.ColorScheme = Colors.TopLevel;
this.Modal = false;
this.Border.BorderStyle = Terminal.Gui.BorderStyle.Single;
this.Border.BorderBrush = Terminal.Gui.Color.White;
this.Border.Effect3D = false;
this.Border.Effect3DBrush = null;
this.Border.DrawMarginFrame = true;
this.TextAlignment = Terminal.Gui.TextAlignment.Left;
this.Title = "Child Window";
this.button1 = new Terminal.Gui.Button ();
this.button1.X = Pos.Center ();
this.button1.Y = Pos.Center ();
this.button1.Text = "Press Me";
this.Label1 = new Terminal.Gui.Label ("TL");
this.Label2 = new Terminal.Gui.Label ("TR");
this.Label2.X = Pos.AnchorEnd (2);
this.Label3 = new Terminal.Gui.Label ("BL");
this.Label3.Y = Pos.AnchorEnd (1);
this.Label4 = new Terminal.Gui.Label ("BR");
this.Label4.X = Pos.AnchorEnd (2);
this.Label4.Y = Pos.AnchorEnd (1);
this.Add (this.button1, this.Label1, this.Label2, this.Label3, this.Label4);
}
}
}