Пример #1
0
        /// <summary>
        /// Sets the prefix keys used by the collection from one of the <see cref="MenuLabeling"/> values.
        /// </summary>
        /// <param name="label">The set of prefix keys to use.</param>
        public void SetKeys(MenuLabeling label)
        {
            switch (label)
            {
            case MenuLabeling.None: SetKeys(new char[0]); break;

            case MenuLabeling.Numbers: SetKeys(GetRange('1', '9')); break;

            case MenuLabeling.Letters: SetKeys(GetRange('a', 'z')); break;

            case MenuLabeling.LettersUpper: SetKeys(GetRange('A', 'Z')); break;

            case MenuLabeling.NumbersAndLetters: SetKeys(GetRange('1', '9').Concat(GetRange('a', 'z'))); break;

            case MenuLabeling.NumbersAndLettersUpper: SetKeys(GetRange('1', '9').Concat(GetRange('A', 'Z'))); break;
            }
        }
Пример #2
0
        /// <summary>
        /// Displays a menu where a enumeration value of type <typeparamref name="TEnum"/> can be selected.
        /// </summary>
        /// <typeparam name="TEnum">The type of the enum.</typeparam>
        /// <param name="console">The console on which the action is carried out.</param>
        /// <param name="keySelector">A function that gets the <see cref="ConsoleString"/> that should be displayed for each enum value.</param>
        /// <param name="labeling">The type of labeling (option prefix) that should be applied when displaying the menu.</param>
        /// <param name="cleanup">The cleanup applied after displaying the menu.</param>
        /// <param name="allowflags">If set to <c>true</c> a combination of values can be selected; otherwise only a single value can be selected.
        /// <c>null</c> indicates that multiple values can be selected if the type has the <see cref="FlagsAttribute"/>.
        /// </param>
        /// <returns>The selected <typeparamref name="TEnum"/> value.</returns>
        public static TEnum MenuSelectEnum <TEnum>(this IConsole console, Func <TEnum, ConsoleString> keySelector = null, MenuLabeling labeling = MenuLabeling.NumbersAndLetters, MenuCleanup cleanup = MenuCleanup.None, bool?allowflags = null)
        {
            var typeinfo = typeof(TEnum).GetTypeInfo();

            if (!typeinfo.IsEnum)
            {
                throw new ArgumentException($"The {nameof(MenuSelectEnum)} method only support Enum types as type-parameter.");
            }

            if (!allowflags.HasValue)
            {
                allowflags = typeinfo.GetCustomAttribute <FlagsAttribute>(false) != null;
            }

            var values = (TEnum[])Enum.GetValues(typeof(TEnum));

            Func <IEnumerable <TEnum>, TEnum> merge = x =>
            {
                int val = (int)Convert.ChangeType(x.First(), typeof(int));
                foreach (var v in x.Skip(1))
                {
                    val |= (int)Convert.ChangeType(v, typeof(int));
                }

                return((TEnum)Enum.ToObject(typeof(TEnum), val));
            };

            if (allowflags.Value)
            {
                var selection = console.MenuSelectMultiple(values, isSelectionValid: x => x.Count() >= 1, onKeySelector: keySelector, labeling: labeling, cleanup: cleanup == MenuCleanup.RemoveMenuShowChoice ? MenuCleanup.RemoveMenu : cleanup);

                if (cleanup == MenuCleanup.RemoveMenuShowChoice)
                {
                    for (int i = 0; i < selection.Length; i++)
                    {
                        if (i > 0)
                        {
                            console.Render(", ");
                        }
                        console.Render(selection[i].ToString());
                    }
                    console.WriteLine();
                }

                long val = (long)Convert.ChangeType(selection[0], typeof(long));
                for (int i = 1; i < selection.Length; i++)
                {
                    val |= (long)Convert.ChangeType(selection[i], typeof(long));
                }

                return((TEnum)Enum.ToObject(typeof(TEnum), val));
            }
            else
            {
                return(console.MenuSelect(values, keySelector, labeling, cleanup));
            }
        }
