From 373eb7051410d0d7a1bcdbc93e9cc34f2951333d Mon Sep 17 00:00:00 2001 From: Scott Gasch Date: Wed, 1 Jun 2016 19:42:52 -0700 Subject: [PATCH 1/1] Initial checkin of typhoon UI project. --- App.ico | Bin 0 -> 1078 bytes AssemblyInfo.cs | 58 +++++ Form1.cs | 542 ++++++++++++++++++++++++++++++++++++++++++ Form1.resx | 108 +++++++++ typhoonUI.csproj | 112 +++++++++ typhoonUI.csproj.user | 48 ++++ typhoonUI.sln | 21 ++ 7 files changed, 889 insertions(+) create mode 100644 App.ico create mode 100644 AssemblyInfo.cs create mode 100644 Form1.cs create mode 100644 Form1.resx create mode 100644 typhoonUI.csproj create mode 100644 typhoonUI.csproj.user create mode 100644 typhoonUI.sln diff --git a/App.ico b/App.ico new file mode 100644 index 0000000000000000000000000000000000000000..3a5525fd794f7a7c5c8e6187f470ea3af38cd2b6 GIT binary patch literal 1078 zcmeHHJr05}7=1t!Hp3A*8IHkVf+j?-!eHY14Gtcw1Eb*_9>Bq^zETJ@GKj{_2j4$w zo9}xCh!8{T3=X##Skq>ikMjsvB|y%crWBM2iW(4pI}c%z6%lW!=~4v77#3{z!dmB1 z__&l)-{KUYR+|8|;wB^R|9ET$J@(@=#rd^=)qs85?vAy(PSF5CyNkus435LVkZ$rj zNw|JG-P7^hF<(;#o*Vk}5R#e|^13tBbQkeF?djULtvqyxd3<{9 literal 0 HcmV?d00001 diff --git a/AssemblyInfo.cs b/AssemblyInfo.cs new file mode 100644 index 0000000..177a4f0 --- /dev/null +++ b/AssemblyInfo.cs @@ -0,0 +1,58 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("1.0.*")] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyFile("")] +[assembly: AssemblyKeyName("")] diff --git a/Form1.cs b/Form1.cs new file mode 100644 index 0000000..766ac22 --- /dev/null +++ b/Form1.cs @@ -0,0 +1,542 @@ +/** + * Copyright (c) Lynn J. Gasch + * 7/17/04 + * Redmond, Washington + * + * typhoonUI displays the contents of an xml file in a tree control. + * It was developed to support chess programming, but can really be + * used for any xml file you wish. + * + * Xml nodes that do not have children should be written within + * a single tag, as < tag anAttrib="value" /> so that they can + * be displayed on a single line (node) of the tree. + * + * Tags starting with "FEN" can be used to lauch chess board + * viewers with the board value (they must use the single-line + * formatting as described above to trigger this functionality). + * + * This app is pretty special purpose and I'm sure there are plenty + * of ways to break it with various inputs. I coded it up in a few + * hours and it meets our needs. + */ + +using System; +using System.Drawing; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; +using System.Data; +using System.Xml; +using System.IO; +using System.Diagnostics; +using System.Text; + +namespace typhoonUI +{ + // TODO: write tag for eval; Write evals dumps to file + // and retrieve the text into a separate text block + // on selection of the node + // TODO: command line file launch + // TODO: speed up loading + + /// + /// Summary description for Form1. + /// + public class Form1 : System.Windows.Forms.Form + { + #region Private Fields + + /// + /// inserted between tag names and their values for display + /// in the tree. For tags that have no children other than their + /// values, list them in the xml as + /// < tag attrib="something to display" /> and they will only + /// take up one tree node and be listed as + /// tag something to display. + /// + private const string VALUE_SEPARATOR = " "; + + /// + /// Use this tag name to identify the board configuration node + /// in your xml. This will provide menu item and double-clicking + /// to launch the position in a viewer that you can specify. + /// + private const string TAG_BOARD = "FEN"; + + /// + /// name of a tag for which the first attrib should be added to its parent + /// node text. If it's the only child, the node itself will be skipped + /// + private const string TAG_SCORE = "score"; + + /// + /// Attributes named tip will be set as tool tip text for the node + /// + private const string ATTRIB_TIP = "tip"; + + /// + /// an attrib name to denote request for boldfacing the text. + /// In order for the text to be displayed, it must be the frst attrib. + /// + private const string ATTRIB_BOLD = "bold"; + + /// + /// Name of a (reusable) file that is written with the board + /// position and used as a command arg to the board viewer app. + /// + private const string POSITION_FILE_NAME = "boardConfigFile.txt"; + + /// + /// Windows designer generated code + /// + private System.Windows.Forms.MainMenu mainMenu1; + private System.Windows.Forms.MenuItem menuItem1; + private System.Windows.Forms.MenuItem menuItem2; + private System.Windows.Forms.TreeView _treeView1; + + /// + /// appears when right-clicking on a "board" node. See + /// BOARD_TAG_NAME + /// + private System.Windows.Forms.ContextMenu _contextMenu; + + /// + /// Path to the viewer app, to be collected from the user. + /// TODO: allow the user to enter it into the Path environment + /// variable and just attempt to run it; only request path + /// if fail to run. + /// + private string _boardViewerAppPath = null; + + /// + /// the view app process, so we can kill it if another board + /// is to be viewed + /// + private Process _process = null; + + /// + /// local dir for writing the board position file for input + /// into the viewer app. + /// + private string _applicationDir; + + /// + /// Required designer variable. + /// + private System.ComponentModel.Container components = null; + + /// + /// for displaying long or multi-line text + /// + private ToolTip _tip; + + private string _tipText; + + #endregion + + #region Construction / Destruction + + /// + /// The main thing + /// + public Form1(string startFile) + { + // + // Required for Windows Form Designer support + // + InitializeComponent(); + + // create the context menu that will be used for board nodes + _contextMenu = new ContextMenu(); + MenuItem item = new MenuItem("View board"); + item.Click += new EventHandler(OnViewBoardMenuClicked); + _contextMenu.MenuItems.Add(item); + + _applicationDir = Path.GetDirectoryName( + Application.ExecutablePath); + + _tip = new ToolTip(); + _tipText = string.Empty; + _tip.SetToolTip(_treeView1, _tipText); + + if ((startFile != null) && (startFile.Length > 0)) + Display(startFile); + } + + /// + /// Clean up any resources being used. + /// + protected override void Dispose( bool disposing ) + { + if( disposing ) + { + KillProcess(); + if (components != null) + { + components.Dispose(); + } + } + base.Dispose( disposing ); + } + + + #endregion + + #region Windows Form Designer generated code + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.mainMenu1 = new System.Windows.Forms.MainMenu(); + this.menuItem1 = new System.Windows.Forms.MenuItem(); + this.menuItem2 = new System.Windows.Forms.MenuItem(); + this._treeView1 = new System.Windows.Forms.TreeView(); + this.SuspendLayout(); + // + // mainMenu1 + // + this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { + this.menuItem1}); + // + // menuItem1 + // + this.menuItem1.Index = 0; + this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { + this.menuItem2}); + this.menuItem1.Text = "File"; + // + // menuItem2 + // + this.menuItem2.Index = 0; + this.menuItem2.Text = "Open"; + this.menuItem2.Click += new System.EventHandler(this.OnOpenMenuClick); + // + // _treeView1 + // + this._treeView1.Anchor = (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right); + this._treeView1.HideSelection = false; + this._treeView1.ImageIndex = -1; + this._treeView1.Name = "_treeView1"; + this._treeView1.SelectedImageIndex = -1; + this._treeView1.Size = new System.Drawing.Size(680, 600); + this._treeView1.TabIndex = 0; + this._treeView1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.OnTreeViewMouseDown); + this._treeView1.DoubleClick += new System.EventHandler(this.OnTreeViewDoubleClick); + this._treeView1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.OnTreeViewMouseMove); + // + // Form1 + // + this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); + this.ClientSize = new System.Drawing.Size(680, 598); + this.Controls.AddRange(new System.Windows.Forms.Control[] { + this._treeView1}); + this.Menu = this.mainMenu1; + this.Name = "Form1"; + this.Text = "Scott\'s Move Tree"; + this.ResumeLayout(false); + + } + #endregion + + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main(string[] args) + { + string filename = string.Empty; + if (args.Length > 0) + filename = args[0]; + + Application.Run(new Form1(filename)); + } + + /// + /// Use Xml support to load and parse the indicated xml doc. + /// Populate tree control with it. + /// + /// path to the xml file to load + private void Display(string filename) + { + _treeView1.BeginUpdate(); + try + { + XmlDocument doc = new XmlDocument(); + doc.Load(filename); + _treeView1.Nodes.Clear(); + TreeNode root = new TreeNode(doc.DocumentElement.Name); + _treeView1.Nodes.Add(root); + // recursively add all + StringBuilder builder = new StringBuilder(); + foreach(XmlNode node in doc.DocumentElement.ChildNodes) + { + AddNode(node, ref root, ref builder); + } + } + catch(Exception e) + { + MessageBox.Show(this, e.Message + "\r\n" + + e.StackTrace, "Error", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + _treeView1.EndUpdate(); + } + + /// + /// Recursively add nodes to the tree. + /// + /// the current info to add; corresponds + /// to the parent node so that we are adding its children. + /// parent node in the tree + /// on;y create one instance of string builder + /// and use it for text manipulation + /// Nodes that don't have any nested nodes (other than their + /// own "value") should be written in the form + /// < tagName attrib="Attrib value" /> + /// In this case, the tag name and the first attrib value are + /// shown in one line (in one node) in the tree. NOTE: any + /// additional tags are ignored. (the attrib value is not required). + /// + private void AddNode(XmlNode element, ref TreeNode parent, + ref StringBuilder builder) + { + builder.Length = 0; + string text = element.Name; + + // special cases: + // - score: append parent text with score instead of adding + // it as a node. + // - any with attribs - append first attrib val to node text + // - bold - (must be first attrib) - boldface the node + // - tip - (any attrib) - set as the tag of the node for tooltip + + if (text.Equals(TAG_SCORE)) + { + builder.Append(parent.Text); + builder.Append(VALUE_SEPARATOR); + builder.Append(TAG_SCORE); + builder.Append(" "); + builder.Append(element.Attributes[0].Value); + parent.Text = builder.ToString(); + // done + } + else + { + builder.Append(text); + XmlAttributeCollection coll = element.Attributes; + int numAttribs = coll.Count; + XmlAttribute attrib = null; + if (numAttribs > 0) + { + attrib = coll[0]; + // append the tag name with the first attrib value + builder.Append(VALUE_SEPARATOR); + builder.Append(attrib.Value); + } + TreeNode node = new TreeNode(builder.ToString()); + + if ((attrib != null) && attrib.Name.Equals(ATTRIB_BOLD)) + node.ForeColor = Color.Red; + if (numAttribs > 1) + { + attrib = coll[1]; + if (attrib.Name.Equals(ATTRIB_TIP)) + { + node.Tag = attrib.Value; + } + } + + parent.Nodes.Add(node); + + foreach (XmlElement child in element.ChildNodes) + { + AddNode(child, ref node, ref builder); + } + } + } + + /// + /// Gets and saves the path to the viewer app from the user. + /// + private DialogResult SetViewerAppPath() + { + DialogResult result = DialogResult.OK; + if (_boardViewerAppPath == null) + { + result = MessageBox.Show(this, + "Please set path to Winboard or XBoard viewer app", + "Input requested", MessageBoxButtons.OKCancel, + MessageBoxIcon.Question); + if ( result == DialogResult.OK) + { + OpenFileDialog browse = new OpenFileDialog(); + browse.Filter = "Executable files (*.exe)|*.exe"; + browse.Multiselect = false; + result = browse.ShowDialog(this); + if (result == DialogResult.OK) + { + _boardViewerAppPath = browse.FileName; + } + } + } + return result; + } + + /// + /// Closes the viewer app + /// + private void KillProcess() + { + if (_process != null) + { + if (!_process.HasExited) + { + if (!_process.CloseMainWindow()) + _process.Kill(); + } + _process = null; + } + } + + /// + /// Writes board position to file and calls the viewer app with it. + /// + /// text of the board node, starting with the + /// "board" tag and separator + private void ViewBoard(string text) + { + string boardCode = text.Substring(TAG_BOARD.Length + + VALUE_SEPARATOR.Length); + StreamWriter f = new StreamWriter(new FileStream( + Path.Combine(_applicationDir, POSITION_FILE_NAME), + FileMode.Create, FileAccess.Write)); + f.WriteLine(boardCode); + f.Close(); + + if (SetViewerAppPath() == DialogResult.OK) + { + + try + { + KillProcess(); + ProcessStartInfo pInfo = + new ProcessStartInfo(_boardViewerAppPath); + pInfo.Arguments = + "/mode editposition /ncp /top /coords /size small /lpf " + + Path.Combine(_applicationDir, POSITION_FILE_NAME); + + _process = new Process(); + _process.StartInfo = pInfo; + _process.Start(); + } + catch(Exception) + { + MessageBox.Show(this, "Unable to run viewer app", "Error", + MessageBoxButtons.OK, MessageBoxIcon.Error); + _boardViewerAppPath = null; + _process = null; + } + } + } + + + #region Event Handlers + + /// + /// Handler for File | Open menu. Get the xml file to load. + /// + /// ignored + /// ignored + private void OnOpenMenuClick(object sender, System.EventArgs e) + { + OpenFileDialog dialog = new OpenFileDialog(); + dialog.Multiselect = false; + dialog.Filter = "XML files (*.xml)|*.xml|All files (*.*)|*.*"; + if (dialog.ShowDialog(this) == DialogResult.OK) + { + Display(dialog.FileName); + } + } + + /// + /// Handles mouse down. if right-click on "board" node, + /// displays board context menu. + /// + /// ignored + /// select the tree node at the click + /// coords + private void OnTreeViewMouseDown(object sender, MouseEventArgs e) + { + // this doesn't automatically happen + _treeView1.SelectedNode = _treeView1.GetNodeAt(e.X, e.Y); + if (e.Button.Equals(MouseButtons.Right)) + { + string text = _treeView1.SelectedNode.Text; + if (text.StartsWith(TAG_BOARD)) + { + _treeView1.ContextMenu = _contextMenu; + } + } + } + + /// + /// when view board menu item chosen, writes the selected board + /// position to a file and calls the viewer app. + /// + /// ignored + /// ignored + private void OnViewBoardMenuClicked(object sender, EventArgs e) + { + string text = _treeView1.SelectedNode.Text; + if (text.StartsWith(TAG_BOARD)) + { + ViewBoard(text); + } + _treeView1.ContextMenu = null; + } + + /// + /// If double-click a "board" node, calls the viewer + /// for the position + /// + /// + /// + private void OnTreeViewDoubleClick(object sender, System.EventArgs e) + { + string text = _treeView1.SelectedNode.Text; + if (text.StartsWith(TAG_BOARD)) + { + ViewBoard(text); + } + } + + /// + /// set tooltip if over a node with a displayable tag + /// + /// ignored + /// holds mouse position + private void OnTreeViewMouseMove(object sender, MouseEventArgs e) + { + TreeNode node = _treeView1.GetNodeAt(e.X, e.Y); + string tag = string.Empty; + if ((node != null) && (node.Tag != null)) + { + tag = (string)node.Tag; + } + if (!tag.Equals(_tipText)) + { + _tipText = tag; + _tip.SetToolTip(_treeView1, _tipText); + } + } + + + #endregion + + + } +} diff --git a/Form1.resx b/Form1.resx new file mode 100644 index 0000000..3d2bdb8 --- /dev/null +++ b/Form1.resx @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + Form1 + + + 33 + + \ No newline at end of file diff --git a/typhoonUI.csproj b/typhoonUI.csproj new file mode 100644 index 0000000..d4c48d8 --- /dev/null +++ b/typhoonUI.csproj @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/typhoonUI.csproj.user b/typhoonUI.csproj.user new file mode 100644 index 0000000..e31ed2b --- /dev/null +++ b/typhoonUI.csproj.user @@ -0,0 +1,48 @@ + + + + + + + + + + + + diff --git a/typhoonUI.sln b/typhoonUI.sln new file mode 100644 index 0000000..1b3179d --- /dev/null +++ b/typhoonUI.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 7.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "typhoonUI", "typhoonUI.csproj", "{6A1EA114-F59A-4598-A2E1-147B732DD135}" +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + ConfigName.0 = Debug + ConfigName.1 = Release + EndGlobalSection + GlobalSection(ProjectDependencies) = postSolution + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {6A1EA114-F59A-4598-A2E1-147B732DD135}.Debug.ActiveCfg = Debug|.NET + {6A1EA114-F59A-4598-A2E1-147B732DD135}.Debug.Build.0 = Debug|.NET + {6A1EA114-F59A-4598-A2E1-147B732DD135}.Release.ActiveCfg = Release|.NET + {6A1EA114-F59A-4598-A2E1-147B732DD135}.Release.Build.0 = Release|.NET + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal -- 2.45.0