commit 14d215456845f512e7ac953831f505a8c27e126f Author: Taka Date: Mon May 13 18:31:33 2019 +0000 First cut. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b8a1eeb --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +app.config +out/ + +.vscode/ +*.swp +*.swo diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3c4c2ff --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +SRC := $(wildcard src/*.cs) +OUTPUT := out + +all: init compile + +init: + mkdir -p $(OUTPUT) + +compile: + csc $(SRC) /nologo /warnaserror \ + /d:TRACE \ + /target:winexe /out:$(OUTPUT)/asl-charts.exe + cp app.config $(OUTPUT)/asl-charts.exe.config + +clean: + rm -r $(OUTPUT) diff --git a/data/IIFTMQRDCc/afv-destruction.png b/data/IIFTMQRDCc/afv-destruction.png new file mode 100644 index 0000000..c4ac1f1 Binary files /dev/null and b/data/IIFTMQRDCc/afv-destruction.png differ diff --git a/data/IIFTMQRDCc/ambush.png b/data/IIFTMQRDCc/ambush.png new file mode 100644 index 0000000..ad70f7d Binary files /dev/null and b/data/IIFTMQRDCc/ambush.png differ diff --git a/data/IIFTMQRDCc/ap-to-kill.png b/data/IIFTMQRDCc/ap-to-kill.png new file mode 100644 index 0000000..d916de2 Binary files /dev/null and b/data/IIFTMQRDCc/ap-to-kill.png differ diff --git a/data/IIFTMQRDCc/apcr-apds-to-kill.png b/data/IIFTMQRDCc/apcr-apds-to-kill.png new file mode 100644 index 0000000..cd9ed44 Binary files /dev/null and b/data/IIFTMQRDCc/apcr-apds-to-kill.png differ diff --git a/data/IIFTMQRDCc/close-combat.png b/data/IIFTMQRDCc/close-combat.png new file mode 100644 index 0000000..05db8ce Binary files /dev/null and b/data/IIFTMQRDCc/close-combat.png differ diff --git a/data/IIFTMQRDCc/heat-of-battle.png b/data/IIFTMQRDCc/heat-of-battle.png new file mode 100644 index 0000000..4d2bffd Binary files /dev/null and b/data/IIFTMQRDCc/heat-of-battle.png differ diff --git a/data/IIFTMQRDCc/heat-to-kill.png b/data/IIFTMQRDCc/heat-to-kill.png new file mode 100644 index 0000000..d676b1d Binary files /dev/null and b/data/IIFTMQRDCc/heat-to-kill.png differ diff --git a/data/IIFTMQRDCc/iift.png b/data/IIFTMQRDCc/iift.png new file mode 100644 index 0000000..3304fae Binary files /dev/null and b/data/IIFTMQRDCc/iift.png differ diff --git a/data/IIFTMQRDCc/leader-creation.png b/data/IIFTMQRDCc/leader-creation.png new file mode 100644 index 0000000..678b3d7 Binary files /dev/null and b/data/IIFTMQRDCc/leader-creation.png differ diff --git a/data/IIFTMQRDCc/to-hit.png b/data/IIFTMQRDCc/to-hit.png new file mode 100644 index 0000000..de432b3 Binary files /dev/null and b/data/IIFTMQRDCc/to-hit.png differ diff --git a/data/config.json b/data/config.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/data/config.json @@ -0,0 +1 @@ +{} diff --git a/src/JsonConfig.cs b/src/JsonConfig.cs new file mode 100644 index 0000000..bb09e64 --- /dev/null +++ b/src/JsonConfig.cs @@ -0,0 +1,49 @@ +using System ; +using System.Text ; +using System.IO ; +using System.Runtime.Serialization.Json ; +using System.Xml ; +using System.Xml.Linq ; +using System.Xml.XPath ; + +// -------------------------------------------------------------------- + +public class JsonConfig +{ + private XElement mRootElem ; + + public JsonConfig( string caption, string fname ) + { + // load the JSON config + string data ; + if ( File.Exists( fname ) ) { + Program.logTraceMsg( String.Format( "Loading {0}: {1}", caption, Path.GetFullPath(fname) ) ) ; + data = File.ReadAllText( fname ) ; + } else + data ="{}" ; + var jsonReader = JsonReaderWriterFactory.CreateJsonReader( + Encoding.UTF8.GetBytes( data ), + new XmlDictionaryReaderQuotas() + ) ; + mRootElem = XElement.Load( jsonReader ) ; + } + + public string getStringVal( string xpath, string defaultVal="" ) + { + // return the specified value + var elem = mRootElem.XPathSelectElement( xpath ) ; + if ( elem == null ) + return defaultVal ; + return elem.Value ; + } + + public int getIntVal( string xpath, int defaultVal=0 ) + { + // return the specified value + try { + return Int32.Parse( getStringVal( xpath ) ) ; + } catch( System.FormatException ) { + return defaultVal ; + } + } +} diff --git a/src/MainForm.cs b/src/MainForm.cs new file mode 100644 index 0000000..76cae0d --- /dev/null +++ b/src/MainForm.cs @@ -0,0 +1,78 @@ +using System ; +using System.Text ; +using System.Drawing ; +using System.IO ; +using System.Runtime.InteropServices ; +using System.Collections.Generic ; +using System.Windows.Forms ; +using System.Diagnostics ; + +// -------------------------------------------------------------------- + +public class MainForm : Form +{ + private readonly HashSet mValidImageExtensions = new HashSet{ ".png", ".jpg", ".gif" } ; + + private Dictionary mImages = new Dictionary() ; + private Dictionary.Enumerator mImagesIter ; + + private PictureBox mImagePictureBox = new PictureBox() ; + + public MainForm() + { + // initialize the form + this.Text = Program.APP_NAME ; + this.MinimumSize = new Size( 800, 500 ) ; + + // initialize the form + // FIXME! We will probably need something better to render the images, but this will do, for now... + this.mImagePictureBox.Dock = DockStyle.Fill ; + this.mImagePictureBox.SizeMode = PictureBoxSizeMode.Zoom ; + this.Controls.Add( mImagePictureBox ) ; + + // initialize handlers + this.Load += new EventHandler( this.MainForm_Load ) ; + this.KeyDown += new System.Windows.Forms.KeyEventHandler( this.MainForm_KeyDown ) ; + } + + private void MainForm_Load( object sender, EventArgs args ) + { + // locate the image files + string dataDir = Path.GetFullPath( Program.dataDir ) ; + IEnumerable files = Directory.EnumerateFiles( + dataDir, "*.*", SearchOption.AllDirectories + ) ; + foreach( string fname in files ) { + string extn = Path.GetExtension( fname ).ToLower() ; + if ( ! mValidImageExtensions.Contains( extn ) ) + continue ; + string fname2 = Path.GetFullPath( fname ) ; + if ( fname2.StartsWith( dataDir ) ) { + fname2 = fname.Substring( dataDir.Length ) ; + if ( fname2.StartsWith( "/" ) || fname2.StartsWith( "\\" ) ) + fname2 = fname2.Substring( 1 ) ; + } else { + // NOTE: I don't think we should ever get here :-/ If we do, the user will have to manage + // their configuration using full paths for the image files, but at least we will still run... + } + Program.logTraceMsg( String.Format( "Loading image: {0}", fname2 ) ) ; + mImages[ fname2 ] = Image.FromFile( fname ) ; + } + mImagesIter = mImages.GetEnumerator() ; + } + + private void MainForm_KeyDown( object sender, KeyEventArgs args ) + { + // FIXME! For now, we just allow the user to cycle through the loaded images. + if ( args.KeyCode == Keys.Space ) { + // show the next image + KeyValuePair val ; + if ( ! mImagesIter.MoveNext() ) { + mImagesIter = mImages.GetEnumerator() ; + mImagesIter.MoveNext() ; + } + val = mImagesIter.Current ; + mImagePictureBox.Image = val.Value ; + } + } +} diff --git a/src/Program.cs b/src/Program.cs new file mode 100644 index 0000000..de760df --- /dev/null +++ b/src/Program.cs @@ -0,0 +1,67 @@ +using System ; +using System.Windows.Forms ; +using System.IO ; +using System.Diagnostics ; + +// -------------------------------------------------------------------- + +public static class Program +{ + public const string APP_NAME = "ASL Charts" ; + + private static string mBaseDir ; + private static string mDataDir ; + private static JsonConfig mAppConfig = null ; + private static JsonConfig mDebugConfig = null ; + private static MainForm mMainForm = null ; + + [STAThread] + static void Main( string[] args ) + { + // initialize + mBaseDir = Application.StartupPath ; + + // locate the data directory + mDataDir = System.IO.Path.Combine( mBaseDir , "data" ) ; + if ( ! Directory.Exists( mDataDir ) ) { + mDataDir = System.IO.Path.Combine( mBaseDir , "../data" ) ; + if ( ! Directory.Exists( mDataDir ) ) + mDataDir = mBaseDir ; + } + + try { + + // load the app config + // NOTE: It would be nice to be able to load the app config from another location, but it seems + // we need to create a new AppDomain to do this, and it doesn't work with Mono :-/ + mAppConfig = new JsonConfig( "app config", Path.Combine( mDataDir, "config.json" ) ) ; + + // load the debug config + mDebugConfig = new JsonConfig( "debug config", Path.Combine( mBaseDir, "debug.json" ) ) ; + + } catch( Exception ex ) { + showErrorMsg( "Initialization failed:\n\n" + ex.Message ) ; + return ; + } + + // run the application + Application.EnableVisualStyles() ; + Application.SetCompatibleTextRenderingDefault( false ) ; + mMainForm = new MainForm() ; + Application.Run( mMainForm ) ; + } + + public static void showInfoMsg( string msg ) { MessageBox.Show(msg,APP_NAME,MessageBoxButtons.OK,MessageBoxIcon.Information) ; } + public static void showWarningMsg( string msg ) { MessageBox.Show(msg,APP_NAME,MessageBoxButtons.OK,MessageBoxIcon.Warning) ; } + public static void showErrorMsg( string msg ) { MessageBox.Show(msg,APP_NAME,MessageBoxButtons.OK,MessageBoxIcon.Error) ; } + + public static void logTraceMsg( string msg ) + { + // log a trace message + Trace.WriteLine( DateTime.Now.ToString("HH:mm:ss") + " | " + msg ) ; + } + + public static JsonConfig appConfig { get { return mAppConfig ; } } + public static JsonConfig debugConfig { get { return mDebugConfig ; } } + public static string dataDir { get { return mDataDir ; } } +}