From b947a5fba940991a51f2147c9a8338db0a7f2a04 Mon Sep 17 00:00:00 2001 From: Taka Date: Mon, 15 Jul 2019 05:51:37 +0000 Subject: [PATCH] Show any warning messages in the UI after startup has completed. --- resources/spinner.gif | Bin 0 -> 15209 bytes resources/startup-msgs.html | 10 +++++++ resources/startup.html | 15 ++++++++++ src/ChartImage.cs | 8 ++--- src/MainForm.cs | 51 +++++++++++++++++++++++++++----- src/MainForm.ui.cs | 20 +++++++++++++ src/Program.cs | 23 +++++++-------- src/Program2.cs | 57 ++++++++++++++++++++++++++++++++++++ 8 files changed, 161 insertions(+), 23 deletions(-) create mode 100644 resources/spinner.gif create mode 100644 resources/startup-msgs.html create mode 100644 resources/startup.html create mode 100644 src/Program2.cs diff --git a/resources/spinner.gif b/resources/spinner.gif new file mode 100644 index 0000000000000000000000000000000000000000..8585d4b297867629e92db12ed274e3b01bf5d5ae GIT binary patch literal 15209 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 aC#9#r5R5s0e>RA1fjS9_Bmx&~t^Wf&z_K#{ literal 0 HcmV?d00001 diff --git a/resources/startup-msgs.html b/resources/startup-msgs.html new file mode 100644 index 0000000..a24d392 --- /dev/null +++ b/resources/startup-msgs.html @@ -0,0 +1,10 @@ + + + + +{{UNUSED-CONFIGS}} +{{UNCONFIGURED-IMAGES}} +{{BAD-SHORTCUTS}} +{{OTHER-MESSAGES}} diff --git a/resources/startup.html b/resources/startup.html new file mode 100644 index 0000000..4086fbf --- /dev/null +++ b/resources/startup.html @@ -0,0 +1,15 @@ + + + + + + +
+