Пример #3
0
 /// <summary>
 /// Displays a menu where a set of elements can be selected from the collection.
 /// Displays the key part of each element in the menu and returns the selected value part.
 /// </summary>
 /// <typeparam name="TKey">The type of the Key part of elements in <paramref name="collection"/>.</typeparam>
 /// <typeparam name="TValue">The type of the Value part of elements in <paramref name="collection"/>.</typeparam>
 /// <param name="isSelectionValid">A function that determines if the current selected collection is a valid selection. If the function returns <c>true</c> the done option is enabled.</param>
 /// <param name="collection">The collection of elements from which the menu should be created.</param>
 /// <param name="selected">A function that returns a boolean value indicating if an element should be pre-selected when the menu is displayed.</param>
 /// <param name="labeling">The type of labeling (option prefix) that should be applied when displaying the menu.</param>
 /// <param name="cleanup">The cleanup applied after displaying the menu.</param>
 /// <param name="doneText">The <see cref="ConsoleString"/> that is displayed as the bottommost option in the menu. Selecting this option will cause the function to return.</param>
 /// <returns>The elements that were selected using the displayed menu.</returns>
 public static TValue[] MenuSelectMultiple <TKey, TValue>(this IConsole console, IEnumerable <KeyValuePair <TKey, TValue> > collection, Func <IEnumerable <TValue>, bool> isSelectionValid = null, Func <KeyValuePair <TKey, TValue>, bool> selected = null, MenuLabeling labeling = MenuLabeling.NumbersAndLetters, MenuCleanup cleanup = MenuCleanup.None, ConsoleString doneText = null)
 {
     return(MenuSelectMultiple(console, collection, selection => isSelectionValid(selection.Select(x => x.Value)), null, null, selected, labeling, cleanup, doneText).Select(x => x.Value).ToArray());
 }
Пример #4
0
        /// <summary>
        /// Displays a menu where a single element can be selected from the collection.
        /// </summary>
        /// <typeparam name="T">The type of the elements in <paramref name="collection"/>.</typeparam>
        /// <param name="collection">The collection of element from which the menu should be created.</param>
        /// <param name="keySelector">A function that gets the <see cref="ConsoleString"/> that should be displayed for an item in the collection.</param>
        /// <param name="labeling">The type of labeling (option prefix) that should be applied when displaying the menu.</param>
        /// <param name="cleanup">The cleanup applied after displaying the menu.</param>
        /// <param name="cancelKey">If not <c>null</c>, this string is displayed as a "cancel option" in the bottom of the menu.
        /// <paramref name="cancelValue"/> will be returned if this option is selected.</param>
        /// <param name="cancelValue">The value returned if <paramref name="cancelKey"/> is not <c>null</c>.</param>
        /// <returns>The element that was selected using the displayed menu.</returns>
        public static T MenuSelect <T>(this IConsole console, IEnumerable <T> collection, Func <T, ConsoleString> keySelector = null, MenuLabeling labeling = MenuLabeling.NumbersAndLetters, MenuCleanup cleanup = MenuCleanup.None, ConsoleString cancelKey = null, T cancelValue = default(T))
        {
            if (collection == null)
            {
                throw new ArgumentNullException(nameof(collection));
            }
            if (!collection.Any())
            {
                throw new ArgumentOutOfRangeException(nameof(collection), $"{nameof(MenuSelect)} can not on be executed on non-empty collections.");
            }

            if (keySelector == null)
            {
                keySelector = x => x.ToString();
            }

            MenuOption <T> result = null;

            console.CursorVisible = false;

            using (var display = new MenuDisplay <MenuOption <T> >(console))
            {
                display.Cleanup = cleanup == MenuCleanup.None ? InputCleanup.None : InputCleanup.Clean;
                display.PrefixesTop.SetKeys(labeling);

                foreach (var item in collection)
                {
                    display.Options.Add(new MenuOption <T>(keySelector(item), item));
                }

                if (cancelKey != null || (cancelValue != null && !cancelValue.Equals(default(T))))
                {
                    if (labeling != MenuLabeling.None)
                    {
                        display.PrefixesBottom.SetKeys(new char[] { '0' });
                    }
                    if (cancelKey == null)
                    {
                        cancelKey = keySelector(cancelValue);
                    }
                    display.Options.Add(new MenuOption <T>(cancelKey, cancelValue));
                }

                display.SelectedIndex = 0;

                bool           done = false;
                ConsoleKeyInfo info;
                do
                {
                    info = console.ReadKey(true);
                    switch (info.Key)
                    {
                    case ConsoleKey.DownArrow:
                    case ConsoleKey.UpArrow:
                        display.HandleKey(info);
                        break;

                    case ConsoleKey.Enter:
                        result = display.Options[display.SelectedIndex];
                        done   = true;
                        break;

                    default:
                        var index = display.IndexFromPrefix(info.KeyChar);
                        if (index >= 0)
                        {
                            display.HandleKey(info);
                            result = display.Options[index];
                            done   = true;
                        }
                        break;
                    }
                } while (!done);

                if (cleanup == MenuCleanup.None)
                {
                    console.SetCursorPosition(display.Origin + new ConsoleSize(0, display.Options.Count));
                }
            }

            if (cleanup == MenuCleanup.RemoveMenuShowChoice)
            {
                console.WriteLine(result.Text);
            }

            console.CursorVisible = true;

            return(result.Value);
        }
