using System.Data; using Model; using System; using System.Collections.Generic; using System.ComponentModel.Design; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp.Menu { /// /// Define a selection menu. ///
It allows you to navigate through the selections and search with a console input. ///
/// The type (or the implementation) of the selection. internal abstract class Menu : IMenu where T : notnull { #region Attributes & Properties protected StringBuilder _screenDisplay; protected List> _allSelectors = new List>(); protected List> _selectList = new List>(); private int _currentLine; /// /// Title of the menu. /// public string Title { get; private set; } /// /// The current line of the selection list. /// public int CurrentLine { get { if (_currentLine >= _selectList.Count) _currentLine = _selectList.Count - 1; return _currentLine; } protected set { _currentLine = value; if (_currentLine <= 0) _currentLine = 0; else if (_currentLine >= _selectList.Count) _currentLine = _selectList.Count-1; } } /// /// The currently selected object. /// public T? CurrentSelected { get; protected set; } #endregion #region Constructors /// /// Base constructor of the Menu class. ///
This one is incomplete and need to be completed in the inherited class constructors. ///
Basically, the '_allSelection' and '_selectList' attribute initialization are missing. ///
/// The title of the Menu. protected Menu(string title) { Title = title; CurrentLine = 0; WriteMode = false; _screenDisplay = new StringBuilder(); InputStr = new StringBuilder(); } /// /// Constructor of the Menu class. This constructor allows you to directly pass the selections. /// /// The title of the menu. /// The selections of the menu. protected Menu(string title, params Selector[] selections ) : this(title) { if (selections == null || selections.Length == 0) { Console.WriteLine("Empty menu..."); return; } _allSelectors = selections.ToList(); _selectList = _allSelectors; CurrentSelected = _allSelectors[0].Item; } #endregion #region IMenu implementation public StringBuilder InputStr { get; set; } public bool WriteMode { get; set; } public virtual IMenu? Return() { if (CurrentSelected is null) throw new ArgumentNullException("CurrentSelected"); return (IMenu)CurrentSelected; } protected virtual List> SearchInSelection() { if (_allSelectors is null) throw new ArgumentNullException("_allSelectors"); return _allSelectors.FindAll(x => x.Line.ToLower().Contains(InputStr.ToString().ToLower())); } public virtual void WriteMenuMode(ConsoleKeyInfo cki) { if (!WriteMode && cki.Key == ConsoleKey.R) { EnableWriteMode(); return; } if (WriteMode) { if (cki.Key == ConsoleKey.Escape) { DisableWriteMode(); InputStr.Clear(); return; } if (cki.Key == ConsoleKey.Backspace && InputStr.Length > 0) { InputStr.Remove(InputStr.Length - 1, 1); return; } InputStr.Append(cki.KeyChar); } } public virtual void Update() { _selectList = SearchInSelection(); if (_selectList.Count == 0) { CurrentSelected = default; return; } CurrentSelected = _selectList[CurrentLine].Item; } public virtual void Display() { _screenDisplay.Clear(); Console.Clear(); _screenDisplay.AppendLine($"[ {Title} ]"); _screenDisplay.AppendLine("-------------------------------------------"); if (WriteMode) { _screenDisplay.Append("Search: "); _screenDisplay.AppendLine(InputStr.ToString()); } for (int i = 0; i < _selectList.Count; i++) { if (CurrentLine == i) _screenDisplay.Append($"> "); else _screenDisplay.Append($" "); _screenDisplay.AppendLine($"{_selectList[i].Line}"); } if (_selectList.Count == 0) _screenDisplay.AppendLine("Empty..."); _screenDisplay.AppendLine( "\n\nHint:\n^:previous, v:next, <:ret, -enter-:select, r:search, -escape-:exit search mode"); Console.WriteLine(_screenDisplay); } public void SelectNext() => ++CurrentLine; public void SelectPrevious() => --CurrentLine; public void EnableWriteMode() => WriteMode = true; public void DisableWriteMode() => WriteMode = false; public void ToggleWriteMode() { if (WriteMode) DisableWriteMode(); else EnableWriteMode(); } #endregion } }