diff --git a/data/config.json b/data/config.json index 753a671..7b18da2 100644 --- a/data/config.json +++ b/data/config.json @@ -1,5 +1,9 @@ { +"_DefaultZoom": 0.3, +"_MinZoom": 0.1, +"_MaxZoom": 1.0, + "IIFTMQRDCc/leader-creation.png": { "caption": "Leader Creation", "keywords": [ "LC", "leader" ], @@ -20,6 +24,7 @@ "IIFTMQRDCc/iift.png": { "caption": "Incremental IFT", + "defaultZoom": 0.2, "keywords": [ "IFT", "IIFT" ], "shortcut": "Ctrl-Alt-I" }, diff --git a/src/ChartImage.cs b/src/ChartImage.cs index 5da812d..dee0420 100644 --- a/src/ChartImage.cs +++ b/src/ChartImage.cs @@ -17,7 +17,7 @@ public class ChartImage private static Dictionary< Tuple, List > mShortcuts = new Dictionary< Tuple, List >() ; private string mFullPath ; - private dynamic mConfig ; + private JsonConfig mJsonConfig ; private HashSet mKeywords = new HashSet() ; private Image mImage ; private ImageListViewItem mImageListViewItem ; @@ -26,15 +26,13 @@ public class ChartImage { // initialize the ChartImage mFullPath = fullPath ; - mConfig = config ; - if ( config == null ) - mConfig = new JObject() ; + mJsonConfig = new JsonConfig( config ) ; mImage = Image.FromFile( fullPath ) ; // parse the shortcut ILog logger = LogManager.GetLogger( "shortcuts" ) ; - string val = mConfig[ "shortcut" ] ; - if ( val != null ) { + string val = mJsonConfig.getStringVal( new string[]{"shortcut"} ) ; + if ( val != "" ) { Tuple shortcut = parseShortcut( val ) ; if ( shortcut == null ) Program.logStartupMsg( "bad-shortcut", $"{key}: {val}" ) ; @@ -47,8 +45,8 @@ public class ChartImage } // prepare for search scoring - if ( mConfig["keywords"] != null ) { - foreach( string kywd in mConfig["keywords"] ) + if ( config != null && config["keywords"] != null ) { + foreach( string kywd in config["keywords"] ) mKeywords.Add( kywd.ToUpper() ) ; } @@ -59,11 +57,11 @@ public class ChartImage mImageListViewItem.Text = caption() ; } - public float getSearchScore( string searchQuery ) + public double getSearchScore( string searchQuery ) { // initialize searchQuery = searchQuery.ToUpper() ; - List< Tuple > scores = new List>() ; + List< Tuple > scores = new List>() ; ILog logger = LogManager.GetLogger( "search" ) ; if ( logger.IsDebugEnabled ) { if ( mKeywords.Count == 0 ) @@ -78,27 +76,27 @@ public class ChartImage } // initialize the search score weights - float exactKeywordMatchScore = Program.appConfig.getFloatVal( new string[]{"search","exactKeywordMatchScore"}, 10f ) ; - float leadingPartialKeywordMatchScore = Program.appConfig.getFloatVal( new string[]{"search","leadingPartialKeywordMatchScore"}, 2f ) ; - float internalPartialKeywordMatchScore = Program.appConfig.getFloatVal( new string[]{"search","internalPartialKeywordMatchScore"}, 1.5f ) ; - float exactCaptionMatchScore = Program.appConfig.getFloatVal( new string[]{"search","exactCaptionMatchScore"}, 5f ) ; - float leadingPartialCaptionMatchScore = Program.appConfig.getFloatVal( new string[]{"search","leadingPartialCaptionMatchScore"}, 1f ) ; - float internalPartialCaptionMatchScore = Program.appConfig.getFloatVal( new string[]{"search","internalPartialCaptionMatchScore"}, 0.5f ) ; + double exactKeywordMatchScore = Program.appConfig.getDoubleVal( new string[]{"search","exactKeywordMatchScore"}, 10 ) ; + double leadingPartialKeywordMatchScore = Program.appConfig.getDoubleVal( new string[]{"search","leadingPartialKeywordMatchScore"}, 2 ) ; + double internalPartialKeywordMatchScore = Program.appConfig.getDoubleVal( new string[]{"search","internalPartialKeywordMatchScore"}, 1.5 ) ; + double exactCaptionMatchScore = Program.appConfig.getDoubleVal( new string[]{"search","exactCaptionMatchScore"}, 5 ) ; + double leadingPartialCaptionMatchScore = Program.appConfig.getDoubleVal( new string[]{"search","leadingPartialCaptionMatchScore"}, 1 ) ; + double internalPartialCaptionMatchScore = Program.appConfig.getDoubleVal( new string[]{"search","internalPartialCaptionMatchScore"}, 0.5 ) ; // look for keyword matches foreach ( string kywd in mKeywords ) { if ( kywd == searchQuery ) { - scores.Add( new Tuple( "exactKeywordMatch", exactKeywordMatchScore ) ) ; + scores.Add( new Tuple( "exactKeywordMatch", exactKeywordMatchScore ) ) ; continue ; } int pos = kywd.IndexOf( searchQuery ) ; if ( pos == 0 ) { - scores.Add( new Tuple( + scores.Add( new Tuple( $"leadingPartialKeywordMatch[{kywd}]", Math.Min( leadingPartialKeywordMatchScore * searchQuery.Length, exactKeywordMatchScore ) ) ) ; } else if ( pos > 0 ) { - scores.Add( new Tuple( + scores.Add( new Tuple( $"internalPartialKeywordMatch[{kywd}]", Math.Min( internalPartialKeywordMatchScore * searchQuery.Length, exactKeywordMatchScore ) ) ) ; @@ -108,16 +106,16 @@ public class ChartImage // look for caption matches string caption = this.caption().ToUpper() ; if ( searchQuery == caption ) - scores.Add( new Tuple( "exactCaptionMatch", exactCaptionMatchScore ) ) ; + scores.Add( new Tuple( "exactCaptionMatch", exactCaptionMatchScore ) ) ; else { int pos = caption.IndexOf( searchQuery ) ; if ( pos == 0 ) { - scores.Add( new Tuple( + scores.Add( new Tuple( $"leadingPartialCaptionMatch[{caption}]", Math.Min( leadingPartialCaptionMatchScore * searchQuery.Length, exactCaptionMatchScore ) ) ) ; } else if ( pos > 0 ) { - scores.Add( new Tuple( + scores.Add( new Tuple( $"internalPartialCaptionMatch[{caption}]", Math.Min( internalPartialCaptionMatchScore * searchQuery.Length, exactCaptionMatchScore ) ) ) ; @@ -125,7 +123,7 @@ public class ChartImage } // calculate the total score - float totalScore = 0 ; + double totalScore = 0 ; StringBuilder buf = logger.IsDebugEnabled ? new StringBuilder() : null ; for ( int i=0 ; i < scores.Count ; ++i ) { totalScore += scores[i].Item2 ; @@ -190,12 +188,14 @@ public class ChartImage public string caption() { - string caption = (mConfig != null) ? mConfig["caption"] : null ; - if ( caption == null ) - caption = Path.GetFileNameWithoutExtension( mFullPath ) ; - return caption ; + // return the ChartImage's caption + return jsonConfig.getStringVal( + new string[]{ "caption" }, + Path.GetFileNameWithoutExtension( mFullPath ) + ) ; } + public JsonConfig jsonConfig { get { return mJsonConfig ; } } public Image image { get { return mImage ; } } public ImageListViewItem imageListViewItem { get { return mImageListViewItem ; } } } diff --git a/src/JsonConfig.cs b/src/JsonConfig.cs index ea2e4fe..88d42d0 100644 --- a/src/JsonConfig.cs +++ b/src/JsonConfig.cs @@ -29,6 +29,12 @@ public class JsonConfig logger.Debug( mData.ToString() ) ; } + public JsonConfig( dynamic data ) + { + // initialize + mData = (data != null) ? data : new JObject() ; + } + public string getStringVal( string[] keys, string defaultVal="" ) { // get the specified value @@ -54,12 +60,12 @@ public class JsonConfig } public void setIntVal( string[] keys, int val, bool save=true ) { setVal( keys, val, save ) ; } - public float getFloatVal( string[] keys, float defaultVal=0 ) + public double getDoubleVal( string[] keys, double defaultVal=0 ) { // get the specified value string val = getStringVal( keys ) ; try { - return float.Parse( val ) ; + return double.Parse( val ) ; } catch( FormatException ) { return defaultVal ; } diff --git a/src/MainForm.cs b/src/MainForm.cs index 570cc73..c4d0a89 100644 --- a/src/MainForm.cs +++ b/src/MainForm.cs @@ -29,7 +29,7 @@ public partial class MainForm : Form private string mSearchResultsKey = null ; private Point? mMouseDragAnchor = null ; private Tuple mScrollDragAnchor ; - private double mUserZoom = 1.0 ; + private double mCurrZoom, mMinZoom, mMaxZoom ; private DateTime mLastKeyPressTimeStamp = DateTime.Now ; public MainForm() @@ -86,8 +86,11 @@ public partial class MainForm : Form } // log any config entries that were unused - foreach( string key in configIndex ) + foreach( string key in configIndex ) { + if ( key[0] == '_' ) + continue ; Program.logStartupMsg( "unused-config", key ) ; + } // everything has been loaded, update the UI this.Invoke( (MethodInvoker) onStartupCompleted ) ; @@ -126,9 +129,9 @@ public partial class MainForm : Form logger.Info( $"Updating search results: query=\"{searchQuery}\"" ) ; // search for matching chart images - List< Tuple > results = new List>() ; + List< Tuple > results = new List>() ; foreach( ChartImage chartImage in mChartImages.Values ) { - float score ; + double score ; if ( searchQuery == "" ) score = 0 ; else { @@ -136,7 +139,7 @@ public partial class MainForm : Form if ( score <= 0 ) continue ; } - results.Add( new Tuple( chartImage, score ) ) ; + results.Add( new Tuple( chartImage, score ) ) ; } // sort the search results diff --git a/src/MainForm.ui.cs b/src/MainForm.ui.cs index cd0587f..08fac85 100644 --- a/src/MainForm.ui.cs +++ b/src/MainForm.ui.cs @@ -9,6 +9,7 @@ using System.Windows.Forms ; using System.Diagnostics ; using Manina.Windows.Forms ; +using Newtonsoft.Json.Linq ; using log4net ; // -------------------------------------------------------------------- @@ -183,28 +184,13 @@ public partial class MainForm : Form mSplitter.Panel2.Height - (Program.isMono?28:40) ) ; - // try to size the image to fill the available width + // figure out how large to show the ChartImage + int width, height ; int margin = 5 ; - float aspectRatio = (float)img.Width / (float)img.Height ; int availableWidth = mChartImagePanel.Width - 2*margin ; - int width = availableWidth ; - int height = (int) (availableWidth / aspectRatio) ; - - // check that we're not zooming in/out too much - float zoom = (float)width / (float)img.Width ; - float minZoom = Program.appConfig.getFloatVal( new string[]{"MinZoom"}, 0.5f ) ; - float maxZoom = Program.appConfig.getFloatVal( new string[]{"MaxZoom"}, 2f ) ; - if ( minZoom > 0 && zoom < minZoom ) { - width = (int) (img.Width * minZoom) ; - height = (int) (img.Height * minZoom) ; - } else if ( maxZoom > 0 && zoom > maxZoom ) { - width = (int) (img.Width * maxZoom) ; - height = (int) (img.Height * maxZoom) ; - } - - // incorporate the user-controlled manual zoom - width = (int)( width * mUserZoom + 0.5 ) ; - height = (int)( height * mUserZoom + 0.5 ) ; + double zoom = Math.Max( Math.Min( mCurrZoom, mMaxZoom ), mMinZoom ) ; + width = (int)( img.Width * zoom + 0.5 ) ; + height = (int)( img.Height * zoom + 0.5 ) ; // check if the v-scrollbar is showing if ( height >= mChartImagePanel.Height ) { @@ -298,14 +284,18 @@ public partial class MainForm : Form int scrollX = hscroll.Value + (int)( scrollRange * nLines/100 ) ; scrollChartImagePanel( scrollX, null ) ; } else if ( (Control.ModifierKeys & Keys.Control) != 0 ) { + double newZoom ; if ( nLines > 0 ) { - float maxUserZoom = Program.appConfig.getFloatVal( new string[]{"MaxUserZoom"}, 2.0f ) ; - mUserZoom = Math.Min( mUserZoom+0.1, maxUserZoom ) ; + newZoom = Math.Min( mCurrZoom+0.05, mMaxZoom ) ; } else { - float minUserZoom = Program.appConfig.getFloatVal( new string[]{"MinUserZoom"}, 0.5f ) ; - mUserZoom = Math.Max( mUserZoom-0.1, minUserZoom ) ; + newZoom = Math.Max( mCurrZoom-0.05, mMinZoom ) ; + } + if ( Math.Abs( newZoom - mCurrZoom) > 0.001 ) { + ILog logger = LogManager.GetLogger( "zoom" ) ; + logger.Info( $"Setting image zoom: {newZoom:0.00}" ) ; + mCurrZoom = newZoom ; + doMainFormResize( pos ) ; } - doMainFormResize( pos ) ; } else { // scroll the ChartImage up/down VScrollProperties vscroll = mChartImagePanel.VerticalScroll ; @@ -338,16 +328,28 @@ public partial class MainForm : Form mStartupWebBrowser = null ; } - // show the selected chart image + // figure out the initial zoom Debug.Assert( mSearchResults.SelectedItems.Count == 1 ) ; - ChartImage chartImage ; + double userZoom = Program.dataConfig.getDoubleVal( new string[]{"_DefaultZoom"}, 1.0 ) ; + double minZoom = Program.dataConfig.getDoubleVal( new string[]{"_MinZoom"}, 0.2*userZoom ) ; + double maxZoom = Program.dataConfig.getDoubleVal( new string[]{"_MaxZoom"}, 2*userZoom ) ; if ( mSearchResults.SelectedItems.Count > 0 ) { - chartImage = (ChartImage) mSearchResults.SelectedItems[0].Tag ; + ChartImage chartImage = (ChartImage) mSearchResults.SelectedItems[0].Tag ; mChartImagePictureBox.Image = chartImage.image ; - } else + userZoom = chartImage.jsonConfig.getDoubleVal( new string[]{"defaultZoom"}, userZoom ) ; + minZoom = chartImage.jsonConfig.getDoubleVal( new string[]{"minZoom"}, minZoom ) ; + maxZoom = chartImage.jsonConfig.getDoubleVal( new string[]{"maxZoom"}, maxZoom ) ; + } else { mChartImagePictureBox.Image = null ; + } + ILog logger = LogManager.GetLogger( "zoom" ) ; + logger.Info( $"Setting initial image zoom: {userZoom:0.00} (min={minZoom:0.00}, max={maxZoom:0.00})" ) ; + mCurrZoom = userZoom ; + mMinZoom = minZoom ; + mMaxZoom = maxZoom ; + + // show the selected chart image setChartImagePanelScrollPos( 0, 0 ) ; - mUserZoom = 1.0 ; doMainFormResize( null ) ; }