Allow individual ChartImage's to specify their default/min/max zoom.

master
Pacman Ghost 5 years ago
parent f20a026292
commit 2bbb9e13b9
  1. 5
      data/config.json
  2. 54
      src/ChartImage.cs
  3. 10
      src/JsonConfig.cs
  4. 13
      src/MainForm.cs
  5. 62
      src/MainForm.ui.cs

@ -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"
},

@ -17,7 +17,7 @@ public class ChartImage
private static Dictionary< Tuple<Keys,Keys>, List<ChartImage> > mShortcuts = new Dictionary< Tuple<Keys,Keys>, List<ChartImage> >() ;
private string mFullPath ;
private dynamic mConfig ;
private JsonConfig mJsonConfig ;
private HashSet<string> mKeywords = new HashSet<string>() ;
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<Keys,Keys> 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<string,float> > scores = new List<Tuple<string,float>>() ;
List< Tuple<string,double> > scores = new List<Tuple<string,double>>() ;
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<string,float>( "exactKeywordMatch", exactKeywordMatchScore ) ) ;
scores.Add( new Tuple<string,double>( "exactKeywordMatch", exactKeywordMatchScore ) ) ;
continue ;
}
int pos = kywd.IndexOf( searchQuery ) ;
if ( pos == 0 ) {
scores.Add( new Tuple<string,float>(
scores.Add( new Tuple<string,double>(
$"leadingPartialKeywordMatch[{kywd}]",
Math.Min( leadingPartialKeywordMatchScore * searchQuery.Length, exactKeywordMatchScore )
) ) ;
} else if ( pos > 0 ) {
scores.Add( new Tuple<string,float>(
scores.Add( new Tuple<string,double>(
$"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<string,float>( "exactCaptionMatch", exactCaptionMatchScore ) ) ;
scores.Add( new Tuple<string,double>( "exactCaptionMatch", exactCaptionMatchScore ) ) ;
else {
int pos = caption.IndexOf( searchQuery ) ;
if ( pos == 0 ) {
scores.Add( new Tuple<string,float>(
scores.Add( new Tuple<string,double>(
$"leadingPartialCaptionMatch[{caption}]",
Math.Min( leadingPartialCaptionMatchScore * searchQuery.Length, exactCaptionMatchScore )
) ) ;
} else if ( pos > 0 ) {
scores.Add( new Tuple<string,float>(
scores.Add( new Tuple<string,double>(
$"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 ; } }
}

@ -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 ;
}

@ -29,7 +29,7 @@ public partial class MainForm : Form
private string mSearchResultsKey = null ;
private Point? mMouseDragAnchor = null ;
private Tuple<int,int> 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<ChartImage,float> > results = new List<Tuple<ChartImage,float>>() ;
List< Tuple<ChartImage,double> > results = new List<Tuple<ChartImage,double>>() ;
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,float>( chartImage, score ) ) ;
results.Add( new Tuple<ChartImage,double>( chartImage, score ) ) ;
}
// sort the search results

@ -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 ) ;
}

Loading…
Cancel
Save