Skip to content

Commit

Permalink
Merge pull request #108 from lastunicorn/107-scrollmenu-consolewritel…
Browse files Browse the repository at this point in the history
…ine-whites-text-over-the-menu

107 scrollmenu consolewriteline whites text over the menu
  • Loading branch information
lastunicorn authored Sep 5, 2024
2 parents a526ee6 + 53933b8 commit 350337a
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 50 deletions.
3 changes: 2 additions & 1 deletion doc/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion release/ConsoleTools.proj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<PropertyGroup>
<OutputPath>output</OutputPath>
<TempPath>temp</TempPath>
<Version>1.3.0</Version>
<Version>1.2.1</Version>
<OutputZipFileName>ConsoleTools-$(Version).zip</OutputZipFileName>
<RepositoryRoot>..</RepositoryRoot>
</PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion sources/ConsoleTools/AssemblyInfo.Shared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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.*")]
82 changes: 51 additions & 31 deletions sources/ConsoleTools/ConsoleTools.Controls.Menus/ScrollMenu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/// <summary>
/// The size of the control after it was displayed.
/// Does not include the margins
/// </summary>
private Size menuSize;

private Size itemsSize;

/// <summary>
/// Gets the item that is currently selected.
/// </summary>
Expand Down Expand Up @@ -71,7 +78,7 @@ public class ScrollMenu : ErasableControl, IRepeatableSupport
public bool KeepHighlightingOnClose { get; set; }

/// <summary>
/// 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: <c>true</c>
Expand All @@ -84,7 +91,6 @@ public bool AllowWrapAround

/// <summary>
/// Event raised when the current instance cannot be displayed anymore and it is in the "Closed" state.
/// The <see cref="ControlRepeater"/> must also end its display loop.
/// </summary>
public event EventHandler Closed;

Expand Down Expand Up @@ -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++)
Expand All @@ -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<IMenuItem> visibleMenuItems = menuItems
.Where(x => x.IsVisible);

foreach (IMenuItem menuItem in visibleMenuItems)
{
int left = itemsLocation.Left;
int top = Console.CursorTop;

Expand All @@ -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();

Expand All @@ -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();
}
Expand All @@ -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<IMenuItem> 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);
}
Expand All @@ -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()
Expand Down Expand Up @@ -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();
}

/// <summary>
/// The <see cref="ControlRepeater"/> 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.
/// </summary>
public void RequestClose()
{
Expand Down
12 changes: 0 additions & 12 deletions sources/ConsoleTools/ConsoleTools.Core/Controls/ErasableControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
/// </summary>
/// <remarks>
/// In order to be able to successfully erase the control, the inheritor must
/// calculate and set the <see cref="InnerSize"/> of the control until the end
/// of the <see cref="BlockControl.DoDisplayContent"/> method.
/// </remarks>
public abstract class ErasableControl : BlockControl
{
/// <summary>
/// Gets the size of the control after it was displayed.
/// Does not include the margins
/// </summary>
public Size InnerSize { get; protected set; }

/// <summary>
/// Gets or sets a value that specifies if the control is erased from the Console
/// after it was displayed.
Expand All @@ -49,7 +38,6 @@ public abstract class ErasableControl : BlockControl

/// <summary>
/// When implemented by an inheritor it displays the content of the control to the console.
/// The inheritor must also calculate and set the <see cref="InnerSize"/> property.
/// </summary>
protected abstract override void DoDisplayContent(ControlDisplay display);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<IMenuItem> menuItems = CreateMenuItems(application);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@ private static void Main()
{
DisplayApplicationHeader();

Console.SetWindowSize(80, 50);
Console.SetBufferSize(80, 50);

Console.CancelKeyPress += HandleCancelKeyPress;

gameApplication = new GameApplication();
Expand Down

0 comments on commit 350337a

Please sign in to comment.