// // Copyright (c) PlaceholderCompany. All rights reserved. // namespace SystemTrayMenu.DataClasses { using System; using System.Drawing; using System.IO; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using SystemTrayMenu.Utilities; using static SystemTrayMenu.Utilities.IconReader; using Menu = SystemTrayMenu.UserInterface.Menu; internal class RowData { private static DateTime contextMenuClosed; /// /// Initializes a new instance of the class. /// (Related replace "\x00" see #171.) /// /// Flag if file or folder. /// Flag if additional item, from other folder than root folder. /// The number of the menu level. /// Path to item. internal RowData(bool isFolder, bool isAdditionalItem, int level, string path) { IsFolder = isFolder; IsAdditionalItem = isAdditionalItem; Level = level; try { FileInfo = new FileInfo(path.Replace("\x00", string.Empty)); Path = IsFolder ? $@"{FileInfo.FullName}\" : FileInfo.FullName; FileExtension = System.IO.Path.GetExtension(Path); IsLink = FileExtension.Equals(".lnk", StringComparison.InvariantCultureIgnoreCase); if (IsLink) { ResolvedPath = FileLnk.GetResolvedFileName(Path, out bool isLinkToFolder); IsLinkToFolder = isLinkToFolder || FileLnk.IsNetworkRoot(ResolvedPath); ShowOverlay = Properties.Settings.Default.ShowLinkOverlay; Text = System.IO.Path.GetFileNameWithoutExtension(Path); if (string.IsNullOrEmpty(ResolvedPath)) { Log.Info($"Resolved path is empty: '{Path}'"); ResolvedPath = Path; } } else { ResolvedPath = Path; if (string.IsNullOrEmpty(FileInfo.Name)) { int nameBegin = FileInfo.FullName.LastIndexOf(@"\", StringComparison.InvariantCulture) + 1; Text = FileInfo.FullName[nameBegin..]; } else if (FileExtension.Equals(".url", StringComparison.InvariantCultureIgnoreCase) || FileExtension.Equals(".appref-ms", StringComparison.InvariantCultureIgnoreCase)) { ShowOverlay = Properties.Settings.Default.ShowLinkOverlay; Text = System.IO.Path.GetFileNameWithoutExtension(FileInfo.Name); } else if (!IsFolder && Config.IsHideFileExtension()) { Text = System.IO.Path.GetFileNameWithoutExtension(FileInfo.Name); } else { Text = FileInfo.Name; } } ContainsMenu = IsFolder; if (Properties.Settings.Default.ResolveLinksToFolders) { ContainsMenu |= IsLinkToFolder; } } catch (Exception ex) { Log.Warn($"path:'{path}'", ex); } } internal Icon? Icon { get; private set; } internal FileInfo? FileInfo { get; } internal string? Path { get; } internal bool IsFolder { get; } internal bool IsAdditionalItem { get; } internal int Level { get; set; } internal string? FileExtension { get; } internal bool IsLink { get; } internal string? ResolvedPath { get; } internal bool IsLinkToFolder { get; } internal bool ShowOverlay { get; } internal string? Text { get; } internal bool ContainsMenu { get; } internal Menu? SubMenu { get; set; } internal bool IsMenuOpen { get; set; } internal bool IsClicking { get; set; } internal bool IsSelected { get; set; } internal bool IsContextMenuOpen { get; set; } internal bool HiddenEntry { get; set; } internal int RowIndex { get; set; } internal bool IconLoading { get; set; } internal void ReadIcon(bool updateIconInBackground) { if (IsFolder || IsLinkToFolder) { Icon = GetFolderIconWithCache(Path, ShowOverlay, updateIconInBackground, Level == 0, out bool loading); IconLoading = loading; } else { Icon = GetFileIconWithCache(Path, ResolvedPath, ShowOverlay, updateIconInBackground, Level == 0, out bool loading); IconLoading = loading; } if (!IconLoading) { if (Icon == null) { Icon = Properties.Resources.NotFound; } else if (HiddenEntry) { Icon = AddIconOverlay(Icon, Properties.Resources.White50Percentage); } } } internal void MouseDown(ListView dgv, MouseButtonEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed) { IsClicking = true; } else if (e.RightButton == MouseButtonState.Pressed && FileInfo != null && Path != null && dgv != null && dgv.Items.Count > RowIndex && (DateTime.Now - contextMenuClosed).TotalMilliseconds > 200) { IsContextMenuOpen = true; CreateAndShowShellContextMenu(); void CreateAndShowShellContextMenu() { 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); } } TriggerFileWatcherChangeWorkaround(); 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); } } IsContextMenuOpen = false; contextMenuClosed = DateTime.Now; } } internal void OpenItem(out bool doCloseAfterOpen, int clickCount = -1) { IsClicking = false; doCloseAfterOpen = false; if (clickCount == -1 || (clickCount == 1 && Properties.Settings.Default.OpenItemWithOneClick) || (clickCount == 2 && !Properties.Settings.Default.OpenItemWithOneClick)) { if (!ContainsMenu && Path != null && ResolvedPath != null) { string? workingDirectory = System.IO.Path.GetDirectoryName(ResolvedPath); Log.ProcessStart(Path, string.Empty, false, workingDirectory, true, ResolvedPath); if (!Properties.Settings.Default.StaysOpenWhenItemClicked) { doCloseAfterOpen = true; } } } if (clickCount == -1 || (clickCount == 1 && Properties.Settings.Default.OpenDirectoryWithOneClick) || (clickCount == 2 && !Properties.Settings.Default.OpenDirectoryWithOneClick)) { if (Path != null && ContainsMenu) { Log.ProcessStart(Path); if (!Properties.Settings.Default.StaysOpenWhenItemClicked) { doCloseAfterOpen = true; } } } } } }