using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using InTheHand.Net;
using System.Globalization;
using System.Reflection;
using System.Threading;
namespace ConsoleMenuTesting{
class ConsoleMenu : MenuSystem
{
protected volatile bool quitMenu;
TextReader m_rdr;
TextWriter m_wtr;
string m_subMenu;
bool m_backChosen;
//
const string promptArrow = ">";
public ConsoleMenu()
: this(Console.In, Console.Out)
{
}
public ConsoleMenu(TextReader rdr, TextWriter wtr)
{
Console.CancelKeyPress += new ConsoleCancelEventHandler(Console_CancelKeyPress);
Options.Add(new Option("Quit", null, new ThreadStart(Quit).Method, this));
Options.Add(new Option("<-Back", null, new ThreadStart(Back).Method, this));
//
m_rdr = rdr;
m_wtr = wtr;
}
private void AddSubMenuMenus()
{
foreach (string curSubMenu in SubMenus) {
Options.Add(new OptionSubMenu(curSubMenu, MenuSubMenu, this));
}
}
//--------
public override void RunMenu()
{
AddSubMenuMenus();
Option.console = this;
try {
m_backChosen = true; //reset for init
while (!quitMenu) {
if (m_backChosen) {
m_subMenu = "root";
}
m_backChosen = false;
//
IList<Option> shownOptions = DisplayMenu(Options);
int item = ReadInteger("option");
if (item < 1 || item > shownOptions.Count) {
WriteLine("Not a menu item number");
continue;
}
Option selected = shownOptions[item - 1];
try {
try {
selected.EventHandlerInvoke(null, null);
} catch (TargetInvocationException tiex) {
Console.WriteLine("Original exception :"
+ Environment.NewLine + tiex.InnerException);
throw tiex.InnerException;
}
} catch (EndOfStreamException) {
throw;
} catch (Exception ex) {
WriteLine("Exception: {0}", ex);
bool cont = ReadYesNo("Continue after that exception", true);
if (!cont) {
throw;
}
}
}//while
} catch (EndOfStreamException eosex) {
Thread.Sleep(2000);
if (quitMenu) {
Console.WriteLine("[suppressed: " + FirstLine(eosex) + "]");
} else {
throw;
}
}
}
private string FirstLine(Exception eosex)
{
string t = eosex.ToString();
using (TextReader rdr = new StringReader(t)) {
return rdr.ReadLine();
}
}
private IList<Option> DisplayMenu(IList<Option> options)
{
int menuNum = 0;
IList<Option> shown = new List<Option>();
for (int i = 0; i < options.Count; ++i) {
Option cur = options[i];
if (cur.SubMenu == null
|| cur.SubMenu == m_subMenu) {
WriteLine("{0,2} -- {1}", menuNum + 1, cur.name);
shown.Add(cur);
++menuNum;
} else {
//DEBUG
}
}//for
return shown;
}
void Quit()
{
bool yes = this.ReadYesNo("Quit", false);
if (!yes) return;
quitMenu = true;
}
void Back()
{
m_backChosen = true;
}
void MenuSubMenu(string curSubMenu)
{
m_subMenu = curSubMenu;
}
void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
{
// Does this allow finalizers to run?
quitMenu = true;
if (quit != null)
quit.Set();
MemoryBarrier();
Console.WriteLine("Letting Finalizers run...");
BluetoothTesting.RunFinalizersAfterGc_();
//
//// TODO Console.WriteLine("Nulling peer stream.");
//peer = null;
//Console.WriteLine("Letting Finalizers run...");
//BluetoothTesting.RunFinalizersAfterGc_();
if (e.SpecialKey != ConsoleSpecialKey.ControlBreak) // May not cancel it!
e.Cancel = true;
}
private static void MemoryBarrier()
{
Thread.MemoryBarrier();
}
//--------
public override void WriteLine(string msg)
{
Console.WriteLine(msg);
}
public override void Write(string msg)
{
Console.Write(msg);
}
public override void WriteLine(object arg0)
{
Console.WriteLine(arg0);
}
public override void WriteLine(string fmt, params object[] args)
{
Console.WriteLine(fmt, args);
}
public override void Write(string fmt, params object[] args)
{
Console.Write(fmt, args);
}
//--------
public override string ReadLine(string prompt)
{
Write(prompt + promptArrow);
string line = m_rdr.ReadLine();
if (line == null)
throw new EndOfStreamException();
return line;
}
public override int ReadInteger(string prompt)
{
m_wtr.Write(prompt);
while (true) {
m_wtr.Write(promptArrow);
string line = m_rdr.ReadLine();
if (line == null)
throw new EndOfStreamException();
int result;
if (int.TryParse(line, out result))
return result;
m_wtr.Write("Invalid number");
}
}
public override int? ReadOptionalInteger(string prompt)
{
m_wtr.Write(prompt);
m_wtr.Write(" (optional)");
while (true) {
m_wtr.Write(promptArrow);
string line = m_rdr.ReadLine();
if (line == null)
throw new EndOfStreamException();
int result;
if (int.TryParse(line, out result))
return result;
else
return null;
}
}
public override int? ReadOptionalIntegerHexadecimal(string prompt)
{
m_wtr.Write(prompt);
m_wtr.Write(" (optional)");
while (true) {
m_wtr.Write(promptArrow);
string line = m_rdr.ReadLine();
if (line == null)
throw new EndOfStreamException();
int result;
if (int.TryParse(line, NumberStyles.HexNumber, null, out result))
return result;
else
return null;
}
}
public override BluetoothAddress ReadBluetoothAddress(string prompt)
{
m_wtr.Write(prompt);
while (true) {
m_wtr.Write(promptArrow);
string line = m_rdr.ReadLine();
if (line == null)
throw new EndOfStreamException();
BluetoothAddress result;
if (BluetoothAddress.TryParse(line, out result))
return result;
m_wtr.Write("Invalid address");
}
}
public override void Pause(string prompt)
{
m_wtr.Write(prompt);
m_wtr.Write(promptArrow);
string line = m_rdr.ReadLine();
if (line == null)
throw new EndOfStreamException();
}
public override bool ReadYesNo(string prompt, bool defaultYes)
{
m_wtr.Write(prompt);
if (defaultYes)
m_wtr.Write(" [Y/n]");
else
m_wtr.Write(" [y/N]");
while (true) {
m_wtr.Write(promptArrow);
string line = m_rdr.ReadLine();
if (line == null)
throw new EndOfStreamException();
if (line.Length == 0)
return defaultYes;
char val = line.Trim().ToUpper()[0];
if (val == 'Y')
return true;
else if (val == 'N')
return false;
m_wtr.Write("Need Y or N");
}
}
public override Guid? ReadOptionalBluetoothUuid(string prompt)
{
m_wtr.Write(prompt + " Int32 or GUID");
m_wtr.Write(" (optional)");
while (true) {
m_wtr.Write(promptArrow);
string line = m_rdr.ReadLine();
if (line == null)
throw new EndOfStreamException();
if (line.Length == 0)
return null;
Guid result;
if (BluetoothService_TryParseIncludingShortForm(line, out result))
return result;
m_wtr.Write("Invalid UUID, re-enter");
}
}
public override void UiInvoke(EventHandler dlgt)
{
throw new NotSupportedException("UiInvoke");
}
}
}
|