Пример #5
0
        /// <summary>
        /// Displays a menu where a set of elements can be selected from the collection.
        /// </summary>
        /// <typeparam name="T">The type of the elements in <paramref name="collection"/>.</typeparam>
        /// <param name="isSelectionValid">A function that determines if the current selected collection is a valid selection. If the function returns <c>true</c> the done option is enabled.</param>
        /// <param name="collection">The collection of element from which the menu should be created.</param>
        /// <param name="onKeySelector">A function that gets the <see cref="ConsoleString"/> that should be displayed for an item in the collection, when the option is selected.</param>
        /// <param name="offKeySelector">A function that gets the <see cref="ConsoleString"/> that should be displayed for an item in the collection, when the option is not selected.</param>
        /// <param name="selected">A function that returns a boolean value indicating if an element should be pre-selected when the menu is displayed.</param>
        /// <param name="labeling">The type of labeling (option prefix) that should be applied when displaying the menu.</param>
        /// <param name="cleanup">The cleanup applied after displaying the menu.</param>
        /// <param name="doneText">The <see cref="ConsoleString"/> that is displayed as the bottommost option in the menu. Selecting this option will cause the function to return.</param>
        /// <returns>The elements that were selected using the displayed menu.</returns>
        public static T[] MenuSelectMultiple <T>(this IConsole console, IEnumerable <T> collection, Func <IEnumerable <T>, bool> isSelectionValid = null, Func <T, ConsoleString> onKeySelector = null, Func <T, ConsoleString> offKeySelector = null, Func <T, bool> selected = null, MenuLabeling labeling = MenuLabeling.NumbersAndLetters, MenuCleanup cleanup = MenuCleanup.None, ConsoleString doneText = null)
        {
            if (collection == null)
            {
                throw new ArgumentNullException(nameof(collection));
            }
            var items = collection.ToArray();

            if (!items.Any())
            {
                throw new ArgumentOutOfRangeException(nameof(collection), $"{nameof(MenuSelect)} can not on be executed on non-empty collections.");
            }

            if (isSelectionValid == null)
            {
                isSelectionValid = x => true;
            }

            if (onKeySelector == null)
            {
                onKeySelector = x => x.ToString();
            }
            if (offKeySelector == null)
            {
                offKeySelector = x =>
                {
                    var text = onKeySelector(x);
                    if (text.HasColors)
                    {
                        return(text.ClearColors());
                    }
                    else
                    {
                        return($"[DarkGray:{text.Content}]");
                    }
                }
            }
            ;
            if (selected == null)
            {
                selected = x => false;
            }

            List <MenuOnOffOption <T> > result = null;

            console.CursorVisible = false;

            using (var display = new MenuDisplay <MenuOnOffOption <T> >(console))
            {
                display.Cleanup = cleanup == MenuCleanup.None ? InputCleanup.None : InputCleanup.Clean;
                display.PrefixesTop.SetKeys(labeling);
                display.PrefixesBottom.SetKeys(new char[] { '0' });

                foreach (var item in items)
                {
                    display.Options.Add(new MenuOnOffOption <T>(onKeySelector(item), offKeySelector(item), selected(item), item));
                }

                if (doneText == null)
                {
                    doneText = "Done";
                }
                var doneOption = new MenuOnOffOption <T>(doneText, $"[DarkGray:{doneText.Content}]", true, default(T));
                display.Options.Add(doneOption);

                doneOption.On = isSelectionValid(display.Options.Where(x => x != doneOption && x.On).Select(x => x.Value));

                display.SelectedIndex = 0;

                bool           done = false;
                ConsoleKeyInfo info;
                do
                {
                    info = console.ReadKey(true);
                    switch (info.Key)
                    {
                    case ConsoleKey.DownArrow:
                    case ConsoleKey.UpArrow:
                        display.HandleKey(info);
                        break;

                    case ConsoleKey.Enter:
                    default:
                        var index = info.Key == ConsoleKey.Enter ? display.SelectedIndex : display.IndexFromPrefix(info.KeyChar);

                        if (index >= 0)
                        {
                            var option = display.Options[index];
                            if (option == doneOption && doneOption.On)
                            {
                                done = true;
                            }
                            else if (option != doneOption)
                            {
                                option.On     = !option.On;
                                doneOption.On = isSelectionValid(display.Options.Where(x => x != doneOption && x.On).Select(x => x.Value));
                            }
                        }
                        break;
                    }
                } while (!done);

                result = new List <MenuOnOffOption <T> >(display.Options.Where(x => x != doneOption && x.On));

                if (cleanup == MenuCleanup.None)
                {
                    console.SetCursorPosition(display.Origin + new ConsoleSize(0, display.Options.Count));
                }
            }

            if (cleanup == MenuCleanup.RemoveMenuShowChoice)
            {
                foreach (var r in result)
                {
                    console.WriteLine(r.Text);
                }
            }

            console.CursorVisible = true;

            return(result.Select(x => x.Value).ToArray());
        }
