diff --git a/doc/changelog.txt b/doc/changelog.txt index 8d04d70f..13866aba 100644 --- a/doc/changelog.txt +++ b/doc/changelog.txt @@ -3,8 +3,9 @@ ConsoleTools Note: For any bug or feature request please add a new issue on GitHub: https://github.com/lastunicorn/ConsoleTools/issues/new/choose -ver 1.3.0 +ver 1.2.1 --------- +- [bugfix ] ScrollMenu: Failing to leave the cursor below the menu when the menu was closing. ver 1.2.0 diff --git a/release/ConsoleTools.proj b/release/ConsoleTools.proj index c1c4b39d..91d31e6a 100644 --- a/release/ConsoleTools.proj +++ b/release/ConsoleTools.proj @@ -5,7 +5,7 @@ output temp - 1.3.0 + 1.2.1 ConsoleTools-$(Version).zip .. diff --git a/sources/ConsoleTools/AssemblyInfo.Shared.cs b/sources/ConsoleTools/AssemblyInfo.Shared.cs index dec601e2..054d2cde 100644 --- a/sources/ConsoleTools/AssemblyInfo.Shared.cs +++ b/sources/ConsoleTools/AssemblyInfo.Shared.cs @@ -39,5 +39,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.3.0.0")] +[assembly: AssemblyVersion("1.2.1.0")] //[assembly: AssemblyFileVersion("1.0.0.*")] \ No newline at end of file diff --git a/sources/ConsoleTools/ConsoleTools.Controls.Menus/ScrollMenu.cs b/sources/ConsoleTools/ConsoleTools.Controls.Menus/ScrollMenu.cs index 1e756ac6..d98afc0d 100644 --- a/sources/ConsoleTools/ConsoleTools.Controls.Menus/ScrollMenu.cs +++ b/sources/ConsoleTools/ConsoleTools.Controls.Menus/ScrollMenu.cs @@ -34,9 +34,16 @@ public class ScrollMenu : ErasableControl, IRepeatableSupport private const HorizontalAlignment DefaultHorizontalAlignment = HorizontalAlignment.Center; private readonly MenuItemCollection menuItems = new(); private bool closeWasRequested; - private Location menuLocation; private Location itemsLocation; + /// + /// The size of the control after it was displayed. + /// Does not include the margins + /// + private Size menuSize; + + private Size itemsSize; + /// /// Gets the item that is currently selected. /// @@ -71,7 +78,7 @@ public class ScrollMenu : ErasableControl, IRepeatableSupport public bool KeepHighlightingOnClose { get; set; } /// - /// Gets or sets a vlue that specifies if circular selection is allowed. + /// Gets or sets a value that specifies if circular selection is allowed. /// When reaching the first item go to the last item. /// When reaching the last item go to the first item. /// Default value: true @@ -84,7 +91,6 @@ public bool AllowWrapAround /// /// Event raised when the current instance cannot be displayed anymore and it is in the "Closed" state. - /// The must also end its display loop. /// public event EventHandler Closed; @@ -160,8 +166,6 @@ protected override void OnBeforeDisplay() throw new ApplicationException("There are no menu items to be displayed."); closeWasRequested = false; - //InnerSize = Size.Empty; - menuLocation = Location.Origin; itemsLocation = Location.Origin; //for (int i = 0; i < InnerSize.Height; i++) @@ -182,18 +186,16 @@ protected override void DoDisplayContent(ControlDisplay display) try { - menuLocation = CalculateMenuLocation(); - - Size itemsSize = CalculateItemsSize(); - //InnerSize = new Size(itemsSize.Width, InnerSize.Height + itemsSize.Height); + itemsSize = CalculateItemsSize(); + menuSize = itemsSize + new Size(Padding.Left + Padding.Right, Padding.Top + Padding.Bottom); itemsLocation = CalculateMenuLocation(); - foreach (IMenuItem menuItem in menuItems) - { - if (!menuItem.IsVisible) - continue; + IEnumerable visibleMenuItems = menuItems + .Where(x => x.IsVisible); + foreach (IMenuItem menuItem in visibleMenuItems) + { int left = itemsLocation.Left; int top = Console.CursorTop; @@ -205,6 +207,8 @@ protected override void DoDisplayContent(ControlDisplay display) Console.WriteLine(); } + itemsLocation = new Location(itemsLocation.Left, Console.CursorTop - itemsSize.Height); + if (SelectFirstByDefault) menuItems.SelectFirst(); @@ -217,7 +221,7 @@ protected override void DoDisplayContent(ControlDisplay display) menuItems.CurrentIndexChanged -= HandleCurrentIndexChanged; - int lastMenuLine = menuLocation.Top + InnerSize.Height - 1; + int lastMenuLine = itemsLocation.Top + itemsSize.Height - 1; Console.SetCursorPosition(0, lastMenuLine); Console.WriteLine(); } @@ -234,32 +238,44 @@ private void HandleCurrentIndexChanged(object sender, CurrentIndexChangedEventAr private Location CalculateMenuLocation() { - HorizontalAlignment calcualtedHorizontalAlignment = CalcualteHorizontalAlignment(); + HorizontalAlignment calculatedHorizontalAlignment = CalculateHorizontalAlignment(); int menuTop = Console.CursorTop; - switch (calcualtedHorizontalAlignment) + switch (calculatedHorizontalAlignment) { default: return new Location(0, menuTop); case HorizontalAlignment.Center: - return new Location((Console.BufferWidth - InnerSize.Width) / 2, menuTop); + { + int menuLeft = (Console.BufferWidth - menuSize.Width) / 2; + return new Location(menuLeft, menuTop); + } case HorizontalAlignment.Right: - return new Location(Console.BufferWidth - InnerSize.Width, menuTop); + { + int menuLeft = Console.BufferWidth - menuSize.Width; + return new Location(menuLeft, menuTop); + } } } private Size CalculateItemsSize() { - int menuHeight = menuItems - .Count(x => x.IsVisible); + IEnumerable visibleMenuItems = menuItems + .Where(x => x.IsVisible); + + int menuHeight = 0; + int menuWidth = 0; + + foreach (IMenuItem menuItem in visibleMenuItems) + { + menuHeight++; - int menuWidth = menuItems - .Where(x => x.IsVisible) - .Select(x => x.Size) - .Max(x => x.Width); + if (menuItem.Size.Width > menuWidth) + menuWidth = menuItem.Size.Width; + } return new Size(menuWidth, menuHeight); } @@ -276,21 +292,21 @@ private void DrawMenuItem(int index) Console.SetCursorPosition(left, top); - Size menuItemSize = new(InnerSize.Width, 1); + Size menuItemSize = new(itemsSize.Width, 1); bool isHighlighted = menuItemToDraw == menuItems.CurrentItem; menuItemToDraw.Display(menuItemSize, isHighlighted); } } - private HorizontalAlignment CalcualteHorizontalAlignment() + private HorizontalAlignment CalculateHorizontalAlignment() { - HorizontalAlignment calcualtedHorizontalAlignment = HorizontalAlignment; + HorizontalAlignment calculatedHorizontalAlignment = HorizontalAlignment; - if (calcualtedHorizontalAlignment == HorizontalAlignment.Default) - calcualtedHorizontalAlignment = DefaultHorizontalAlignment; + if (calculatedHorizontalAlignment == HorizontalAlignment.Default) + calculatedHorizontalAlignment = DefaultHorizontalAlignment; - return calcualtedHorizontalAlignment; + return calculatedHorizontalAlignment; } private void ReadUserSelection() @@ -363,11 +379,15 @@ protected override void OnAfterDisplay() { base.OnAfterDisplay(); + //int lastMenuLine = itemsLocation.Top + menuSize.Height - 1; + //Console.SetCursorPosition(0, lastMenuLine); + //Console.WriteLine(); + SelectedItem?.Command?.Execute(); } /// - /// The calls this method to announce the control that it should end its process. + /// Call this method to announce the control that it should end its process. /// public void RequestClose() { diff --git a/sources/ConsoleTools/ConsoleTools.Core/Controls/ErasableControl.cs b/sources/ConsoleTools/ConsoleTools.Core/Controls/ErasableControl.cs index 123a468f..7d9cee2b 100644 --- a/sources/ConsoleTools/ConsoleTools.Core/Controls/ErasableControl.cs +++ b/sources/ConsoleTools/ConsoleTools.Core/Controls/ErasableControl.cs @@ -28,19 +28,8 @@ namespace DustInTheWind.ConsoleTools.Controls; /// It is sometime useful for the controls that wait for an user input /// and then must get themselves out of the way. /// -/// -/// In order to be able to successfully erase the control, the inheritor must -/// calculate and set the of the control until the end -/// of the method. -/// public abstract class ErasableControl : BlockControl { - /// - /// Gets the size of the control after it was displayed. - /// Does not include the margins - /// - public Size InnerSize { get; protected set; } - /// /// Gets or sets a value that specifies if the control is erased from the Console /// after it was displayed. @@ -49,7 +38,6 @@ public abstract class ErasableControl : BlockControl /// /// When implemented by an inheritor it displays the content of the control to the console. - /// The inheritor must also calculate and set the property. /// protected abstract override void DoDisplayContent(ControlDisplay display); diff --git a/sources/ConsoleTools/ConsoleTools.Demo.ScrollMenuDemo/MainMenu.cs b/sources/ConsoleTools/ConsoleTools.Demo.ScrollMenuDemo/MainMenu.cs index ccc11428..007dac4c 100644 --- a/sources/ConsoleTools/ConsoleTools.Demo.ScrollMenuDemo/MainMenu.cs +++ b/sources/ConsoleTools/ConsoleTools.Demo.ScrollMenuDemo/MainMenu.cs @@ -16,6 +16,7 @@ using System; using System.Collections.Generic; +using DustInTheWind.ConsoleTools.Controls; using DustInTheWind.ConsoleTools.Controls.Menus; using DustInTheWind.ConsoleTools.Controls.Menus.MenuItems; using DustInTheWind.ConsoleTools.Demo.ScrollMenuDemo.Commands; @@ -28,8 +29,8 @@ public MainMenu(GameApplication application) { if (application == null) throw new ArgumentNullException(nameof(application)); - EraseAfterClose = true; Margin = "0 1"; + HorizontalAlignment = HorizontalAlignment.Center; SelectFirstByDefault = true; IEnumerable menuItems = CreateMenuItems(application); diff --git a/sources/ConsoleTools/ConsoleTools.Demo.ScrollMenuDemo/Program.cs b/sources/ConsoleTools/ConsoleTools.Demo.ScrollMenuDemo/Program.cs index 2dff6227..883aa715 100644 --- a/sources/ConsoleTools/ConsoleTools.Demo.ScrollMenuDemo/Program.cs +++ b/sources/ConsoleTools/ConsoleTools.Demo.ScrollMenuDemo/Program.cs @@ -30,9 +30,6 @@ private static void Main() { DisplayApplicationHeader(); - Console.SetWindowSize(80, 50); - Console.SetBufferSize(80, 50); - Console.CancelKeyPress += HandleCancelKeyPress; gameApplication = new GameApplication();