@ -0,0 +1,6 @@ |
||||
app.config |
||||
out/ |
||||
|
||||
.vscode/ |
||||
*.swp |
||||
*.swo |
@ -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)
|
After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 154 KiB |
After Width: | Height: | Size: 81 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 207 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 274 KiB |
@ -0,0 +1 @@ |
||||
{} |
@ -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 ; |
||||
} |
||||
} |
||||
} |
@ -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<string> mValidImageExtensions = new HashSet<string>{ ".png", ".jpg", ".gif" } ; |
||||
|
||||
private Dictionary<string,Image> mImages = new Dictionary<string,Image>() ; |
||||
private Dictionary<string,Image>.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<string> 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<String,Image> val ; |
||||
if ( ! mImagesIter.MoveNext() ) { |
||||
mImagesIter = mImages.GetEnumerator() ; |
||||
mImagesIter.MoveNext() ; |
||||
} |
||||
val = mImagesIter.Current ; |
||||
mImagePictureBox.Image = val.Value ; |
||||
} |
||||
} |
||||
} |
@ -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 ; } } |
||||
} |