Пример #6
0
 /// <summary>
 /// Displays a menu where a single element can be selected from the collection.
 /// Displays the key part of each element in the menu and returns the selected value part.
 /// </summary>
 /// <typeparam name="TKey">The type of the Key part of elements in <paramref name="collection"/>.</typeparam>
 /// <typeparam name="TValue">The type of the Value part of elements in <paramref name="collection"/>.</typeparam>
 /// <param name="collection">The collection of elements from which the menu should be created.</param>
 /// <param name="labeling">The type of labeling (option prefix) that should be applied when displaying the menu.</param>
 /// <param name="cleanup">The cleanup applied after displaying the menu.</param>
 /// <param name="cancelKey">If not <c>null</c>, this string is displayed as a "cancel option" in the bottom of the menu.
 /// <paramref name="cancelValue"/> will be returned if this option is selected.</param>
 /// <param name="cancelValue">The value returned if <paramref name="cancelKey"/> is not <c>null</c>.</param>
 /// <returns>The element that was selected using the displayed menu.</returns>
 public static TValue MenuSelect <TKey, TValue>(IConsole console, IEnumerable <KeyValuePair <TKey, TValue> > collection, MenuLabeling labeling = MenuLabeling.NumbersAndLetters, MenuCleanup cleanup = MenuCleanup.None, ConsoleString cancelKey = null, TValue cancelValue = default(TValue))
 {
     return(MenuSelect(console, collection, x => x.Key.ToString(), labeling, cleanup, cancelKey, new KeyValuePair <TKey, TValue>(default(TKey), cancelValue)).Value);
 }