Loading...
+
+ + diff --git a/src/ChartImage.cs b/src/ChartImage.cs index 462afda..5da812d 100644 --- a/src/ChartImage.cs +++ b/src/ChartImage.cs @@ -22,12 +22,12 @@ public class ChartImage private Image mImage ; private ImageListViewItem mImageListViewItem ; - public ChartImage( string key, string fullPath ) + public ChartImage( string key, string fullPath, dynamic config ) { // initialize the ChartImage mFullPath = fullPath ; - mConfig = Program.dataConfig.data[ key ] ; - if ( mConfig == null ) + mConfig = config ; + if ( config == null ) mConfig = new JObject() ; mImage = Image.FromFile( fullPath ) ; @@ -37,7 +37,7 @@ public class ChartImage if ( val != null ) { Tuple shortcut = parseShortcut( val ) ; if ( shortcut == null ) - logger.Warn( $"Can't parse shortcut: {val}" ) ; + Program.logStartupMsg( "bad-shortcut", $"{key}: {val}" ) ; else { if ( ! mShortcuts.ContainsKey( shortcut ) ) mShortcuts[ shortcut ] = new List() ; diff --git a/src/MainForm.cs b/src/MainForm.cs index c147946..4507cfd 100644 --- a/src/MainForm.cs +++ b/src/MainForm.cs @@ -1,4 +1,5 @@ using System ; +using System.Text ; using System.IO ; using System.Threading ; using System.Drawing ; @@ -21,6 +22,7 @@ public partial class MainForm : Form private Label mSearchLabel = new Label() ; private TextBox mSearchQuery = new TextBox() ; private ImageListView mSearchResults = new ImageListView() ; + private WebBrowser mStartupWebBrowser = new WebBrowser() ; private Panel mChartImagePanel = new Panel() ; private PictureBox mChartImagePictureBox = new PictureBox() ; @@ -41,6 +43,11 @@ public partial class MainForm : Form // initialize ILog logger = LogManager.GetLogger( "startup" ) ; + // build an index of the config entries + HashSet configIndex = new HashSet( + Program.dataConfig.data.ToObject< Dictionary >().Keys + ) ; + // locate the chart images string dataDir = Path.GetFullPath( Program.dataDir ) ; IEnumerable files = Directory.EnumerateFiles( @@ -64,7 +71,12 @@ public partial class MainForm : Form key = fullPath ; } logger.Debug( $"Loading image: {key}" ) ; - ChartImage chartImage = new ChartImage( key, fullPath ) ; + dynamic config = Program.dataConfig.data[ key ] ; + if ( config == null ) + Program.logStartupMsg( "unconfigured-image", fname.Substring(dataDir.Length+1) ) ; + else + configIndex.Remove( key ) ; + ChartImage chartImage = new ChartImage( key, fullPath, config ) ; mChartImages[ key ] = chartImage ; // add the image to the list @@ -72,12 +84,37 @@ public partial class MainForm : Form mSearchResults.Invoke( (MethodInvoker) ( () => mSearchResults.Items.Add( item ) ) ) ; } - // everything has been loaded, allow searches - mSearchQuery.Invoke( (MethodInvoker) ( () => { - mSearchLabel.Enabled = true ; - mSearchQuery.Enabled = true ; - mSearchQuery.Focus() ; - } ) ) ; + // log any config entries that were unused + foreach( string key in configIndex ) + Program.logStartupMsg( "unused-config", key ) ; + + // everything has been loaded, update the UI + this.Invoke( (MethodInvoker) onStartupCompleted ) ; + } + + private void onStartupCompleted() + { + // show any startup messages + string unusedConfigs = Program.getStartupMsgs( "unused-config", "WARNING: Found unused configuration entries:" ) ; + string unconfiguredImages = Program.getStartupMsgs( "unconfigured-image", "WARNING: Found image files with no configuration:" ) ; + string badShortcuts = Program.getStartupMsgs( "bad-shortcut", "WARNING: Couldn't parse shortcuts:" ) ; + string otherMsgs = Program.getStartupMsgs( "", "" ) ; + string buf = "" ; + string fname = Path.Combine( Program.resourcesDir, "startup-msgs.html" ) ; + if ( File.Exists( fname ) ) { + buf = File.ReadAllText( fname ) ; + buf = buf.Replace( "{{UNUSED-CONFIGS}}", unusedConfigs ) ; + buf = buf.Replace( "{{UNCONFIGURED-IMAGES}}", unconfiguredImages ) ; + buf = buf.Replace( "{{BAD-SHORTCUTS}}", badShortcuts ) ; + buf = buf.Replace( "{{OTHER-MESSAGES}}", otherMsgs ) ; + } + mStartupWebBrowser.DocumentText = buf ; + + // allow searches + mSearchLabel.Enabled = true ; + mSearchQuery.Enabled = true ; + mSearchResults.Enabled = true ; + mSearchQuery.Focus() ; } private void updateSearchResults( string searchQuery ) diff --git a/src/MainForm.ui.cs b/src/MainForm.ui.cs index fde4407..e1f2283 100644 --- a/src/MainForm.ui.cs +++ b/src/MainForm.ui.cs @@ -69,6 +69,19 @@ public partial class MainForm : Form mChartImagePanel.Controls.Add( mChartImagePictureBox ) ; mSplitter.Panel2.Controls.Add( mChartImagePanel ) ; + // initialize the bottom pane (startup messages) + this.mStartupWebBrowser.AutoSize = true ; + this.mStartupWebBrowser.Dock = DockStyle.Fill ; + mSplitter.Panel2.Controls.Add( mStartupWebBrowser ) ; + + // show the startup page + string fname = Path.Combine( Program.resourcesDir, "startup.html" ) ; + if ( File.Exists( fname ) ) { + string buf = File.ReadAllText( fname ) ; + fname = Path.Combine( Program.resourcesDir, "spinner.gif" ) ; + mStartupWebBrowser.DocumentText = buf.Replace( "{{SPINNER-URL}}", fname ) ; + } + // initialize handlers this.Load += new EventHandler( this.MainForm_Load ) ; this.FormClosing += new FormClosingEventHandler( this.MainForm_FormClosing ) ; @@ -135,6 +148,7 @@ public partial class MainForm : Form // NOTE: This can take some time, so we update the UI as they are loaded. mSearchLabel.Enabled = false ; mSearchQuery.Enabled = false ; + mSearchResults.Enabled = false ; Thread thread = new Thread( () => loadChartImages() ) ; thread.Start() ; } @@ -323,6 +337,12 @@ public partial class MainForm : Form private void SearchResults_SelectionChanged( object sender, EventArgs e ) { + // remove the startup messages + if ( mStartupWebBrowser != null ) { + mSplitter.Panel2.Controls.Remove( mStartupWebBrowser ) ; + mStartupWebBrowser = null ; + } + // show the selected chart image Debug.Assert( mSearchResults.SelectedItems.Count == 1 ) ; ChartImage chartImage ; diff --git a/src/Program.cs b/src/Program.cs index 9a5bc59..0686a5e 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -1,27 +1,27 @@ using System ; using System.Windows.Forms ; using System.IO ; +using System.Collections.Generic ; using System.Diagnostics ; using log4net.Config ; // -------------------------------------------------------------------- -public static class Program +public static partial class Program { - private class MyMessageFilter : IMessageFilter { - public bool PreFilterMessage( ref Message msg ) { return Program.preFilterMessage( ref msg ) ; } - } public const string APP_NAME = "ASL Charts" ; private static bool mIsMono ; private static string mBaseDir ; + private static string mResourcesDir ; private static string mDataDir ; private static JsonConfig mAppConfig = null ; private static JsonConfig mDataConfig = null ; private static JsonConfig mDebugConfig = null ; private static MainForm mMainForm = null ; + private static Dictionary< string, List > mStartupMsgs = new Dictionary>() ; [STAThread] static void Main( string[] args ) @@ -37,6 +37,11 @@ public static class Program if ( File.Exists( fname ) ) XmlConfigurator.Configure( new FileInfo( fname ) ) ; + // locate the resources directory + mResourcesDir = Path.Combine( mBaseDir, "resources" ) ; + if ( ! Directory.Exists( mResourcesDir ) ) + mResourcesDir = Path.Combine( mBaseDir, "../resources" ) ; + // locate the data directory mDataDir = Path.Combine( mBaseDir , "data" ) ; if ( ! Directory.Exists( mDataDir ) ) { @@ -78,14 +83,6 @@ public static class Program Application.Run( mMainForm ) ; } - public static bool preFilterMessage( ref Message msg ) - { - // check if we should filter this message - if ( Program.mainForm.preFilterMessage( ref msg ) ) - return true ; - return false ; - } - 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) ; } @@ -93,6 +90,8 @@ public static class Program public static bool isMono { get { return mIsMono ; } } public static MainForm mainForm { get { return mMainForm ; } } + public static string baseDir { get { return mBaseDir ; } } + public static string resourcesDir { get { return mResourcesDir ; } } public static JsonConfig appConfig { get { return mAppConfig ; } } public static JsonConfig dataConfig { get { return mDataConfig ; } } public static JsonConfig debugConfig { get { return mDebugConfig ; } } diff --git a/src/Program2.cs b/src/Program2.cs new file mode 100644 index 0000000..c3bed1d --- /dev/null +++ b/src/Program2.cs @@ -0,0 +1,57 @@ +using System.Security ; +using System.Text ; +using System.Windows.Forms ; +using System.Collections.Generic ; + +using log4net ; + +// -------------------------------------------------------------------- + +public static partial class Program +{ + + private class MyMessageFilter : IMessageFilter { + public bool PreFilterMessage( ref Message msg ) { + // check if we should filter this message + if ( Program.mainForm.preFilterMessage( ref msg ) ) + return true ; + return false ; + } + } + + public static void logStartupMsg( string key, string msg ) + { + // log the startup message + List msgs ; + if ( ! mStartupMsgs.TryGetValue( key, out msgs ) ) + mStartupMsgs[key] = msgs = new List() ; + msgs.Add( msg ) ; + } + + public static string getStartupMsgs( string key, string caption ) + { + // check if there were any startup messages of the specified type + List msgs ; + if ( ! mStartupMsgs.TryGetValue( key, out msgs ) || msgs.Count == 0 ) + return "" ; + + // NOTE: WebBrowser isn't really available with Mono, so we just log startup messages normally. + ILog logger = LogManager.GetLogger( "startup" ) ; + + // generate a report for the specified startup messages + StringBuilder buf = new StringBuilder() ; + if ( caption != "" ) { + buf.Append( caption ) ; + logger.Warn( caption ) ; + } + buf.Append( "
    " ) ; + foreach ( string msg in msgs ) { + buf.Append( "
  • " + SecurityElement.Escape(msg) ) ; + logger.Warn( (caption != "") ? $"- {msg}" : msg ) ; + } + buf.Append( "
" ) ; + + return buf.ToString() ; + } + +}