using System ; using System.Text ; using System.Security ; using System.Collections.Generic ; using System.Windows.Forms ; using log4net ; // -------------------------------------------------------------------- public abstract class Shortcut { private static Dictionary mRegisteredShortcuts = new Dictionary() ; private static Shortcut mLastShortcut = null ; private static DateTime mLastShortcutTimestamp = DateTime.Now ; private Keys mKeys ; public Shortcut( Keys keys ) { // initialize mKeys = keys ; } public static Keys? parseShortcutString( string val ) { // parse the shortcut // FUDGE! We can't just pass in '-' since a Mono-compiled EXE has trouble running on Windows :-/ string[] parts = val.ToLower().Split( new char[]{'-'} ) ; if ( parts.Length <= 1 ) return null ; Keys keys ; bool rc = Enum.TryParse( parts[parts.Length-1], true, out keys ) ; if ( ! rc ) return null ; for ( int i=0 ; i < parts.Length-1 ; ++i ) { if ( parts[i] == "ctrl" ) keys |= Keys.Control ; else if ( parts[i] == "alt" ) keys |= Keys.Alt ; else if ( parts[i] == "shift" ) keys |= Keys.Shift ; else return null ; } return keys ; } public static bool handleShortcut( Keys keys ) { // look for a registered shortcut Shortcut shortcut = findRegisteredShortcut( keys ) ; if ( shortcut == null ) return false ; // found one - check if it's the same as the last shortcut used ILog logger = LogManager.GetLogger( "shortcuts" ) ; if ( mLastShortcut != null && Object.ReferenceEquals( shortcut, mLastShortcut ) ) { // yup - check how much time has passed since the last shortcut was used TimeSpan delta = DateTime.Now - mLastShortcutTimestamp ; double cutoff = Program.appConfig.getDoubleVal( new string[]{"ShortcutRepeatThreshold"}, 5 ) ; logger.Debug( $"Repeated shortcut: {mLastShortcut} ; delta={delta.TotalSeconds} ; cutoff={cutoff}" ) ; if ( delta.TotalSeconds <= cutoff ) { // less than the threshold - select the next search result instead logger.Debug( "- Selecting next search result instead." ) ; Program.mainForm.selectSearchResult( Keys.Right ) ; mLastShortcutTimestamp = DateTime.Now ; return true ; } } logger.Info( $"Executing shortcut: {shortcut}" ) ; shortcut.executeShortcut() ; mLastShortcut = shortcut ; mLastShortcutTimestamp = DateTime.Now ; return true ; } public static void resetLastShortcut() { mLastShortcut = null ; } public static void registerShortcut( Shortcut shortcut ) { // register the shortcut if ( findRegisteredShortcut( shortcut.mKeys ) != null ) { Program.logStartupMsg( "bad-shortcut", $"Found duplicate: {shortcut}" ) ; } mRegisteredShortcuts[ shortcut.mKeys ] = shortcut ; } public static Shortcut findRegisteredShortcut( Keys keys ) { // look for a registered shortcut Shortcut shortcut ; if ( ! mRegisteredShortcuts.TryGetValue( keys, out shortcut ) ) return null ; 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 StringBuilder buf = new StringBuilder() ; if ( (mKeys & Keys.Control) != 0 ) buf.Append( "Ctrl-" ) ; if ( (mKeys & Keys.Shift) != 0 ) buf.Append( "Shift-" ) ; if ( (mKeys & Keys.Alt) != 0 ) buf.Append( "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() ; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - public class ChartImageShortcut : Shortcut { private List mChartImages = new List() ; public ChartImageShortcut( Keys keys ) : base( keys ) { } public override void executeShortcut() { // execute the shortcut ILog logger = LogManager.GetLogger( "shortcuts" ) ; foreach ( ChartImage chartImage in mChartImages ) logger.Debug( $"- {chartImage.caption()}" ) ; 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 ) ; } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - public class SearchQueryShortcut : Shortcut { private string mSearchQuery ; public SearchQueryShortcut( Keys keys, string searchQuery ) : base( keys ) { // initialize mSearchQuery = searchQuery ; } public override void executeShortcut() { // execute the shortcut Program.mainForm.setSearchQuery( mSearchQuery ) ; ILog logger = LogManager.GetLogger( "shortcuts" ) ; logger.Debug( $"- {mSearchQuery}" ) ; } public override string textDescription() { return mSearchQuery ; } public override string htmlDescription() { return SecurityElement.Escape( mSearchQuery ) ; } }