diff --git a/Business/Menus.cs b/Business/Menus.cs index 54d8983..adf44f7 100644 --- a/Business/Menus.cs +++ b/Business/Menus.cs @@ -209,7 +209,6 @@ namespace SystemTrayMenu.Business timerShowProcessStartedAsLoadingIcon.Stop(); timerStillActiveCheck.Stop(); waitLeave.Stop(); - IconReader.Dispose(); MainMenu?.Close(); foreach (FileSystemWatcher watcher in watchers) @@ -634,10 +633,7 @@ namespace SystemTrayMenu.Business if (!AsEnumerable.Any(m => m.Visibility == Visibility.Visible)) { - if (IconReader.ClearIfCacheTooBig()) - { - GC.Collect(); - } + IconReader.ClearCacheWhenLimitReached(); openCloseState = OpenCloseState.Default; } @@ -1088,7 +1084,7 @@ namespace SystemTrayMenu.Business } } - RowData rowDataRenamed = new(isFolder, rowData.IsAdditionalItem, false, 0, path); + RowData rowDataRenamed = new(isFolder, rowData.IsAdditionalItem, 0, path); FolderOptions.ReadHiddenAttributes(rowDataRenamed.Path, out bool hasHiddenFlag, out bool isDirectoryToHide); if (isDirectoryToHide) { @@ -1160,7 +1156,7 @@ namespace SystemTrayMenu.Business FileAttributes attr = File.GetAttributes(e.FullPath); bool isFolder = (attr & FileAttributes.Directory) == FileAttributes.Directory; bool isAddionalItem = Path.GetDirectoryName(e.FullPath) != Config.Path; - RowData rowData = new(isFolder, isAddionalItem, false, 0, e.FullPath); + RowData rowData = new(isFolder, isAddionalItem, 0, e.FullPath); FolderOptions.ReadHiddenAttributes(rowData.Path, out bool hasHiddenFlag, out bool isDirectoryToHide); if (isDirectoryToHide) { diff --git a/DataClasses/RowData.cs b/DataClasses/RowData.cs index 9eb1f6c..91c178b 100644 --- a/DataClasses/RowData.cs +++ b/DataClasses/RowData.cs @@ -24,14 +24,12 @@ namespace SystemTrayMenu.DataClasses /// /// Flag if file or folder. /// Flag if additional item, from other folder than root folder. - /// Flag if resolved from network root folder. /// The number of the menu level. /// Path to item. - internal RowData(bool isFolder, bool isAdditionalItem, bool isNetworkRoot, int level, string path) + internal RowData(bool isFolder, bool isAdditionalItem, int level, string path) { IsFolder = isFolder; IsAdditionalItem = isAdditionalItem; - IsNetworkRoot = isNetworkRoot; Level = level; try @@ -81,8 +79,6 @@ namespace SystemTrayMenu.DataClasses { ContainsMenu |= IsLinkToFolder; } - - IsMainMenu = Level == 0; } catch (Exception ex) { @@ -100,8 +96,6 @@ namespace SystemTrayMenu.DataClasses internal bool IsAdditionalItem { get; } - internal bool IsNetworkRoot { get; } - internal int Level { get; set; } internal string? FileExtension { get; } @@ -118,8 +112,6 @@ namespace SystemTrayMenu.DataClasses internal bool ContainsMenu { get; } - internal bool IsMainMenu { get; } - internal Menu? SubMenu { get; set; } internal bool IsMenuOpen { get; set; } @@ -140,12 +132,12 @@ namespace SystemTrayMenu.DataClasses { if (IsFolder || IsLinkToFolder) { - Icon = GetFolderIconWithCache(Path, ShowOverlay, updateIconInBackground, IsMainMenu, out bool loading); + Icon = GetFolderIconWithCache(Path, ShowOverlay, updateIconInBackground, Level == 0, out bool loading); IconLoading = loading; } else { - Icon = GetFileIconWithCache(Path, ResolvedPath, ShowOverlay, updateIconInBackground, IsMainMenu, out bool loading); + Icon = GetFileIconWithCache(Path, ResolvedPath, ShowOverlay, updateIconInBackground, Level == 0, out bool loading); IconLoading = loading; } @@ -168,53 +160,52 @@ namespace SystemTrayMenu.DataClasses { IsClicking = true; } - - if (e != null && - e.RightButton == MouseButtonState.Pressed && - FileInfo != null && - Path != null && - dgv != null && - dgv.Items.Count > RowIndex && + else if (e.RightButton == MouseButtonState.Pressed && + FileInfo != null && Path != null && + dgv != null && dgv.Items.Count > RowIndex && (DateTime.Now - contextMenuClosed).TotalMilliseconds > 200) { IsContextMenuOpen = true; - ShellContextMenu ctxMnu = new(); - Window window = dgv.GetParentWindow(); - var position = Mouse.GetPosition(window); - position.Offset(window.Left, window.Top); - if (ContainsMenu) + CreateAndShowShellContextMenu(); + void CreateAndShowShellContextMenu() { - DirectoryInfo[] dir = new DirectoryInfo[1]; - dir[0] = new DirectoryInfo(Path); - ctxMnu.ShowContextMenu(dir, position); - TriggerFileWatcherChangeWorkaround(); + ShellContextMenu ctxMnu = new(); + Window window = dgv.GetParentWindow(); + var position = Mouse.GetPosition(window); + position.Offset(window.Left, window.Top); + if (ContainsMenu) + { + DirectoryInfo[] dir = new DirectoryInfo[1]; + dir[0] = new DirectoryInfo(Path); + ctxMnu.ShowContextMenu(dir, position); + } + else + { + FileInfo[] arrFI = new FileInfo[1]; + arrFI[0] = FileInfo; + ctxMnu.ShowContextMenu(arrFI, position); + } } - else + + TriggerFileWatcherChangeWorkaround(); + void TriggerFileWatcherChangeWorkaround() { - FileInfo[] arrFI = new FileInfo[1]; - arrFI[0] = FileInfo; - ctxMnu.ShowContextMenu(arrFI, position); - TriggerFileWatcherChangeWorkaround(); + try + { + string? parentFolder = System.IO.Path.GetDirectoryName(Path); + + // Assume folder is not null as failure will be catched any ways + Directory.GetFiles(parentFolder!); + } + catch (Exception ex) + { + Log.Warn($"{nameof(TriggerFileWatcherChangeWorkaround)} '{Path}'", ex); + } } IsContextMenuOpen = false; contextMenuClosed = DateTime.Now; } - - void TriggerFileWatcherChangeWorkaround() - { - try - { - string? parentFolder = System.IO.Path.GetDirectoryName(Path); - - // Assume folder is not null as failure will be catched any ways - Directory.GetFiles(parentFolder!); - } - catch (Exception ex) - { - Log.Warn($"{nameof(TriggerFileWatcherChangeWorkaround)} '{Path}'", ex); - } - } } internal void OpenItem(out bool doCloseAfterOpen, int clickCount = -1) diff --git a/Helpers/DirectoryHelpers.cs b/Helpers/DirectoryHelpers.cs index ebc5a38..96a6530 100644 --- a/Helpers/DirectoryHelpers.cs +++ b/Helpers/DirectoryHelpers.cs @@ -173,7 +173,7 @@ namespace SystemTrayMenu.Helpers if (indexOfFirstSpace > 0) { string directory = Path.Combine(path, line[..indexOfFirstSpace]); - menuData.RowDatas.Add(new RowData(true, false, true, menuData.Level, directory)); + menuData.RowDatas.Add(new RowData(true, false, menuData.Level, directory)); resolvedSomething = true; } } @@ -201,7 +201,7 @@ namespace SystemTrayMenu.Helpers return; } - menuData.RowDatas.Add(new RowData(true, false, false, menuData.Level, directory)); + menuData.RowDatas.Add(new RowData(true, false, menuData.Level, directory)); } foreach (string file in DirectoryBySearchPattern.GetFiles(path, Config.SearchPattern)) @@ -211,7 +211,7 @@ namespace SystemTrayMenu.Helpers return; } - menuData.RowDatas.Add(new RowData(false, false, false, menuData.Level, file)); + menuData.RowDatas.Add(new RowData(false, false, menuData.Level, file)); } } @@ -225,14 +225,14 @@ namespace SystemTrayMenu.Helpers { foreach (string file in DirectoryBySearchPattern.GetFiles(path, Config.SearchPattern)) { - menuData.RowDatas.Add(new RowData(false, true, false, menuData.Level, file)); + menuData.RowDatas.Add(new RowData(false, true, menuData.Level, file)); } foreach (string directory in Directory.GetDirectories(path)) { if (!onlyFiles) { - menuData.RowDatas.Add(new RowData(true, true, false, menuData.Level, directory)); + menuData.RowDatas.Add(new RowData(true, true, menuData.Level, directory)); } if (recursiv) diff --git a/UserInterface/ShellContextMenu/ShellContextMenu.cs b/UserInterface/ShellContextMenu/ShellContextMenu.cs index da08373..8b78a59 100644 --- a/UserInterface/ShellContextMenu/ShellContextMenu.cs +++ b/UserInterface/ShellContextMenu/ShellContextMenu.cs @@ -5,6 +5,7 @@ namespace SystemTrayMenu.Utilities { using System; + using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.InteropServices; using System.Text; @@ -735,7 +736,7 @@ namespace SystemTrayMenu.Utilities try { - if (arrPIDLs == null || oParentFolder == null || oContextMenu == null) + if (arrPIDLs == null || oParentFolder == null) { ReleaseAll(); return; @@ -972,6 +973,7 @@ namespace SystemTrayMenu.Utilities /// Parent folder. /// PIDLs. /// true if it got the interfaces, otherwise false. + [MemberNotNullWhen(true, nameof(oContextMenu))] private bool GetContextMenuInterfaces(IShellFolder oParentFolder, IntPtr[] arrPIDLs, out IntPtr ctxMenuPtr) { int nResult = oParentFolder.GetUIObjectOf( diff --git a/Utilities/File/IconReader.cs b/Utilities/File/IconReader.cs index fa574be..973fcf9 100644 --- a/Utilities/File/IconReader.cs +++ b/Utilities/File/IconReader.cs @@ -20,8 +20,8 @@ namespace SystemTrayMenu.Utilities /// public static class IconReader { - private static readonly ConcurrentDictionary DictIconCacheMainMenu = new(); - private static readonly ConcurrentDictionary DictIconCacheSubMenus = new(); + private static readonly ConcurrentDictionary IconDictPersistent = new(); + private static readonly ConcurrentDictionary IconDictCache = new(); public enum IconSize { @@ -29,47 +29,26 @@ namespace SystemTrayMenu.Utilities Small = 1, // 16x16 pixels } - public enum FolderType - { - Open = 0, - Closed = 1, - } - // see https://github.com/Hofknecht/SystemTrayMenu/issues/209. public static bool IsPreloading { get; set; } = true; - public static void Dispose(bool includingMainMenu = true) + public static void ClearCacheWhenLimitReached() { - if (includingMainMenu) + if (IconDictCache.Count > Properties.Settings.Default.ClearCacheIfMoreThanThisNumberOfItems) { - foreach (Icon? icon in DictIconCacheMainMenu.Values) + foreach (Icon? icon in IconDictCache.Values) { icon?.Dispose(); } - } - foreach (Icon? icon in DictIconCacheSubMenus.Values) - { - icon?.Dispose(); + IconDictCache.Clear(); + GC.Collect(); } } - public static bool ClearIfCacheTooBig() - { - bool cleared = false; - if (DictIconCacheSubMenus.Count > Properties.Settings.Default.ClearCacheIfMoreThanThisNumberOfItems) - { - Dispose(false); - DictIconCacheSubMenus.Clear(); - cleared = true; - } - - return cleared; - } - public static void RemoveIconFromCache(string path) { - if (DictIconCacheMainMenu.Remove(path, out Icon? iconToRemove)) + if (IconDictPersistent.Remove(path, out Icon? iconToRemove)) { iconToRemove?.Dispose(); } @@ -80,7 +59,7 @@ namespace SystemTrayMenu.Utilities string? resolvedPath, bool linkOverlay, bool updateIconInBackground, - bool isMainMenu, + bool checkPersistentFirst, out bool loading, string keyPath = "") { @@ -109,8 +88,8 @@ namespace SystemTrayMenu.Utilities key = extension + linkOverlay; } - if (!DictIconCache(isMainMenu).TryGetValue(key, out icon) && - !DictIconCache(!isMainMenu).TryGetValue(key, out icon)) + if (!DictIconCache(checkPersistentFirst).TryGetValue(key, out icon) && + !DictIconCache(!checkPersistentFirst).TryGetValue(key, out icon)) { icon = Resources.StaticResources.LoadingIcon; loading = true; @@ -119,7 +98,7 @@ namespace SystemTrayMenu.Utilities new Thread(UpdateIconInBackground).Start(); void UpdateIconInBackground() { - DictIconCache(isMainMenu).GetOrAdd(key, GetIconSTA(path, resolvedPath, linkOverlay, size, false)); + DictIconCache(checkPersistentFirst).GetOrAdd(key, GetIconSTA(path, resolvedPath, linkOverlay, size, false)); } } } @@ -132,7 +111,7 @@ namespace SystemTrayMenu.Utilities string? path, bool linkOverlay, bool updateIconInBackground, - bool isMainMenu, + bool checkPersistentFirst, out bool loading) { loading = false; @@ -150,8 +129,8 @@ namespace SystemTrayMenu.Utilities } string key = path; - if (!DictIconCache(isMainMenu).TryGetValue(key, out icon) && - !DictIconCache(!isMainMenu).TryGetValue(key, out icon)) + if (!DictIconCache(checkPersistentFirst).TryGetValue(key, out icon) && + !DictIconCache(!checkPersistentFirst).TryGetValue(key, out icon)) { icon = Resources.StaticResources.LoadingIcon; loading = true; @@ -160,14 +139,14 @@ namespace SystemTrayMenu.Utilities { if (IsPreloading) { - DictIconCache(isMainMenu).GetOrAdd(key, GetFolder); + DictIconCache(checkPersistentFirst).GetOrAdd(key, GetFolder); } else { new Thread(UpdateIconInBackground).Start(); void UpdateIconInBackground() { - DictIconCache(isMainMenu).GetOrAdd(key, GetFolder); + DictIconCache(checkPersistentFirst).GetOrAdd(key, GetFolder); } } @@ -223,17 +202,8 @@ namespace SystemTrayMenu.Utilities return icon; } - private static ConcurrentDictionary DictIconCache(bool isMainMenu) - { - if (isMainMenu) - { - return DictIconCacheMainMenu; - } - else - { - return DictIconCacheSubMenus; - } - } + private static ConcurrentDictionary DictIconCache(bool checkPersistentFirst) + => checkPersistentFirst ? IconDictPersistent : IconDictCache; private static bool IsExtensionWithSameIcon(string fileExtension) {