diff --git a/resources/shortcuts.html b/resources/shortcuts.html
new file mode 100644
index 0000000..3ca6c28
--- /dev/null
+++ b/resources/shortcuts.html
@@ -0,0 +1,10 @@
+
+
+
+
+{{SHORTCUTS}}
diff --git a/src/MainForm.cs b/src/MainForm.cs
index d01061e..3d697e5 100644
--- a/src/MainForm.cs
+++ b/src/MainForm.cs
@@ -3,6 +3,7 @@ using System.Text ;
using System.IO ;
using System.Threading ;
using System.Drawing ;
+using System.Security ;
using System.Collections.Generic ;
using System.Windows.Forms ;
@@ -22,7 +23,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 WebBrowser mWebBrowser = new WebBrowser() ;
private Panel mChartImagePanel = new Panel() ;
private PictureBox mChartImagePictureBox = new PictureBox() ;
@@ -114,12 +115,11 @@ public partial class MainForm : Form
buf = buf.Replace( "{{BAD-SHORTCUTS}}", badShortcuts ) ;
buf = buf.Replace( "{{OTHER-MESSAGES}}", otherMsgs ) ;
}
- mStartupWebBrowser.DocumentText = buf ;
+ mWebBrowser.DocumentText = buf ;
// allow searches
mSearchLabel.Enabled = true ;
mSearchQuery.Enabled = true ;
- mSearchResults.Enabled = true ;
mSearchQuery.Focus() ;
}
@@ -201,6 +201,68 @@ public partial class MainForm : Form
}
}
+ public void showShortcuts()
+ {
+ // load the report template
+ string fname = Path.Combine( Program.resourcesDir, "shortcuts.html" ) ;
+ if ( ! File.Exists( fname ) ) {
+ Program.showErrorMsg( "Can't find the shortcuts report template." ) ;
+ return ;
+ }
+ string htmlBuf = File.ReadAllText( fname ) ;
+
+ // FUDGE! We also log the shortcuts, in case WebBrowser is not working e.g. on Mono :-/
+ ILog logger = LogManager.GetLogger( "shortcuts" ) ;
+
+ // generate HTML fragments for each type of shortcut
+ Dictionary> registeredShortcuts = Shortcut.getRegisteredShortcuts() ;
+ string makeShortcutsHtml( string caption, Type shortcutType ) {
+ logger.Info( $"SHORTCUTS: {caption}" ) ;
+ List shortcuts ;
+ if ( ! registeredShortcuts.TryGetValue( shortcutType, out shortcuts ) )
+ return "" ;
+ shortcuts.Sort( (lhs, rhs) => {
+ int rc = String.Compare( lhs.getKeyCode().ToString().ToLower(), rhs.getKeyCode().ToString().ToLower() ) ;
+ if ( rc != 0 )
+ return rc ;
+ int nLhsModifiers = lhs.countModifiers() ;
+ int nRhsModifiers = rhs.countModifiers() ;
+ if ( nLhsModifiers < nRhsModifiers )
+ return -1 ;
+ else if ( nLhsModifiers > nRhsModifiers )
+ return +1 ;
+ else
+ return 0 ;
+ } ) ;
+ StringBuilder buf = new StringBuilder() ;
+ buf.Append( $"" ) ;
+ buf.Append( "" ) ;
+ foreach( Shortcut shortcut in shortcuts ) {
+ logger.Info( $"- {shortcut} => {shortcut.textDescription()}" ) ;
+ buf.Append( "" ) ;
+ buf.Append( "" + SecurityElement.Escape(shortcut.ToString()) ) ;
+ buf.Append( " | " + shortcut.htmlDescription() ) ;
+ }
+ buf.Append( " |
" ) ;
+ return buf.ToString() ;
+ }
+ string htmlBuf2a = makeShortcutsHtml( "Search queries", typeof(SearchQueryShortcut) ) ;
+ string htmlBuf2b = makeShortcutsHtml( "Images", typeof(ChartImageShortcut) ) ;
+
+ // generate the shortcuts report
+ if ( htmlBuf2a != "" && htmlBuf2b != "" ) {
+ mWebBrowser.DocumentText = htmlBuf.Replace( "{{SHORTCUTS}}",
+ "" + htmlBuf2a + " | " + htmlBuf2b + " |
"
+ ) ;
+ } else if ( htmlBuf2a != "" )
+ mWebBrowser.DocumentText = htmlBuf.Replace( "{{SHORTCUTS}}", htmlBuf2a ) ;
+ else if ( htmlBuf2b != "" )
+ mWebBrowser.DocumentText = htmlBuf.Replace( "{{SHORTCUTS}}", htmlBuf2b ) ;
+ else
+ mWebBrowser.DocumentText = htmlBuf.Replace( "{{SHORTCUTS}}", "There are no shortcuts defined." ) ;
+ mWebBrowser.BringToFront() ;
+ }
+
public void setSearchQuery( string s ) { mSearchQuery.Text = s ; }
private void setChartImagePanelScrollPos( int? hscrollPos, int? vscrollPos )
diff --git a/src/MainForm.ui.cs b/src/MainForm.ui.cs
index 6775efa..7e0886d 100644
--- a/src/MainForm.ui.cs
+++ b/src/MainForm.ui.cs
@@ -49,6 +49,12 @@ public partial class MainForm : Form
this.mSearchQuery.Width = mSearchLabel.Width ;
this.mSearchQuery.BorderStyle = BorderStyle.FixedSingle ;
this.mSearchUserControl.Controls.Add( mSearchQuery ) ;
+ LinkLabel showShortcutsLabel = new LinkLabel() ;
+ showShortcutsLabel.Text = "Shortcuts" ;
+ showShortcutsLabel.AutoSize = true ;
+ showShortcutsLabel.Location = new Point( margin, mSearchUserControl.Height-margin-showShortcutsLabel.Height ) ;
+ showShortcutsLabel.LinkClicked += delegate( object sender, LinkLabelLinkClickedEventArgs e ) { showShortcuts() ; } ;
+ this.mSearchUserControl.Controls.Add( showShortcutsLabel ) ;
this.mSplitter.Panel1.Controls.Add( mSearchUserControl ) ;
this.mSearchResults.View = Manina.Windows.Forms.View.Gallery ;
this.mSearchResults.SetRenderer( new AppImageListView.AppImageListViewRenderer() ) ;
@@ -71,16 +77,16 @@ public partial class MainForm : Form
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 ) ;
+ this.mWebBrowser.AutoSize = true ;
+ this.mWebBrowser.Dock = DockStyle.Fill ;
+ mSplitter.Panel2.Controls.Add( mWebBrowser ) ;
// 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 ) ;
+ mWebBrowser.DocumentText = buf.Replace( "{{SPINNER-URL}}", fname ) ;
}
// initialize handlers
@@ -250,7 +256,6 @@ 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() ;
}
@@ -423,12 +428,6 @@ 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 ;
- }
-
// figure out the initial zoom
Debug.Assert( mSearchResults.SelectedItems.Count == 1 ) ;
double userZoom = Program.dataConfig.getDoubleVal( new string[]{"_DefaultZoom"}, 1.0 ) ;
@@ -450,6 +449,7 @@ public partial class MainForm : Form
mMaxZoom = maxZoom ;
// show the selected chart image
+ mChartImagePanel.BringToFront() ;
setChartImagePanelScrollPos( 0, 0 ) ;
doMainFormResize( null ) ;
}
diff --git a/src/Shortcut.cs b/src/Shortcut.cs
index d352b3a..40deeeb 100644
--- a/src/Shortcut.cs
+++ b/src/Shortcut.cs
@@ -1,5 +1,6 @@
using System ;
using System.Text ;
+using System.Security ;
using System.Collections.Generic ;
using System.Windows.Forms ;
@@ -76,6 +77,21 @@ public abstract class Shortcut
return shortcut ;
}
+ public static Dictionary< Type, List > getRegisteredShortcuts()
+ {
+ // return the registered shortcuts (grouped by type)
+ Dictionary> shortcuts = new Dictionary>() ;
+ foreach( Shortcut shortcut in mRegisteredShortcuts.Values ) {
+ Type shortcutType = shortcut.GetType() ;
+ List shortcutList ;
+ if ( ! shortcuts.TryGetValue( shortcutType, out shortcutList ) )
+ shortcuts[shortcutType] = shortcutList = new List() ;
+ shortcutList.Add( shortcut ) ;
+ }
+
+ return shortcuts ;
+ }
+
public override string ToString()
{
// return the Shortcut as a string
@@ -86,11 +102,28 @@ public abstract class Shortcut
buf.Append( "Shift-" ) ;
if ( (mKeys & Keys.Alt) != 0 )
buf.Append( "Alt-" ) ;
- buf.Append( mKeys & ~(Keys.Control | Keys.Shift | Keys.Alt) ) ;
+ buf.Append( getKeyCode() ) ;
return buf.ToString() ;
}
+ public Keys getKeyCode() { return mKeys & ~(Keys.Control | Keys.Shift | Keys.Alt) ; }
+
+ public int countModifiers()
+ {
+ // count how many modifiers the shortcut has
+ int nModifiers = 0 ;
+ if ( (mKeys & Keys.Control) != 0 )
+ ++ nModifiers ;
+ if ( (mKeys & Keys.Shift) != 0 )
+ ++ nModifiers ;
+ if ( (mKeys & Keys.Alt) != 0 )
+ ++ nModifiers ;
+ return nModifiers ;
+ }
+
public abstract void executeShortcut() ;
+ public abstract string textDescription() ;
+ public abstract string htmlDescription() ;
}
@@ -111,6 +144,20 @@ public class ChartImageShortcut : Shortcut
Program.mainForm.loadSearchResults( mChartImages, "HOTKEY:"+this, true ) ;
}
+ public override string textDescription() { return makeDescription( " ; ", false ) ; }
+ public override string htmlDescription() { return makeDescription( "
", true ) ; }
+ private string makeDescription( string sep, bool escape )
+ {
+ StringBuilder buf = new StringBuilder() ;
+ for ( int i=0 ; i < mChartImages.Count ; ++i ) {
+ if ( i > 0 )
+ buf.Append( sep ) ;
+ string caption = mChartImages[i].caption() ;
+ buf.Append( escape ? SecurityElement.Escape(caption) : caption ) ;
+ }
+ return buf.ToString() ;
+ }
+
public void addChartImage( ChartImage ci ) { mChartImages.Add( ci ) ; }
}
@@ -133,4 +180,8 @@ public class SearchQueryShortcut : Shortcut
ILog logger = LogManager.GetLogger( "shortcuts" ) ;
logger.Debug( $"- {mSearchQuery}" ) ;
}
+
+ public override string textDescription() { return mSearchQuery ; }
+ public override string htmlDescription() { return SecurityElement.Escape( mSearchQuery ) ;
+ }
}