mirror of
https://github.com/inthehand/32feet.git
synced 2026-10-20 15:42:43 +08:00
528 lines
16 KiB
C#
528 lines
16 KiB
C#
#define REMOTE_CONSOLE
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.Windows.Forms;
|
|
using Microsoft.VisualBasic; // e.g. Interaction.InputBox, MsgBox, MsgBoxResult etc.
|
|
using System.Diagnostics;
|
|
#if NETCF
|
|
using Microsoft.WindowsCE.Forms;
|
|
#endif
|
|
using System.IO;
|
|
|
|
namespace DeviceMenuTesting
|
|
{
|
|
class FormMenu : ConsoleMenuTesting.MenuSystem
|
|
{
|
|
volatile bool _disposed;
|
|
TextBox tb;
|
|
Label labelPause;
|
|
Menu parentMenu;
|
|
MenuItem itemUnpause, itemClearConsole, itemDoException;
|
|
#if !NETCF
|
|
FormsMenuTesting.FormReadAddr _formReadAddress = new FormsMenuTesting.FormReadAddr();
|
|
#endif
|
|
|
|
public FormMenu(TextBox tb, Menu parentMenu, Label labelPause)
|
|
{
|
|
this.tb = tb;
|
|
this.tb.Disposed += new EventHandler(tb_Disposed);
|
|
this.labelPause = labelPause;
|
|
this.parentMenu = parentMenu;
|
|
SetupPauseControls();
|
|
LoadKnownAddresses();
|
|
}
|
|
|
|
void tb_Disposed(object sender, EventArgs e)
|
|
{
|
|
_disposed = true;
|
|
SaveKnownAddresses();
|
|
}
|
|
|
|
Dictionary<string, MenuItem> m_subMenus = new Dictionary<string, MenuItem>();
|
|
|
|
public override void RunMenu()
|
|
{
|
|
if (this.tb.InvokeRequired)
|
|
throw new InvalidOperationException("Must be called from the main thread.");
|
|
itemUnpause = new MenuItem();
|
|
itemUnpause.Enabled = false;
|
|
itemUnpause.Text = "Un-pause";
|
|
itemUnpause.Click += Unpause_Click;
|
|
this.parentMenu.MenuItems.Add(itemUnpause);
|
|
//
|
|
itemClearConsole = new MenuItem();
|
|
itemClearConsole.Text = "Clear console";
|
|
itemClearConsole.Click += ClearConsole_Click;
|
|
this.parentMenu.MenuItems.Add(itemClearConsole);
|
|
//
|
|
#if NETCF && REMOTE_CONSOLE
|
|
MenuItem itemX = new MenuItem();
|
|
itemX.Text = "Remote console";
|
|
itemX.Click += RemoteConsole_Click;
|
|
this.parentMenu.MenuItems.Add(itemX);
|
|
#else
|
|
// Keep the compiler happy.
|
|
_secondConsole = null;
|
|
#endif
|
|
//
|
|
MenuItem itemY = new MenuItem();
|
|
itemY.Text = "Save text";
|
|
itemY.Click += SaveText_Click;
|
|
this.parentMenu.MenuItems.Add(itemY);
|
|
//
|
|
itemDoException = new MenuItem();
|
|
itemDoException.Text = "Unhandled Exception";
|
|
itemDoException.Click += delegate
|
|
{
|
|
if (!this.ReadYesNo("Throw exception", false)) return;
|
|
throw new RankException("DeviceMenuTesting manual exception.");
|
|
};
|
|
this.parentMenu.MenuItems.Add(itemDoException);
|
|
//
|
|
foreach (ConsoleMenuTesting.Option cur in Options) {
|
|
MenuItem item = new MenuItem();
|
|
var label = cur.name;
|
|
label = label.Replace('_', '&');
|
|
item.Text = label;
|
|
item.Click += cur.EventHandlerInvokeOnBackground;
|
|
if (cur.SubMenu == null || cur.SubMenu == RootName) {
|
|
this.parentMenu.MenuItems.Add(item);
|
|
} else {
|
|
if (!m_subMenus.ContainsKey(cur.SubMenu)) {
|
|
MenuItem newSubMenu = new MenuItem();
|
|
newSubMenu.Text = cur.SubMenu;
|
|
m_subMenus.Add(cur.SubMenu, newSubMenu);
|
|
this.parentMenu.MenuItems.Add(newSubMenu);
|
|
}
|
|
MenuItem subMenu = m_subMenus[cur.SubMenu];
|
|
subMenu.MenuItems.Add(item);
|
|
}
|
|
}//for
|
|
}
|
|
|
|
//----
|
|
#if NETCF && REMOTE_CONSOLE
|
|
void RemoteConsole_Click(object sender, EventArgs e)
|
|
{
|
|
if (!ReadYesNo("Connect to Remote console (port " + RemoteConsole.Port + ")", false))
|
|
return;
|
|
if (_secondConsole != null) {
|
|
var msg = "Remote Console already active!";
|
|
SafeMsgBox(msg, "Warning", MsgBoxStyle.Information);
|
|
return;
|
|
}
|
|
_secondConsole = new RemoteConsole(this);
|
|
}
|
|
#endif
|
|
|
|
void SaveText_Click(object sender, EventArgs e)
|
|
{
|
|
using (var f = System.IO.File.CreateText("output.txt")) {
|
|
f.WriteLine(this.tb.Text);
|
|
}
|
|
}
|
|
|
|
//--------
|
|
const string NewLine = "\r\n";
|
|
|
|
IAuxConsole _secondConsole;
|
|
|
|
void SafeAppendText(string txt)
|
|
{
|
|
if (_secondConsole != null) {
|
|
_secondConsole.AppendText(txt);
|
|
}
|
|
//
|
|
EventHandler dlgt = delegate
|
|
{
|
|
tb.Text += txt;
|
|
};
|
|
SafeInvoke(tb, dlgt);
|
|
}
|
|
|
|
void SafeSetText(string txt)
|
|
{
|
|
EventHandler dlgt = delegate
|
|
{
|
|
tb.Text = txt;
|
|
};
|
|
SafeInvoke(tb, dlgt);
|
|
}
|
|
|
|
private void SafeInvoke(Control c, EventHandler dlgt)
|
|
{
|
|
if (_disposed) {
|
|
return;
|
|
}
|
|
if (c.InvokeRequired) {
|
|
c.Invoke(dlgt);
|
|
} else {
|
|
dlgt.Invoke(c, EventArgs.Empty);
|
|
}
|
|
}
|
|
|
|
public /*override*/ void Clear()
|
|
{
|
|
SafeSetText(string.Empty);
|
|
}
|
|
|
|
|
|
public override void WriteLine(string msg)
|
|
{
|
|
SafeAppendText(msg + NewLine);
|
|
}
|
|
public override void Write(string msg)
|
|
{
|
|
SafeAppendText(msg);
|
|
}
|
|
|
|
public override void WriteLine(object arg0)
|
|
{
|
|
WriteLine(arg0.ToString());
|
|
}
|
|
|
|
public override void WriteLine(string fmt, params object[] args)
|
|
{
|
|
WriteLine(string.Format(fmt, args));
|
|
}
|
|
public override void Write(string fmt, params object[] args)
|
|
{
|
|
Write(string.Format(fmt, args));
|
|
}
|
|
|
|
string SafeReadLine(string prompt, string title)
|
|
{
|
|
string txt = "eeeeeeh";
|
|
EventHandler dlgt = delegate
|
|
{
|
|
txt = Interaction.InputBox(prompt, title,
|
|
null, -1, -1);
|
|
};
|
|
SafeInvoke(this.tb, dlgt);
|
|
return txt;
|
|
}
|
|
|
|
string SafeReadBluetoothAddress(string prompt, string title)
|
|
{
|
|
#if NETCF
|
|
return SafeReadLine(prompt, title);
|
|
#else
|
|
string txt = "eeeeeeh";
|
|
EventHandler dlgt = delegate {
|
|
_formReadAddress.SetPrompt(prompt, title);
|
|
var rslt = _formReadAddress.ShowDialog();
|
|
if (rslt == DialogResult.OK) {
|
|
txt = _formReadAddress.Line;
|
|
} else {
|
|
txt = null;
|
|
}
|
|
};
|
|
SafeInvoke(this.tb, dlgt);
|
|
return txt;
|
|
#endif
|
|
}
|
|
|
|
MsgBoxResult SafeMsgBox(string prompt, string title,
|
|
MsgBoxStyle buttons)
|
|
{
|
|
MsgBoxResult result = MsgBoxResult.Cancel;
|
|
EventHandler dlgt = delegate
|
|
{
|
|
result = Interaction.MsgBox(prompt, buttons,
|
|
title);
|
|
};
|
|
SafeInvoke(this.tb, dlgt);
|
|
return result;
|
|
}
|
|
|
|
//--------
|
|
public override string ReadLine(string prompt)
|
|
{
|
|
return SafeReadLine(prompt, "ReadLine");
|
|
}
|
|
|
|
public override int ReadInteger(string prompt)
|
|
{
|
|
while (true) {
|
|
int value;
|
|
string txt = SafeReadLine(prompt, "ReadInteger");
|
|
try {
|
|
value = int.Parse(txt);
|
|
} catch (FormatException) {
|
|
continue;
|
|
}
|
|
return value;
|
|
}
|
|
}
|
|
|
|
public override int? ReadOptionalInteger(string prompt)
|
|
{
|
|
while (true) {
|
|
int value;
|
|
string txt = SafeReadLine(prompt, "ReadOptionalInteger");
|
|
if (string.IsNullOrEmpty(txt)) {
|
|
return null;
|
|
} else {
|
|
try {
|
|
value = int.Parse(txt);
|
|
} catch (FormatException) {
|
|
continue;
|
|
}
|
|
return value;
|
|
}
|
|
}
|
|
}
|
|
|
|
public override int? ReadOptionalIntegerHexadecimal(string prompt)
|
|
{
|
|
while (true) {
|
|
int value;
|
|
string txt = SafeReadLine(prompt, "ReadOptionalIntegerHexadecimal");
|
|
if (string.IsNullOrEmpty(txt)) {
|
|
return null;
|
|
} else {
|
|
try {
|
|
value = int.Parse(txt, System.Globalization.NumberStyles.HexNumber);
|
|
} catch (FormatException) {
|
|
continue;
|
|
}
|
|
return value;
|
|
}
|
|
}
|
|
}
|
|
|
|
public override InTheHand.Net.BluetoothAddress ReadBluetoothAddress(string prompt)
|
|
{
|
|
return ReadBluetoothAddress(prompt, false);
|
|
}
|
|
|
|
public override InTheHand.Net.BluetoothAddress ReadOptionalBluetoothAddress(string prompt)
|
|
{
|
|
return ReadBluetoothAddress(prompt, true);
|
|
}
|
|
|
|
InTheHand.Net.BluetoothAddress ReadBluetoothAddress(string prompt, bool optional)
|
|
{
|
|
while (true) {
|
|
InTheHand.Net.BluetoothAddress value;
|
|
string txt = SafeReadBluetoothAddress(prompt, "ReadBluetoothAddress");
|
|
if (string.IsNullOrEmpty(txt) && optional) {
|
|
return null;
|
|
}
|
|
if (InTheHand.Net.BluetoothAddress.TryParse(txt, out value)) {
|
|
AddKnownAddress(value);
|
|
return value;
|
|
}
|
|
}//while
|
|
}
|
|
|
|
public override string GetFilename()
|
|
{
|
|
return GetFilenameWinForms(this);
|
|
}
|
|
|
|
void ClearConsole_Click(object sender, EventArgs e)
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
System.Threading.ManualResetEvent m_pause = new System.Threading.ManualResetEvent(false);
|
|
|
|
public override void Pause(string prompt)
|
|
{
|
|
m_pause.Reset();
|
|
ShowPause(true, prompt);
|
|
bool x = m_pause.WaitOne();
|
|
}
|
|
|
|
private void Unpause_Click(object sender, EventArgs e)
|
|
{
|
|
ShowPause(false, null);
|
|
m_pause.Set();
|
|
}
|
|
|
|
private void SetupPauseControls()
|
|
{
|
|
this.labelPause.SendToBack();
|
|
ShowPause(false, null);
|
|
}
|
|
|
|
private void ShowPause(bool pausing, string prompt)
|
|
{
|
|
System.Threading.ThreadStart dlgt = delegate
|
|
{
|
|
if (pausing) {
|
|
WriteLine(prompt);
|
|
this.labelPause.Text = "Menu->Un-pause: " + prompt;
|
|
this.labelPause.Visible = true;
|
|
Debug.Assert(itemUnpause != null, "init'd in RunMenu so should be valid!");
|
|
} else {
|
|
this.labelPause.Visible = false;
|
|
}
|
|
if (itemUnpause != null) {
|
|
itemUnpause.Enabled = pausing;
|
|
}
|
|
};
|
|
if (this.tb.InvokeRequired) {
|
|
this.tb.BeginInvoke(dlgt);
|
|
} else {
|
|
dlgt();
|
|
}
|
|
}
|
|
|
|
void Pause__old()
|
|
{
|
|
//bool hc = this.tb.IsHandleCreated;
|
|
bool ir = this.tb.InvokeRequired;
|
|
if (ir) { //DEBUG
|
|
}
|
|
MessageBox.Show("Pause" + (ir ? " InvokeRequired!!" : " (is on UI thread)"), "Pause",
|
|
MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);
|
|
}
|
|
|
|
public override bool ReadYesNo(string prompt, bool defaultYes)
|
|
{
|
|
MsgBoxStyle style = MsgBoxStyle.YesNo;
|
|
style |= (defaultYes ? MsgBoxStyle.DefaultButton1 : MsgBoxStyle.DefaultButton2);
|
|
while (true) {
|
|
MsgBoxResult val = SafeMsgBox(prompt, "ReadYesNo", style);
|
|
Debug.Assert(val == MsgBoxResult.Yes || val == MsgBoxResult.No);
|
|
return (val == MsgBoxResult.Yes); // true==Yes, false==No
|
|
}
|
|
}
|
|
|
|
public override bool? ReadYesNoCancel(string prompt, bool? defaultYes)
|
|
{
|
|
MsgBoxStyle style = MsgBoxStyle.YesNoCancel;
|
|
style |= (defaultYes == true ? MsgBoxStyle.DefaultButton1
|
|
: defaultYes == false ? MsgBoxStyle.DefaultButton2
|
|
: MsgBoxStyle.DefaultButton3);
|
|
var twoChoicesSupportedOnly = false;
|
|
#if NETCF
|
|
twoChoicesSupportedOnly = SystemSettings.Platform == WinCEPlatform.Smartphone;
|
|
|
|
#endif
|
|
if (twoChoicesSupportedOnly) {
|
|
bool result;
|
|
result = ReadYesNo("Choose Yes or No/Cancel -- " + prompt, defaultYes == null);
|
|
if (result)
|
|
return true;
|
|
result = ReadYesNo("Choose No or Cancel -- " + prompt, defaultYes == null);
|
|
if (result)
|
|
return false;
|
|
else
|
|
return null;
|
|
}
|
|
while (true) {
|
|
MsgBoxResult val = SafeMsgBox(prompt, "ReadYesNoCancel", style);
|
|
Debug.Assert(val == MsgBoxResult.Yes || val == MsgBoxResult.No
|
|
|| val == MsgBoxResult.Cancel);
|
|
// true==Yes, false==No
|
|
if (val == MsgBoxResult.Yes)
|
|
return true;
|
|
else if (val == MsgBoxResult.No)
|
|
return false;
|
|
else return null;
|
|
}
|
|
}
|
|
|
|
public override Guid? ReadOptionalBluetoothUuid(string prompt, Guid? promptDefault)
|
|
{
|
|
while (true) {
|
|
Guid value;
|
|
if (promptDefault != null) {
|
|
prompt += " (default: " + promptDefault.ToString() + ")";
|
|
}
|
|
string txt = SafeReadLine(prompt, "ReadOptionalIntegerHexadecimal");
|
|
if (string.IsNullOrEmpty(txt)) {
|
|
return null;
|
|
} else {
|
|
if (base.BluetoothService_TryParseIncludingShortForm(txt, out value))
|
|
return value;
|
|
// Continue to give user another chance to input a good value.
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
private void Log(string msg)
|
|
{
|
|
SafeAppendText(msg + "\r\n");
|
|
}
|
|
|
|
//--
|
|
public override void UiInvoke(EventHandler dlgt)
|
|
{
|
|
SafeInvoke(tb, dlgt);
|
|
}
|
|
|
|
public override bool? InvokeRequired
|
|
{
|
|
get { return tb.InvokeRequired; }
|
|
}
|
|
|
|
public override object InvokeeControl
|
|
{
|
|
get { return tb; }
|
|
}
|
|
|
|
//----
|
|
#if !NETCF
|
|
AutoCompleteStringCollection _knownAddresses;
|
|
|
|
private string _knownAddressesPath
|
|
{
|
|
get
|
|
{
|
|
var dir = Path.GetDirectoryName(EntryAssemblyPath);
|
|
return Path.Combine(dir, "knownAddresses.txt");
|
|
}
|
|
}
|
|
|
|
private string EntryAssemblyPath
|
|
{
|
|
get
|
|
{
|
|
var cb = System.Reflection.Assembly.GetEntryAssembly().CodeBase;
|
|
var u = new Uri(cb);
|
|
var dir = u.LocalPath;
|
|
return dir;
|
|
}
|
|
}
|
|
|
|
void LoadKnownAddresses()
|
|
{
|
|
_knownAddresses = new AutoCompleteStringCollection();
|
|
_formReadAddress.SetKnownAddressList(_knownAddresses);
|
|
string[] lines;
|
|
try {
|
|
lines = File.ReadAllLines(_knownAddressesPath);
|
|
} catch (FileNotFoundException) {
|
|
return;
|
|
}
|
|
_knownAddresses.AddRange(lines);
|
|
}
|
|
|
|
void SaveKnownAddresses()
|
|
{
|
|
string[] arr = new string[_knownAddresses.Count];
|
|
_knownAddresses.CopyTo(arr, 0);
|
|
System.IO.File.WriteAllLines(_knownAddressesPath, arr);
|
|
}
|
|
|
|
void AddKnownAddress(InTheHand.Net.BluetoothAddress value)
|
|
{
|
|
var text = value.ToString("C");
|
|
if (!_knownAddresses.Contains(text)) {
|
|
_knownAddresses.Add(text);
|
|
}
|
|
}
|
|
#else
|
|
void LoadKnownAddresses() { }
|
|
void SaveKnownAddresses() { }
|
|
void AddKnownAddress(InTheHand.Net.BluetoothAddress value) { }
|
|
#endif
|
|
}
|
|
}
|