[Feature] Option to cache main menu (#232), version 1.0.25.9

This commit is contained in:
Markus Hofknecht 2021-11-13 13:55:01 +01:00
parent fd554ec7ea
commit 7f65ef0e7f
6 changed files with 74 additions and 47 deletions

View file

@ -92,7 +92,15 @@ namespace SystemTrayMenu.Business
{
DisposeMenu(menus[menuData.Level]);
menus[0] = Create(menuData, Path.GetFileName(Config.Path));
AsEnumerable.ToList().ForEach(m => { m.ShowWithFade(); });
if (IconReader.MainPreload)
{
IconReader.MainPreload = false;
}
else
{
AsEnumerable.ToList().ForEach(m => { m.ShowWithFade(); });
}
}
break;
@ -608,7 +616,7 @@ namespace SystemTrayMenu.Business
if (FileUrl.GetDefaultBrowserPath(out string browserPath))
{
IconReader.GetFileIconWithCache(browserPath, true, true, out _);
IconReader.GetFileIconWithCache(browserPath, true, true, true, out _);
}
timerShowProcessStartedAsLoadingIcon.Tick += Tick;
@ -820,7 +828,6 @@ namespace SystemTrayMenu.Business
else if (!Properties.Settings.Default.StaysOpenWhenFocusLostAfterEnterPressed ||
!waitingForReactivate)
{
Log.Info($"Deactivate {openCloseState}");
FadeHalfOrOutIfNeeded();
if (!IsActive())
{

View file

@ -96,7 +96,7 @@ namespace SystemTrayMenu.DataClasses
}
else if (isDirectory)
{
icon = IconReader.GetFolderIconWithCache(TargetFilePathOrig, IconReader.FolderType.Closed, false, true, out bool loading);
icon = IconReader.GetFolderIconWithCache(TargetFilePathOrig, IconReader.FolderType.Closed, false, true, MenuLevel == 0, out bool loading);
IconLoading = loading;
}
else
@ -131,7 +131,7 @@ namespace SystemTrayMenu.DataClasses
try
{
FilePathIcon = TargetFilePathOrig;
icon = IconReader.GetFileIconWithCache(FilePathIcon, showOverlay, true, out bool loading);
icon = IconReader.GetFileIconWithCache(FilePathIcon, showOverlay, true, MenuLevel == 0, out bool loading);
IconLoading = loading;
}
catch (Exception ex)
@ -212,7 +212,7 @@ namespace SystemTrayMenu.DataClasses
{
if (ContainsMenu)
{
icon = IconReader.GetFolderIconWithCache(TargetFilePathOrig, IconReader.FolderType.Closed, false, false, out bool loading);
icon = IconReader.GetFolderIconWithCache(TargetFilePathOrig, IconReader.FolderType.Closed, false, false, MenuLevel == 0, out bool loading);
IconLoading = loading;
}
else
@ -230,7 +230,7 @@ namespace SystemTrayMenu.DataClasses
filePath = TargetFilePathOrig;
}
icon = IconReader.GetFileIconWithCache(filePath, showOverlay, false, out bool loading);
icon = IconReader.GetFileIconWithCache(filePath, showOverlay, false, MenuLevel == 0, out bool loading);
IconLoading = loading;
}
@ -267,7 +267,7 @@ namespace SystemTrayMenu.DataClasses
}
else if (string.IsNullOrEmpty(Path.GetExtension(resolvedLnkPath)))
{
icon = IconReader.GetFolderIconWithCache(TargetFilePathOrig, IconReader.FolderType.Open, true, true, out bool loading);
icon = IconReader.GetFolderIconWithCache(TargetFilePathOrig, IconReader.FolderType.Open, true, true, MenuLevel == 0, out bool loading);
IconLoading = loading;
handled = true;
isLnkDirectory = true;
@ -303,7 +303,7 @@ namespace SystemTrayMenu.DataClasses
if (FileUrl.GetDefaultBrowserPath(out string browserPath))
{
FilePathIcon = browserPath;
icon = IconReader.GetFileIconWithCache(FilePathIcon, true, true, out bool loading);
icon = IconReader.GetFileIconWithCache(FilePathIcon, true, true, MenuLevel == 0, out bool loading);
IconLoading = loading;
handled = true;
}
@ -311,7 +311,7 @@ namespace SystemTrayMenu.DataClasses
else if (File.Exists(iconFile))
{
FilePathIcon = iconFile;
icon = IconReader.GetFileIconWithCache(FilePathIcon, true, true, out bool loading);
icon = IconReader.GetFileIconWithCache(FilePathIcon, true, true, MenuLevel == 0, out bool loading);
IconLoading = loading;
handled = true;
}
@ -335,7 +335,7 @@ namespace SystemTrayMenu.DataClasses
bool handled = false;
try
{
icon = IconReader.GetExtractAllIconsLastWithCache(TargetFilePathOrig, true, out bool loading);
icon = IconReader.GetExtractAllIconsLastWithCache(TargetFilePathOrig, true, MenuLevel == 0, out bool loading);
IconLoading = loading;
handled = true;
}

View file

@ -39,5 +39,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.25.8")]
[assembly: AssemblyFileVersion("1.0.25.8")]
[assembly: AssemblyVersion("1.0.25.9")]
[assembly: AssemblyFileVersion("1.0.25.9")]

View file

@ -44,7 +44,7 @@ namespace SystemTrayMenu.UserInterface
labelTitle.Name = "labelTitle";
labelTitle.Padding = new Padding(3, 0, 0, 1);
labelTitle.Size = new Size(70, 14);
labelTitle.Text = "STM";
labelTitle.Text = "SystemTrayMenu";
labelTitle.TextAlign = ContentAlignment.MiddleCenter;
labelTitle.MouseWheel += new MouseEventHandler(DgvMouseWheel);

View file

@ -44,7 +44,7 @@
this.MaximizeBox = false;
this.Name = "TaskbarForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.Text = "STM";
this.Text = "SystemTrayMenu";
this.LocationChanged += new System.EventHandler(this.TaskbarForm_LocationChanged);
this.ResumeLayout(false);

View file

@ -22,7 +22,8 @@ namespace SystemTrayMenu.Utilities
/// </summary>
public static class IconReader
{
private static readonly ConcurrentDictionary<string, Icon> DictIconCache = new ConcurrentDictionary<string, Icon>();
private static readonly ConcurrentDictionary<string, Icon> DictIconCacheMainMenu = new ConcurrentDictionary<string, Icon>();
private static readonly ConcurrentDictionary<string, Icon> DictIconCacheSubMenus = new ConcurrentDictionary<string, Icon>();
public enum IconSize
{
@ -39,9 +40,18 @@ namespace SystemTrayMenu.Utilities
// see https://github.com/Hofknecht/SystemTrayMenu/issues/209.
public static bool MainPreload { get; set; }
public static void Dispose()
public static void Dispose(bool includingMainMenu = true)
{
foreach (Icon icon in DictIconCache.Values)
if (includingMainMenu)
{
foreach (Icon icon in DictIconCacheMainMenu.Values)
{
icon?.Dispose();
}
}
foreach (Icon icon in DictIconCacheSubMenus.Values)
{
icon?.Dispose();
}
@ -50,17 +60,21 @@ namespace SystemTrayMenu.Utilities
public static bool ClearIfCacheTooBig()
{
bool cleared = false;
if (DictIconCache.Count > Properties.Settings.Default.ClearCacheIfMoreThanThisNumberOfItems)
if (DictIconCacheSubMenus.Count > Properties.Settings.Default.ClearCacheIfMoreThanThisNumberOfItems)
{
Dispose();
DictIconCache.Clear();
Dispose(false);
DictIconCacheSubMenus.Clear();
cleared = true;
}
return cleared;
}
public static Icon GetExtractAllIconsLastWithCache(string filePath, bool updateIconInBackground, out bool loading)
public static Icon GetExtractAllIconsLastWithCache(
string filePath,
bool updateIconInBackground,
bool isMainMenu,
out bool loading)
{
bool linkOverlay = false;
loading = false;
@ -73,9 +87,8 @@ namespace SystemTrayMenu.Utilities
key = extension + linkOverlay;
}
ClearBadIcons();
if (!DictIconCache.TryGetValue(key, out Icon icon))
if (!DictIconCache(isMainMenu).TryGetValue(key, out Icon icon) &&
!DictIconCache(!isMainMenu).TryGetValue(key, out icon))
{
icon = Resources.StaticResources.LoadingIcon;
loading = true;
@ -85,7 +98,7 @@ namespace SystemTrayMenu.Utilities
new Thread(UpdateIconInBackground).Start();
void UpdateIconInBackground()
{
DictIconCache.GetOrAdd(key, GetExtractAllIconsLast);
DictIconCache(isMainMenu).GetOrAdd(key, GetExtractAllIconsLast);
}
}
}
@ -134,7 +147,13 @@ namespace SystemTrayMenu.Utilities
return icon;
}
public static Icon GetFileIconWithCache(string filePath, bool linkOverlay, bool updateIconInBackground, out bool loading, string keyPath = "")
public static Icon GetFileIconWithCache(
string filePath,
bool linkOverlay,
bool updateIconInBackground,
bool isMainMenu,
out bool loading,
string keyPath = "")
{
loading = false;
string extension = Path.GetExtension(filePath);
@ -155,9 +174,8 @@ namespace SystemTrayMenu.Utilities
key = extension + linkOverlay;
}
ClearBadIcons();
if (!DictIconCache.TryGetValue(key, out Icon icon))
if (!DictIconCache(isMainMenu).TryGetValue(key, out Icon icon) &&
!DictIconCache(!isMainMenu).TryGetValue(key, out icon))
{
icon = Resources.StaticResources.LoadingIcon;
loading = true;
@ -167,7 +185,7 @@ namespace SystemTrayMenu.Utilities
new Thread(UpdateIconInBackground).Start();
void UpdateIconInBackground()
{
DictIconCache.GetOrAdd(key, GetIcon);
DictIconCache(isMainMenu).GetOrAdd(key, GetIcon);
}
}
}
@ -204,7 +222,13 @@ namespace SystemTrayMenu.Utilities
return icon;
}
public static Icon GetFolderIconWithCache(string path, FolderType folderType, bool linkOverlay, bool updateIconInBackground, out bool loading)
public static Icon GetFolderIconWithCache(
string path,
FolderType folderType,
bool linkOverlay,
bool updateIconInBackground,
bool isMainMenu,
out bool loading)
{
loading = false;
@ -213,9 +237,8 @@ namespace SystemTrayMenu.Utilities
string key = path;
ClearBadIcons();
if (!DictIconCache.TryGetValue(key, out Icon icon))
if (!DictIconCache(isMainMenu).TryGetValue(key, out Icon icon) &&
!DictIconCache(!isMainMenu).TryGetValue(key, out icon))
{
icon = Resources.StaticResources.LoadingIcon;
loading = true;
@ -224,14 +247,14 @@ namespace SystemTrayMenu.Utilities
{
if (MainPreload)
{
DictIconCache.GetOrAdd(key, GetFolder);
DictIconCache(isMainMenu).GetOrAdd(key, GetFolder);
}
else
{
new Thread(UpdateIconInBackground).Start();
void UpdateIconInBackground()
{
DictIconCache.GetOrAdd(key, GetFolder);
DictIconCache(isMainMenu).GetOrAdd(key, GetFolder);
}
}
}
@ -356,18 +379,15 @@ namespace SystemTrayMenu.Utilities
return icon;
}
/// <summary>
/// Clear icons which are null.
/// see https://github.com/Hofknecht/SystemTrayMenu/issues/209.
/// This only happens with the MainPreload method. SingleThread had only partially solved it before.
/// It is unclear exactly where the problem comes from, because it never seems to be null later.
/// </summary>
private static void ClearBadIcons()
private static ConcurrentDictionary<string, Icon> DictIconCache(bool isMainMenu)
{
IEnumerable<string> badKeysList = DictIconCache.Where(x => x.Value == null).Select(x => x.Key);
foreach (string badKey in badKeysList)
if (isMainMenu)
{
DictIconCache.Remove(badKey, out _);
return DictIconCacheMainMenu;
}
else
{
return DictIconCacheSubMenus;
}
}