From 2d301eb4540b7ceff969cda4bc77a28300840669 Mon Sep 17 00:00:00 2001 From: Markus Hofknecht Date: Sat, 6 Jul 2019 17:11:55 +0200 Subject: [PATCH] [Feature] Adjust about form #24 https://github.com/Hofknecht/SystemTrayMenu/issues/24 --- Controls/AppContextMenu.cs | 15 +- Properties/AssemblyInfo.cs | 6 +- SystemTrayMenuHandler.cs | 2196 ++++++++++++++++++------------------ 3 files changed, 1109 insertions(+), 1108 deletions(-) diff --git a/Controls/AppContextMenu.cs b/Controls/AppContextMenu.cs index 369c74b..566ba4a 100644 --- a/Controls/AppContextMenu.cs +++ b/Controls/AppContextMenu.cs @@ -163,18 +163,19 @@ namespace SystemTrayMenu.Controls ab.AppDescription = versionInfo.FileDescription; ab.AppVersion = $"Version {versionInfo.FileVersion}"; ab.AppCopyright = versionInfo.LegalCopyright; - ab.AppMoreInfo = "SystemTrayMenu - An improved Windows Toolbar"; - ab.AppMoreInfo += Environment.NewLine; - ab.AppMoreInfo += "Code from © 2019, TAMAHO, All Rights Reserved."; - ab.AppMoreInfo += Environment.NewLine; - ab.AppMoreInfo += "Developer:"; + ab.AppMoreInfo = versionInfo.LegalCopyright; ab.AppMoreInfo += Environment.NewLine; ab.AppMoreInfo += "Markus Hofknecht (mailto:Markus@Hofknecht.eu)"; ab.AppMoreInfo += Environment.NewLine; - ab.AppMoreInfo += "Tanja Kauth (Tanja@Hofknecht.eu)"; + ab.AppMoreInfo += "Tanja Kauth (mailto:Tanja@Hofknecht.eu)"; + ab.AppMoreInfo += Environment.NewLine; + ab.AppMoreInfo += "http://www.hofknecht.eu/systemtraymenu/"; + ab.AppMoreInfo += Environment.NewLine; + ab.AppMoreInfo += "https://github.com/Hofknecht/SystemTrayMenu"; ab.AppMoreInfo += Environment.NewLine; ab.AppMoreInfo += Environment.NewLine; - ab.AppMoreInfo += "http://www.hofknecht.eu/systemtraymenu/" + Environment.NewLine; + ab.AppMoreInfo += "GNU GENERAL PUBLIC LICENSE" + Environment.NewLine; + ab.AppMoreInfo += "(Version 3, 29 June 2007)" + Environment.NewLine; ab.AppDetailsButton = true; ab.ShowDialog(); } diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index ad2420e..b776a24 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("TAMAHO")] [assembly: AssemblyProduct("TAMAHO SystemTrayMenu")] -[assembly: AssemblyCopyright("Copyright © 2019, TAMAHO")] +[assembly: AssemblyCopyright("Copyright © 2019, TAMAHO SystemTrayMenu")] [assembly: AssemblyTrademark("TAMAHO")] [assembly: AssemblyCulture("")] @@ -31,5 +31,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("0.9.1.236")] -[assembly: AssemblyFileVersion("0.9.1.236")] +[assembly: AssemblyVersion("0.9.1.237")] +[assembly: AssemblyFileVersion("0.9.1.237")] diff --git a/SystemTrayMenuHandler.cs b/SystemTrayMenuHandler.cs index d889e05..b4909b6 100644 --- a/SystemTrayMenuHandler.cs +++ b/SystemTrayMenuHandler.cs @@ -1,942 +1,942 @@ -using Clearcove.Logging; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Drawing; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Windows.Forms; -using SystemTrayMenu.Controls; -using SystemTrayMenu.Helper; - -namespace SystemTrayMenu -{ - #region Enable debug log by putting this code into each function - //MethodBase m = MethodBase.GetCurrentMethod(); - //log.Debug($"Executing {m.ReflectedType.Name}, {m.Name}"); - #endregion - class SystemTrayMenuHandler : IDisposable - { - Logger log = new Logger(nameof(SystemTrayMenuHandler)); - - KeyboardHook hook = new KeyboardHook(); - Timer timerKeySearch = new Timer(); - int iRowKey = -1; - int iMenuKey = 0; - string keyInput = string.Empty; - - MenuNotifyIcon menuNotifyIcon = new MenuNotifyIcon(); - WaitFastLeave fastLeave = new WaitFastLeave(); - Menu[] menus = new Menu[MenuDefines.MenusMax]; - bool isMainMenuOpen = false; - - BackgroundWorker worker = new BackgroundWorker(); - bool restartLoading = false; - Screen screen = null; - - public SystemTrayMenuHandler(ref bool cancelAppRun) - { - log.Info("Application Start " + - Assembly.GetExecutingAssembly(). - GetName().Version.ToString() + - $" ScalingFactor={Program.ScalingFactor}"); - - if (!string.IsNullOrEmpty(Properties.Settings.Default.HotKey)) - { - var cvt = new KeysConverter(); - var key = (Keys)cvt.ConvertFrom( - Properties.Settings.Default.HotKey); - try - { - hook.RegisterHotKey( - KeyboardHookModifierKeys.Control | - KeyboardHookModifierKeys.Alt, - key); - hook.KeyPressed += hook_KeyPressed; - } - catch (Exception ex) - { - log.Info($"key:'{key.ToString()}'"); - log.Error($"{ex.ToString()}"); - Properties.Settings.Default.HotKey = string.Empty; - Properties.Settings.Default.Save(); - MessageBox.Show(ex.Message); - ApplicationRestart(); - } - } - void hook_KeyPressed(object sender, KeyPressedEventArgs e) - { - SwitchOpenClose(); - } - - timerKeySearch.Interval = MenuDefines.KeySearchInterval; - timerKeySearch.Tick += TimerKeySearch_Tick; - menus[0] = new Menu(); - MessageFilter messageFilter = new MessageFilter(); - Application.AddMessageFilter(messageFilter); - menuNotifyIcon.Exit += Application.Exit; - - menuNotifyIcon.HandleClick += SwitchOpenClose; - void SwitchOpenClose() - { - if (Config.Path == string.Empty) - { - //Case when Folder Dialog open - } - else if (isMainMenuOpen && menus[0].Visible) - { - isMainMenuOpen = false; - MenusFadeOut(); - if (worker.IsBusy) - { - worker.CancelAsync(); - } - } - else if (worker.IsBusy) - { - restartLoading = true; - worker.CancelAsync(); - } - else - { - isMainMenuOpen = true; - if (menus[0].Visible) - { - ActivateMenu(); - } - else - { - screen = ScreenMouse.GetScreen(); - bool IsNotifyIconInTaskbar() - { - bool isNotifyIconInTaskbar = false; - int height = screen.Bounds.Height - - new Taskbar().Size.Height; - if (Cursor.Position.Y >= height) - { - isNotifyIconInTaskbar = true; - } - return isNotifyIconInTaskbar; - } - if (!IsNotifyIconInTaskbar()) - { - //DragDropHintForm hintForm = new DragDropHintForm( - // Program.Translate("HintDragDropTitle"), - // Program.Translate("HintDragDropText"), - // Program.Translate("buttonOk")); - //hintForm.Show(); - } - - menuNotifyIcon.LoadingStart(); - worker.RunWorkerAsync(); - } - } - } - - worker.WorkerSupportsCancellation = true; - worker.DoWork += Worker_DoWork; - void Worker_DoWork(object senderDoWork, - DoWorkEventArgs eDoWork) - { - int level = 0; - BackgroundWorker worker = (BackgroundWorker)senderDoWork; - restartLoading = false; - eDoWork.Result = ReadMenu(worker, Config.Path, level); - } - - worker.RunWorkerCompleted += Worker_RunWorkerCompleted; - void Worker_RunWorkerCompleted(object sender, - RunWorkerCompletedEventArgs e) - { - if (restartLoading) - { - worker.RunWorkerAsync(); - } - else - { - ResetSelectedByKey(); - menuNotifyIcon.LoadingStop(); - MenuData menuData = (MenuData)e.Result; - if (menuData.Validity == MenuDataValidity.Valid) - { - menus[0] = CreateMenu(menuData, Path.GetFileName(Config.Path)); - menus[0].AdjustLocationAndSize(screen); - ActivateMenu(); - menus[0].AdjustLocationAndSize(screen); - } - } - } - - void ActivateMenu() - { - Menus().ToList().ForEach(menu => - { - menu.FadeIn(); - menu.FadeHalf(); - }); - menus[0].SetTitleColorActive(); - menus[0].Activate(); - WindowToTop.ForceForegroundWindow(menus[0].Handle); - } - - menuNotifyIcon.ChangeFolder += ChangeFolder; - void ChangeFolder() - { - if (Config.SetFolderByUser()) - { - ApplicationRestart(); - } - } - - menuNotifyIcon.OpenLog += OpenLog; - void OpenLog() - { - Process.Start(Program.GetLogFilePath()); - } - - menuNotifyIcon.Restart += ApplicationRestart; - void ApplicationRestart() - { - Dispose(); - Process.Start(Assembly.GetExecutingAssembly(). - ManifestModule.FullyQualifiedName); - } - - messageFilter.MouseMove += FadeInIfNeeded; - messageFilter.ScrollBarMouseMove += FadeInIfNeeded; - - messageFilter.MouseLeave += fastLeave.Start; - fastLeave.Leave += FadeHalfOrOutIfNeeded; - - if (!Config.LoadOrSetByUser()) - { - cancelAppRun = true; - } - } - void FadeInIfNeeded() - { - if (menus[0].Visible && - !menus[0].IsFadingIn && - !menus[0].IsFadingOut) - { - if (Menus().Any(m => m.Opacity < 1)) - { - Menus().ToList().ForEach(menu => menu.FadeIn()); - } - } - } - - void FadeHalfOrOutIfNeeded() - { - Point mousePosition = Control.MousePosition; - bool isMouseOnAnyMenu = - !Menus().Any(m => m.IsMouseOn(mousePosition)); - bool isAnyMenuActive = IsAnyMenuActive(); - - if (isMouseOnAnyMenu) - { - if (isAnyMenuActive && isMainMenuOpen) - { - if (!IsAnyMenuSelectedByKey()) - { - Menus().ToList().ForEach(menu => menu.FadeHalf()); - } - } - else - { - MenusFadeOut(); - } - } - } - - private void ResetSelectedByKey() - { - iRowKey = -1; - iMenuKey = 0; - } - - public void Dispose() - { - hook.Dispose(); - menuNotifyIcon.Dispose(); - fastLeave.Dispose(); - DisposeMenu(menus[0]); - } - - void DisposeMenu(Menu menuToDispose) - { - if (menuToDispose != null) - { - DataGridView dgv = menuToDispose.GetDataGridView(); - foreach (DataGridViewRow row in dgv.Rows) - { - RowData rowData = (RowData)row.Tag; - rowData.Dispose(); - DisposeMenu(rowData.SubMenu); - } - dgv.ClearSelection(); - menuToDispose.Dispose(); - menuToDispose = null; - } - } - - void DisposeWhenHidden(object sender, EventArgs e) - { - Menu menuToDispose = (Menu)sender; - if (!menuToDispose.Visible) - { - DisposeMenu(menuToDispose); - } - } - - void AdjustSubMenusLocationAndSize() - { - Screen screen = ScreenMouse.GetScreen(); - int heightMax = screen.Bounds.Height - - new Taskbar().Size.Height; - Menu menuPredecessor = menus[0]; - int widthPredecessors = -1; // -1 padding - bool directionToRight = false; - - foreach (Menu menu in Menus().Skip(1)) - { - // -1*2 padding - int newWith = (menu.Width - 2 + menuPredecessor.Width); - if (directionToRight) - { -#warning is this still correct? - if (widthPredecessors - menu.Width <= -2) // -1*2 padding - { - directionToRight = false; - } - else - { - widthPredecessors -= newWith; - } - } - else if (screen.Bounds.Width < - widthPredecessors + menuPredecessor.Width + menu.Width) - { - directionToRight = true; - widthPredecessors -= newWith; - } - - menu.AdjustLocationAndSize(heightMax, - widthPredecessors, menuPredecessor); - widthPredecessors += menu.Width - 1; // -1 padding - menuPredecessor = menu; - } - } - - void OpenSubMenu(object sender, EventArgs e) - { - RowData trigger = (RowData)sender; - Menu menuTriggered = trigger.SubMenu; - Menu menuFromTrigger = menus[menuTriggered.Level - 1]; - - for (int level = menuTriggered.Level; - level < MenuDefines.MenusMax; level++) - { - if (menus[level] != null) - { - Menu menuToClose = menus[level]; - RowData oldTrigger = (RowData)menuToClose.Tag; - DataGridView dgv = menuFromTrigger.GetDataGridView(); - foreach (DataGridViewRow row in dgv.Rows) - { - RowData rowData = (RowData)row.Tag; - rowData.IsSelected = false; - } - trigger.IsSelected = true; - dgv.ClearSelection(); - dgv.Rows[trigger.RowIndex].Selected = true; - menuToClose.FadeOut(); - menuToClose.VisibleChanged += DisposeWhenHidden; - menus[level] = null; - } - } - - menus[menuTriggered.Level] = menuTriggered; - AdjustSubMenusLocationAndSize(); - menus[menuTriggered.Level].FadeIn(); - AdjustSubMenusLocationAndSize(); - IsAnyMenuActive(); - } - - void Activated(object sender, EventArgs e) - { - Menu triggeredMenu = (Menu)sender; - menus[0].SetTitleColorActive(); - } - - bool IsAnyMenuActive() - { - bool isAnyMenuActive; - Form activeForm = Form.ActiveForm; - //isAnyMenuActive = Menus().Any(m => m.IsActive(activeForm)); - isAnyMenuActive = activeForm is Menu; - if (!isAnyMenuActive) - { - menus[0].SetTitleColorDeactive(); - CheckMenuOpenerStop(iMenuKey, iRowKey); - ClearIsSelectedByKey(iMenuKey, iRowKey); - ResetSelectedByKey(); - } - else - { - menus[0].SetTitleColorActive(); - } - - return isAnyMenuActive; - } - - MenuData ReadMenu(BackgroundWorker worker, string path, int level) - { - MenuData menuData = new MenuData(); - menuData.RowDatas = new List(); - menuData.Validity = MenuDataValidity.Invalid; - menuData.Level = level; - if (!worker.CancellationPending) - { - string[] directories = new string[] { }; - - try - { - directories = Directory.GetDirectories(path); - Array.Sort(directories, new WindowsExplorerSort()); - } - catch (Exception ex) - { - log.Info($"path:'{path}'"); - log.Error($"{ex.ToString()}"); - } - - foreach (string directory in directories) - { - if (worker != null && worker.CancellationPending) - { - break; - } - - RowData menuButtonData = ReadMenuButtonData(directory, false); - menuButtonData.ContainsMenu = true; - string resolvedLnkPath = string.Empty; - menuButtonData.ReadIcon(true, false, ref resolvedLnkPath); - menuData.RowDatas.Add(menuButtonData); - } - } - - if (!worker.CancellationPending) - { - string[] files = new string[] { }; - - try - { - files = Directory.GetFiles(path). - Where(p => Path.GetFileName(p) != "desktop.ini").ToArray(); - Array.Sort(files, new WindowsExplorerSort()); - } - catch (Exception ex) - { - if ((uint)ex.HResult == 0x80070005) // E_ACCESSDENIED - menuData.Validity = MenuDataValidity.NoAccess; +using Clearcove.Logging; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Windows.Forms; +using SystemTrayMenu.Controls; +using SystemTrayMenu.Helper; + +namespace SystemTrayMenu +{ + #region Enable debug log by putting this code into each function + //MethodBase m = MethodBase.GetCurrentMethod(); + //log.Debug($"Executing {m.ReflectedType.Name}, {m.Name}"); + #endregion + class SystemTrayMenuHandler : IDisposable + { + Logger log = new Logger(nameof(SystemTrayMenuHandler)); + + KeyboardHook hook = new KeyboardHook(); + Timer timerKeySearch = new Timer(); + int iRowKey = -1; + int iMenuKey = 0; + string keyInput = string.Empty; + + MenuNotifyIcon menuNotifyIcon = new MenuNotifyIcon(); + WaitFastLeave fastLeave = new WaitFastLeave(); + Menu[] menus = new Menu[MenuDefines.MenusMax]; + bool isMainMenuOpen = false; + + BackgroundWorker worker = new BackgroundWorker(); + bool restartLoading = false; + Screen screen = null; + + public SystemTrayMenuHandler(ref bool cancelAppRun) + { + log.Info("Application Start " + + Assembly.GetExecutingAssembly(). + GetName().Version.ToString() + + $" ScalingFactor={Program.ScalingFactor}"); + + if (!string.IsNullOrEmpty(Properties.Settings.Default.HotKey)) + { + var cvt = new KeysConverter(); + var key = (Keys)cvt.ConvertFrom( + Properties.Settings.Default.HotKey); + try + { + hook.RegisterHotKey( + KeyboardHookModifierKeys.Control | + KeyboardHookModifierKeys.Alt, + key); + hook.KeyPressed += hook_KeyPressed; + } + catch (Exception ex) + { + log.Info($"key:'{key.ToString()}'"); + log.Error($"{ex.ToString()}"); + Properties.Settings.Default.HotKey = string.Empty; + Properties.Settings.Default.Save(); + MessageBox.Show(ex.Message); + ApplicationRestart(); + } + } + void hook_KeyPressed(object sender, KeyPressedEventArgs e) + { + SwitchOpenClose(); + } + + timerKeySearch.Interval = MenuDefines.KeySearchInterval; + timerKeySearch.Tick += TimerKeySearch_Tick; + menus[0] = new Menu(); + MessageFilter messageFilter = new MessageFilter(); + Application.AddMessageFilter(messageFilter); + menuNotifyIcon.Exit += Application.Exit; + + menuNotifyIcon.HandleClick += SwitchOpenClose; + void SwitchOpenClose() + { + if (Config.Path == string.Empty) + { + //Case when Folder Dialog open + } + else if (isMainMenuOpen && menus[0].Visible) + { + isMainMenuOpen = false; + MenusFadeOut(); + if (worker.IsBusy) + { + worker.CancelAsync(); + } + } + else if (worker.IsBusy) + { + restartLoading = true; + worker.CancelAsync(); + } + else + { + isMainMenuOpen = true; + if (menus[0].Visible) + { + ActivateMenu(); + } else - { - log.Info($"path:'{path}'"); + { + screen = ScreenMouse.GetScreen(); + bool IsNotifyIconInTaskbar() + { + bool isNotifyIconInTaskbar = false; + int height = screen.Bounds.Height - + new Taskbar().Size.Height; + if (Cursor.Position.Y >= height) + { + isNotifyIconInTaskbar = true; + } + return isNotifyIconInTaskbar; + } + if (!IsNotifyIconInTaskbar()) + { + //DragDropHintForm hintForm = new DragDropHintForm( + // Program.Translate("HintDragDropTitle"), + // Program.Translate("HintDragDropText"), + // Program.Translate("buttonOk")); + //hintForm.Show(); + } + + menuNotifyIcon.LoadingStart(); + worker.RunWorkerAsync(); + } + } + } + + worker.WorkerSupportsCancellation = true; + worker.DoWork += Worker_DoWork; + void Worker_DoWork(object senderDoWork, + DoWorkEventArgs eDoWork) + { + int level = 0; + BackgroundWorker worker = (BackgroundWorker)senderDoWork; + restartLoading = false; + eDoWork.Result = ReadMenu(worker, Config.Path, level); + } + + worker.RunWorkerCompleted += Worker_RunWorkerCompleted; + void Worker_RunWorkerCompleted(object sender, + RunWorkerCompletedEventArgs e) + { + if (restartLoading) + { + worker.RunWorkerAsync(); + } + else + { + ResetSelectedByKey(); + menuNotifyIcon.LoadingStop(); + MenuData menuData = (MenuData)e.Result; + if (menuData.Validity == MenuDataValidity.Valid) + { + menus[0] = CreateMenu(menuData, Path.GetFileName(Config.Path)); + menus[0].AdjustLocationAndSize(screen); + ActivateMenu(); + menus[0].AdjustLocationAndSize(screen); + } + } + } + + void ActivateMenu() + { + Menus().ToList().ForEach(menu => + { + menu.FadeIn(); + menu.FadeHalf(); + }); + menus[0].SetTitleColorActive(); + menus[0].Activate(); + WindowToTop.ForceForegroundWindow(menus[0].Handle); + } + + menuNotifyIcon.ChangeFolder += ChangeFolder; + void ChangeFolder() + { + if (Config.SetFolderByUser()) + { + ApplicationRestart(); + } + } + + menuNotifyIcon.OpenLog += OpenLog; + void OpenLog() + { + Process.Start(Program.GetLogFilePath()); + } + + menuNotifyIcon.Restart += ApplicationRestart; + void ApplicationRestart() + { + Dispose(); + Process.Start(Assembly.GetExecutingAssembly(). + ManifestModule.FullyQualifiedName); + } + + messageFilter.MouseMove += FadeInIfNeeded; + messageFilter.ScrollBarMouseMove += FadeInIfNeeded; + + messageFilter.MouseLeave += fastLeave.Start; + fastLeave.Leave += FadeHalfOrOutIfNeeded; + + if (!Config.LoadOrSetByUser()) + { + cancelAppRun = true; + } + } + void FadeInIfNeeded() + { + if (menus[0].Visible && + !menus[0].IsFadingIn && + !menus[0].IsFadingOut) + { + if (Menus().Any(m => m.Opacity < 1)) + { + Menus().ToList().ForEach(menu => menu.FadeIn()); + } + } + } + + void FadeHalfOrOutIfNeeded() + { + Point mousePosition = Control.MousePosition; + bool isMouseOnAnyMenu = + !Menus().Any(m => m.IsMouseOn(mousePosition)); + bool isAnyMenuActive = IsAnyMenuActive(); + + if (isMouseOnAnyMenu) + { + if (isAnyMenuActive && isMainMenuOpen) + { + if (!IsAnyMenuSelectedByKey()) + { + Menus().ToList().ForEach(menu => menu.FadeHalf()); + } + } + else + { + MenusFadeOut(); + } + } + } + + private void ResetSelectedByKey() + { + iRowKey = -1; + iMenuKey = 0; + } + + public void Dispose() + { + hook.Dispose(); + menuNotifyIcon.Dispose(); + fastLeave.Dispose(); + DisposeMenu(menus[0]); + } + + void DisposeMenu(Menu menuToDispose) + { + if (menuToDispose != null) + { + DataGridView dgv = menuToDispose.GetDataGridView(); + foreach (DataGridViewRow row in dgv.Rows) + { + RowData rowData = (RowData)row.Tag; + rowData.Dispose(); + DisposeMenu(rowData.SubMenu); + } + dgv.ClearSelection(); + menuToDispose.Dispose(); + menuToDispose = null; + } + } + + void DisposeWhenHidden(object sender, EventArgs e) + { + Menu menuToDispose = (Menu)sender; + if (!menuToDispose.Visible) + { + DisposeMenu(menuToDispose); + } + } + + void AdjustSubMenusLocationAndSize() + { + Screen screen = ScreenMouse.GetScreen(); + int heightMax = screen.Bounds.Height - + new Taskbar().Size.Height; + Menu menuPredecessor = menus[0]; + int widthPredecessors = -1; // -1 padding + bool directionToRight = false; + + foreach (Menu menu in Menus().Skip(1)) + { + // -1*2 padding + int newWith = (menu.Width - 2 + menuPredecessor.Width); + if (directionToRight) + { +#warning is this still correct? + if (widthPredecessors - menu.Width <= -2) // -1*2 padding + { + directionToRight = false; + } + else + { + widthPredecessors -= newWith; + } + } + else if (screen.Bounds.Width < + widthPredecessors + menuPredecessor.Width + menu.Width) + { + directionToRight = true; + widthPredecessors -= newWith; + } + + menu.AdjustLocationAndSize(heightMax, + widthPredecessors, menuPredecessor); + widthPredecessors += menu.Width - 1; // -1 padding + menuPredecessor = menu; + } + } + + void OpenSubMenu(object sender, EventArgs e) + { + RowData trigger = (RowData)sender; + Menu menuTriggered = trigger.SubMenu; + Menu menuFromTrigger = menus[menuTriggered.Level - 1]; + + for (int level = menuTriggered.Level; + level < MenuDefines.MenusMax; level++) + { + if (menus[level] != null) + { + Menu menuToClose = menus[level]; + RowData oldTrigger = (RowData)menuToClose.Tag; + DataGridView dgv = menuFromTrigger.GetDataGridView(); + foreach (DataGridViewRow row in dgv.Rows) + { + RowData rowData = (RowData)row.Tag; + rowData.IsSelected = false; + } + trigger.IsSelected = true; + dgv.ClearSelection(); + dgv.Rows[trigger.RowIndex].Selected = true; + menuToClose.FadeOut(); + menuToClose.VisibleChanged += DisposeWhenHidden; + menus[level] = null; + } + } + + menus[menuTriggered.Level] = menuTriggered; + AdjustSubMenusLocationAndSize(); + menus[menuTriggered.Level].FadeIn(); + AdjustSubMenusLocationAndSize(); + IsAnyMenuActive(); + } + + void Activated(object sender, EventArgs e) + { + Menu triggeredMenu = (Menu)sender; + menus[0].SetTitleColorActive(); + } + + bool IsAnyMenuActive() + { + bool isAnyMenuActive; + Form activeForm = Form.ActiveForm; + //isAnyMenuActive = Menus().Any(m => m.IsActive(activeForm)); + isAnyMenuActive = activeForm is Menu; + if (!isAnyMenuActive) + { + menus[0].SetTitleColorDeactive(); + CheckMenuOpenerStop(iMenuKey, iRowKey); + ClearIsSelectedByKey(iMenuKey, iRowKey); + ResetSelectedByKey(); + } + else + { + menus[0].SetTitleColorActive(); + } + + return isAnyMenuActive; + } + + MenuData ReadMenu(BackgroundWorker worker, string path, int level) + { + MenuData menuData = new MenuData(); + menuData.RowDatas = new List(); + menuData.Validity = MenuDataValidity.Invalid; + menuData.Level = level; + if (!worker.CancellationPending) + { + string[] directories = new string[] { }; + + try + { + directories = Directory.GetDirectories(path); + Array.Sort(directories, new WindowsExplorerSort()); + } + catch (Exception ex) + { + log.Info($"path:'{path}'"); + log.Error($"{ex.ToString()}"); + } + + foreach (string directory in directories) + { + if (worker != null && worker.CancellationPending) + { + break; + } + + RowData menuButtonData = ReadMenuButtonData(directory, false); + menuButtonData.ContainsMenu = true; + string resolvedLnkPath = string.Empty; + menuButtonData.ReadIcon(true, false, ref resolvedLnkPath); + menuData.RowDatas.Add(menuButtonData); + } + } + + if (!worker.CancellationPending) + { + string[] files = new string[] { }; + + try + { + files = Directory.GetFiles(path). + Where(p => Path.GetFileName(p) != "desktop.ini").ToArray(); + Array.Sort(files, new WindowsExplorerSort()); + } + catch (Exception ex) + { + if ((uint)ex.HResult == 0x80070005) // E_ACCESSDENIED + menuData.Validity = MenuDataValidity.NoAccess; + else + { + log.Info($"path:'{path}'"); log.Error($"{ex.ToString()}"); - } - } - - foreach (string file in files) - { - if (worker != null && worker.CancellationPending) - { - break; - } - - RowData menuButtonData = ReadMenuButtonData(file, false); - string resolvedLnkPath = string.Empty; - if (menuButtonData.ReadIcon(false, - false, ref resolvedLnkPath)) - { - menuButtonData = ReadMenuButtonData(resolvedLnkPath, true, file); - menuButtonData.ContainsMenu = true; - menuButtonData.ReadIcon(true, true, ref resolvedLnkPath); - } - - menuData.RowDatas.Add(menuButtonData); - } - } - - if (!worker.CancellationPending) - { - if (menuData.Validity == MenuDataValidity.Invalid) - menuData.Validity = MenuDataValidity.Valid; - } - - return menuData; - } - - RowData ReadMenuButtonData(string fileName, - bool isResolvedLnk, string fileUnresolved = null) - { - RowData menuButtonData = new RowData(); - menuButtonData.IsResolvedLnk = isResolvedLnk; - - try - { - menuButtonData.FileInfo = new FileInfo(fileName); - menuButtonData.TargetFilePath = menuButtonData.FileInfo.FullName; - menuButtonData.SetText($"{menuButtonData.FileInfo.Name}"); - if(string.IsNullOrEmpty(fileUnresolved)) - { - menuButtonData.TargetFilePathOrig = menuButtonData.TargetFilePath; - } - else - { - menuButtonData.TargetFilePathOrig = fileUnresolved; - } - } - catch (Exception ex) - { - log.Info($"fileName:'{fileName}'"); - log.Error($"{ex.ToString()}"); - } - - return menuButtonData; - } - - private void Dgv_MouseDoubleClick(object sender, MouseEventArgs e) - { - DataGridView dgv = (DataGridView)sender; - DataGridView.HitTestInfo hitTestInfo; - hitTestInfo = dgv.HitTest(e.X, e.Y); - if (hitTestInfo.RowIndex > -1 && - dgv.Rows.Count > hitTestInfo.RowIndex) - { - RowData trigger = (RowData)dgv.Rows[hitTestInfo.RowIndex].Tag; - trigger.DoubleClick(); - } - } - - private void Dgv_MouseDown(object sender, MouseEventArgs e) - { - DataGridView dgv = (DataGridView)sender; - DataGridView.HitTestInfo hitTestInfo; - hitTestInfo = dgv.HitTest(e.X, e.Y); - if (hitTestInfo.RowIndex > -1 && - dgv.Rows.Count > hitTestInfo.RowIndex) - { - RowData trigger = (RowData)dgv.Rows[hitTestInfo.RowIndex].Tag; - trigger.MouseDown(dgv, e); - } - } - - private void Dgv_MouseEnter(object sender, DataGridViewCellEventArgs e) - { - DataGridView dgv = (DataGridView)sender; - CheckMenuOpenerStart(dgv, e.RowIndex); - } - - private void CheckMenuOpenerStart(DataGridView dgv, int rowIndex) - { - if (rowIndex > -1 && - dgv.Rows.Count > rowIndex) - { - RowData trigger = (RowData)dgv.Rows[rowIndex].Tag; - trigger.IsSelected = true; - dgv.Rows[rowIndex].Selected = true; - Menu menuFromTrigger = (Menu)dgv.FindForm(); - Menu menuTriggered = trigger.SubMenu; - int level = menuFromTrigger.Level + 1; - - if (trigger.ContainsMenu && - level < MenuDefines.MenusMax && - !menus[0].IsFadingOut && - !menuFromTrigger.IsFadingOut && - (menus[level] == null || - menus[level] != menuTriggered)) - { - trigger.StopLoadMenuAndStartWaitToOpenIt(); - trigger.StartMenuOpener(); - - if (trigger.Reading.IsBusy) - { - trigger.RestartLoading = true; - } - else - { - menuNotifyIcon.LoadingStart(); - trigger.Reading.RunWorkerAsync(level); - } - } - } - } - - private void Dgv_MouseLeave(object sender, DataGridViewCellEventArgs e) - { - DataGridView dgv = (DataGridView)sender; - Menu menu = (Menu)dgv.FindForm(); - CheckMenuOpenerStop(menu.Level, e.RowIndex, dgv); - } - - private void CheckMenuOpenerStop(int menuIndex, int rowIndex, DataGridView dgv = null) - { - Menu menu = menus[menuIndex]; - if (menu != null && - rowIndex > -1) - { - if (dgv == null) - { - dgv = menu.GetDataGridView(); - } - if (dgv.Rows.Count > rowIndex) - { - RowData trigger = (RowData)dgv.Rows[rowIndex].Tag; - if (trigger.Reading.IsBusy) - { - if (!trigger.IsContextMenuOpen) - { - trigger.IsSelected = false; - dgv.Rows[rowIndex].Selected = false; - } - trigger.Reading.CancelAsync(); - } - else if (trigger.ContainsMenu && !trigger.IsLoading) - { - trigger.IsSelected = true; - dgv.Rows[rowIndex].Selected = true; - } - else - { - if (!trigger.IsContextMenuOpen) - { - trigger.IsSelected = false; - dgv.Rows[rowIndex].Selected = false; - } - } - if (trigger.IsLoading) - { - trigger.StopLoadMenuAndStartWaitToOpenIt(); - trigger.IsLoading = false; - } - } - } - } - - private void Dgv_SelectionChanged(object sender, EventArgs e) - { - DataGridView dgv = (DataGridView)sender; - foreach (DataGridViewRow row in dgv.Rows) - { - RowData rowData = (RowData)row.Tag; - if (rowData.IsSelectedByKeyboard) - { - row.DefaultCellStyle.SelectionBackColor = - MenuDefines.KeyBoardSelection; - row.Selected = true; - } - else if (rowData.IsSelected) - { - row.DefaultCellStyle.SelectionBackColor = - MenuDefines.FolderOpen; - row.Selected = true; - } - else - { - rowData.IsSelected = false; - row.Selected = false; - } - } - } - - IEnumerable Menus() - { - return menus.Where(m => m != null); - } - - void MenusFadeOut() - { - Menus().ToList().ForEach(menu => - { - if (menu.Level > 0) - { - menus[menu.Level] = null; - } - menu.FadeOut(); - }); - } - - Menu CreateMenu(MenuData menuData, string title = null) - { - Menu menu = new Menu(); - if (title != null) - { - if (title == string.Empty) - { - title = Path.GetPathRoot(Config.Path); - } - - menu.SetTitle(title); - menu.UserClickedOpenFolder += OpenFolder; - void OpenFolder() - { - Process.Start("explorer.exe", Config.Path); - } - } - menu.Level = menuData.Level; - menu.MouseWheel += AdjustSubMenusLocationAndSize; - DataGridView dgv = menu.GetDataGridView(); - dgv.CellMouseEnter += Dgv_MouseEnter; - dgv.CellMouseLeave += Dgv_MouseLeave; - dgv.MouseDoubleClick += Dgv_MouseDoubleClick; - dgv.MouseDown += Dgv_MouseDown; - dgv.SelectionChanged += Dgv_SelectionChanged; - menu.KeyPress += KeyPress; - menu.CmdKeyProcessed += CmdKeyProcessed; - menu.Activated += Activated; - menu.Deactivated += fastLeave.Start; - menu.VisibleChanged += DisposeWhenHidden; - AddItemsToMenu(menuData.RowDatas, menu); - return menu; - } - - private void KeyPress(object sender, KeyPressEventArgs e) - { - if (char.IsLetterOrDigit(e.KeyChar) || - char.IsPunctuation(e.KeyChar) || - char.IsWhiteSpace(e.KeyChar) || - char.IsSeparator(e.KeyChar)) - { - string letter = e.KeyChar.ToString(); - - if (string.IsNullOrEmpty(keyInput)) - { - keyInput = letter; - Search(keyInput, true); - } - else if (keyInput.LastOrDefault().ToString() == letter) - { - keyInput += letter; - Search(letter, true); - timerKeySearch.Stop(); - } - else - { - keyInput += letter; - Search(keyInput, false); - timerKeySearch.Stop(); - } - timerKeySearch.Start(); - e.Handled = true; - } - } - - private void TimerKeySearch_Tick(object sender, EventArgs e) - { - timerKeySearch.Stop(); - //Search(keyInput); - keyInput = string.Empty; - } - -#warning better word than force - private void Search(string keyInput, bool force) - { - SelectByKey(Keys.None, keyInput, force); - } - - private void CmdKeyProcessed(Keys keys) - { - SelectByKey(keys); - } - - private bool IsAnyMenuSelectedByKey() - { - Menu menu = null; - DataGridView dgv = null; - string textselected = string.Empty; - return IsAnyMenuSelectedByKey(ref dgv, ref menu, ref textselected); - } - - private bool IsAnyMenuSelectedByKey( - ref DataGridView dgv, - ref Menu menuFromSelected, - ref string textselected) - { - Menu menu = menus[iMenuKey]; - bool isStillSelected = false; - if (menu != null && - iRowKey > -1) - { - dgv = menu.GetDataGridView(); - if (dgv.Rows.Count > iRowKey) - { - RowData rowData = (RowData)dgv. - Rows[iRowKey].Tag; - if (rowData.IsSelectedByKeyboard) - { - isStillSelected = true; - menuFromSelected = rowData.SubMenu; -#warning refactor datagridviewrow get - textselected = dgv.Rows[iRowKey]. - Cells[1].Value.ToString(); - } - } - } - - return isStillSelected; - } - - private void SelectByKey(Keys keys, string keyInput = "", - bool force = true) - { - int iRowBefore = iRowKey; - int iMenuBefore = iMenuKey; - - Menu menu = menus[iMenuKey]; - DataGridView dgv = null; - DataGridView dgvBefore = null; - Menu menuFromSelected = null; - string textselected = string.Empty; - bool isStillSelected = IsAnyMenuSelectedByKey( - ref dgv, ref menuFromSelected, ref textselected); - if (isStillSelected) - { - dgvBefore = dgv; - if (!force && - textselected.ToLower().StartsWith(keyInput.ToLower())) - { -#warning rewrite function should not return here - return; // is that ok? check twice - } - } - else - { - ResetSelectedByKey(); - menu = menus[iMenuKey]; - dgv = menu.GetDataGridView(); - } - - bool toClear = false; - switch (keys) - { - case Keys.Enter: - if (iRowKey > -1 && - dgv.Rows.Count > iRowKey) - { - RowData trigger = (RowData)dgv.Rows[iRowKey].Tag; - trigger.MouseDown(dgv, null); - //trigger.DoubleClick(); - } - break; - case Keys.Up: - FadeInIfNeeded(); - if (SelectMatchedReverse(dgv, iRowKey) || - SelectMatchedReverse(dgv, dgv.Rows.Count - 1)) - { - CheckMenuOpenerStop(iMenuBefore, iRowBefore, dgvBefore); - CheckMenuOpenerStart(dgv, iRowKey); - toClear = true; - } - break; - case Keys.Down: - FadeInIfNeeded(); - if (SelectMatched(dgv, iRowKey) || - SelectMatched(dgv, 0)) - { - CheckMenuOpenerStop(iMenuBefore, iRowBefore, dgvBefore); - CheckMenuOpenerStart(dgv, iRowKey); - toClear = true; - } - break; - case Keys.Left: - FadeInIfNeeded(); - int iMenuKeyNext = iMenuKey + 1; - if (isStillSelected) - { - if (menuFromSelected != null && - menuFromSelected == menus[iMenuKeyNext]) - { - dgv = menuFromSelected.GetDataGridView(); - if (dgv.Rows.Count > 0) - { - iMenuKey += 1; - iRowKey = -1; - if (SelectMatched(dgv, iRowKey) || - SelectMatched(dgv, 0)) - { - CheckMenuOpenerStop(iMenuBefore, - iRowBefore, dgvBefore); - CheckMenuOpenerStart(dgv, iRowKey); - toClear = true; - } - } - } - } - else - { - iRowKey = -1; - iMenuKey = menus.Where(m => m != null).Count() - 1; - if (menus[iMenuKey] != null) - { - dgv = menus[iMenuKey].GetDataGridView(); - if (SelectMatched(dgv, iRowKey) || - SelectMatched(dgv, 0)) - { - CheckMenuOpenerStop(iMenuBefore, iRowBefore, dgvBefore); - CheckMenuOpenerStart(dgv, iRowKey); - toClear = true; - } - } - else - { - log.Info("indexMenuByKey = menus.Where(m => m != null).Count()" + - "=> menus[iMenuKey] == null"); - } - } - break; - case Keys.Right: - if (iMenuKey > 0) - { - if (menus[iMenuKey - 1] != null) - { - iMenuKey -= 1; - iRowKey = -1; - menu = menus[iMenuKey]; - dgv = menu.GetDataGridView(); - if (SelectMatched(dgv, dgv.SelectedRows[0].Index) || - SelectMatched(dgv, 0)) - { - CheckMenuOpenerStop(iMenuBefore, iRowBefore, dgvBefore); - CheckMenuOpenerStart(dgv, iRowKey); - toClear = true; - } - } - } - else - { - CheckMenuOpenerStop(iMenuBefore, iRowBefore, dgvBefore); - iMenuKey = 0; - iRowKey = -1; - toClear = true; - FadeHalfOrOutIfNeeded(); - } - break; - case Keys.Escape: - CheckMenuOpenerStop(iMenuBefore, iRowBefore, dgvBefore); - iMenuKey = 0; - iRowKey = -1; - toClear = true; - isMainMenuOpen = false; - MenusFadeOut(); - break; - default: + } + } + + foreach (string file in files) + { + if (worker != null && worker.CancellationPending) + { + break; + } + + RowData menuButtonData = ReadMenuButtonData(file, false); + string resolvedLnkPath = string.Empty; + if (menuButtonData.ReadIcon(false, + false, ref resolvedLnkPath)) + { + menuButtonData = ReadMenuButtonData(resolvedLnkPath, true, file); + menuButtonData.ContainsMenu = true; + menuButtonData.ReadIcon(true, true, ref resolvedLnkPath); + } + + menuData.RowDatas.Add(menuButtonData); + } + } + + if (!worker.CancellationPending) + { + if (menuData.Validity == MenuDataValidity.Invalid) + menuData.Validity = MenuDataValidity.Valid; + } + + return menuData; + } + + RowData ReadMenuButtonData(string fileName, + bool isResolvedLnk, string fileUnresolved = null) + { + RowData menuButtonData = new RowData(); + menuButtonData.IsResolvedLnk = isResolvedLnk; + + try + { + menuButtonData.FileInfo = new FileInfo(fileName); + menuButtonData.TargetFilePath = menuButtonData.FileInfo.FullName; + menuButtonData.SetText($"{menuButtonData.FileInfo.Name}"); + if(string.IsNullOrEmpty(fileUnresolved)) + { + menuButtonData.TargetFilePathOrig = menuButtonData.TargetFilePath; + } + else + { + menuButtonData.TargetFilePathOrig = fileUnresolved; + } + } + catch (Exception ex) + { + log.Info($"fileName:'{fileName}'"); + log.Error($"{ex.ToString()}"); + } + + return menuButtonData; + } + + private void Dgv_MouseDoubleClick(object sender, MouseEventArgs e) + { + DataGridView dgv = (DataGridView)sender; + DataGridView.HitTestInfo hitTestInfo; + hitTestInfo = dgv.HitTest(e.X, e.Y); + if (hitTestInfo.RowIndex > -1 && + dgv.Rows.Count > hitTestInfo.RowIndex) + { + RowData trigger = (RowData)dgv.Rows[hitTestInfo.RowIndex].Tag; + trigger.DoubleClick(); + } + } + + private void Dgv_MouseDown(object sender, MouseEventArgs e) + { + DataGridView dgv = (DataGridView)sender; + DataGridView.HitTestInfo hitTestInfo; + hitTestInfo = dgv.HitTest(e.X, e.Y); + if (hitTestInfo.RowIndex > -1 && + dgv.Rows.Count > hitTestInfo.RowIndex) + { + RowData trigger = (RowData)dgv.Rows[hitTestInfo.RowIndex].Tag; + trigger.MouseDown(dgv, e); + } + } + + private void Dgv_MouseEnter(object sender, DataGridViewCellEventArgs e) + { + DataGridView dgv = (DataGridView)sender; + CheckMenuOpenerStart(dgv, e.RowIndex); + } + + private void CheckMenuOpenerStart(DataGridView dgv, int rowIndex) + { + if (rowIndex > -1 && + dgv.Rows.Count > rowIndex) + { + RowData trigger = (RowData)dgv.Rows[rowIndex].Tag; + trigger.IsSelected = true; + dgv.Rows[rowIndex].Selected = true; + Menu menuFromTrigger = (Menu)dgv.FindForm(); + Menu menuTriggered = trigger.SubMenu; + int level = menuFromTrigger.Level + 1; + + if (trigger.ContainsMenu && + level < MenuDefines.MenusMax && + !menus[0].IsFadingOut && + !menuFromTrigger.IsFadingOut && + (menus[level] == null || + menus[level] != menuTriggered)) + { + trigger.StopLoadMenuAndStartWaitToOpenIt(); + trigger.StartMenuOpener(); + + if (trigger.Reading.IsBusy) + { + trigger.RestartLoading = true; + } + else + { + menuNotifyIcon.LoadingStart(); + trigger.Reading.RunWorkerAsync(level); + } + } + } + } + + private void Dgv_MouseLeave(object sender, DataGridViewCellEventArgs e) + { + DataGridView dgv = (DataGridView)sender; + Menu menu = (Menu)dgv.FindForm(); + CheckMenuOpenerStop(menu.Level, e.RowIndex, dgv); + } + + private void CheckMenuOpenerStop(int menuIndex, int rowIndex, DataGridView dgv = null) + { + Menu menu = menus[menuIndex]; + if (menu != null && + rowIndex > -1) + { + if (dgv == null) + { + dgv = menu.GetDataGridView(); + } + if (dgv.Rows.Count > rowIndex) + { + RowData trigger = (RowData)dgv.Rows[rowIndex].Tag; + if (trigger.Reading.IsBusy) + { + if (!trigger.IsContextMenuOpen) + { + trigger.IsSelected = false; + dgv.Rows[rowIndex].Selected = false; + } + trigger.Reading.CancelAsync(); + } + else if (trigger.ContainsMenu && !trigger.IsLoading) + { + trigger.IsSelected = true; + dgv.Rows[rowIndex].Selected = true; + } + else + { + if (!trigger.IsContextMenuOpen) + { + trigger.IsSelected = false; + dgv.Rows[rowIndex].Selected = false; + } + } + if (trigger.IsLoading) + { + trigger.StopLoadMenuAndStartWaitToOpenIt(); + trigger.IsLoading = false; + } + } + } + } + + private void Dgv_SelectionChanged(object sender, EventArgs e) + { + DataGridView dgv = (DataGridView)sender; + foreach (DataGridViewRow row in dgv.Rows) + { + RowData rowData = (RowData)row.Tag; + if (rowData.IsSelectedByKeyboard) + { + row.DefaultCellStyle.SelectionBackColor = + MenuDefines.KeyBoardSelection; + row.Selected = true; + } + else if (rowData.IsSelected) + { + row.DefaultCellStyle.SelectionBackColor = + MenuDefines.FolderOpen; + row.Selected = true; + } + else + { + rowData.IsSelected = false; + row.Selected = false; + } + } + } + + IEnumerable Menus() + { + return menus.Where(m => m != null); + } + + void MenusFadeOut() + { + Menus().ToList().ForEach(menu => + { + if (menu.Level > 0) + { + menus[menu.Level] = null; + } + menu.FadeOut(); + }); + } + + Menu CreateMenu(MenuData menuData, string title = null) + { + Menu menu = new Menu(); + if (title != null) + { + if (title == string.Empty) + { + title = Path.GetPathRoot(Config.Path); + } + + menu.SetTitle(title); + menu.UserClickedOpenFolder += OpenFolder; + void OpenFolder() + { + Process.Start("explorer.exe", Config.Path); + } + } + menu.Level = menuData.Level; + menu.MouseWheel += AdjustSubMenusLocationAndSize; + DataGridView dgv = menu.GetDataGridView(); + dgv.CellMouseEnter += Dgv_MouseEnter; + dgv.CellMouseLeave += Dgv_MouseLeave; + dgv.MouseDoubleClick += Dgv_MouseDoubleClick; + dgv.MouseDown += Dgv_MouseDown; + dgv.SelectionChanged += Dgv_SelectionChanged; + menu.KeyPress += KeyPress; + menu.CmdKeyProcessed += CmdKeyProcessed; + menu.Activated += Activated; + menu.Deactivated += fastLeave.Start; + menu.VisibleChanged += DisposeWhenHidden; + AddItemsToMenu(menuData.RowDatas, menu); + return menu; + } + + private void KeyPress(object sender, KeyPressEventArgs e) + { + if (char.IsLetterOrDigit(e.KeyChar) || + char.IsPunctuation(e.KeyChar) || + char.IsWhiteSpace(e.KeyChar) || + char.IsSeparator(e.KeyChar)) + { + string letter = e.KeyChar.ToString(); + + if (string.IsNullOrEmpty(keyInput)) + { + keyInput = letter; + Search(keyInput, true); + } + else if (keyInput.LastOrDefault().ToString() == letter) + { + keyInput += letter; + Search(letter, true); + timerKeySearch.Stop(); + } + else + { + keyInput += letter; + Search(keyInput, false); + timerKeySearch.Stop(); + } + timerKeySearch.Start(); + e.Handled = true; + } + } + + private void TimerKeySearch_Tick(object sender, EventArgs e) + { + timerKeySearch.Stop(); + //Search(keyInput); + keyInput = string.Empty; + } + +#warning better word than force + private void Search(string keyInput, bool force) + { + SelectByKey(Keys.None, keyInput, force); + } + + private void CmdKeyProcessed(Keys keys) + { + SelectByKey(keys); + } + + private bool IsAnyMenuSelectedByKey() + { + Menu menu = null; + DataGridView dgv = null; + string textselected = string.Empty; + return IsAnyMenuSelectedByKey(ref dgv, ref menu, ref textselected); + } + + private bool IsAnyMenuSelectedByKey( + ref DataGridView dgv, + ref Menu menuFromSelected, + ref string textselected) + { + Menu menu = menus[iMenuKey]; + bool isStillSelected = false; + if (menu != null && + iRowKey > -1) + { + dgv = menu.GetDataGridView(); + if (dgv.Rows.Count > iRowKey) + { + RowData rowData = (RowData)dgv. + Rows[iRowKey].Tag; + if (rowData.IsSelectedByKeyboard) + { + isStillSelected = true; + menuFromSelected = rowData.SubMenu; +#warning refactor datagridviewrow get + textselected = dgv.Rows[iRowKey]. + Cells[1].Value.ToString(); + } + } + } + + return isStillSelected; + } + + private void SelectByKey(Keys keys, string keyInput = "", + bool force = true) + { + int iRowBefore = iRowKey; + int iMenuBefore = iMenuKey; + + Menu menu = menus[iMenuKey]; + DataGridView dgv = null; + DataGridView dgvBefore = null; + Menu menuFromSelected = null; + string textselected = string.Empty; + bool isStillSelected = IsAnyMenuSelectedByKey( + ref dgv, ref menuFromSelected, ref textselected); + if (isStillSelected) + { + dgvBefore = dgv; + if (!force && + textselected.ToLower().StartsWith(keyInput.ToLower())) + { +#warning rewrite function should not return here + return; // is that ok? check twice + } + } + else + { + ResetSelectedByKey(); + menu = menus[iMenuKey]; + dgv = menu.GetDataGridView(); + } + + bool toClear = false; + switch (keys) + { + case Keys.Enter: + if (iRowKey > -1 && + dgv.Rows.Count > iRowKey) + { + RowData trigger = (RowData)dgv.Rows[iRowKey].Tag; + trigger.MouseDown(dgv, null); + //trigger.DoubleClick(); + } + break; + case Keys.Up: + FadeInIfNeeded(); + if (SelectMatchedReverse(dgv, iRowKey) || + SelectMatchedReverse(dgv, dgv.Rows.Count - 1)) + { + CheckMenuOpenerStop(iMenuBefore, iRowBefore, dgvBefore); + CheckMenuOpenerStart(dgv, iRowKey); + toClear = true; + } + break; + case Keys.Down: + FadeInIfNeeded(); + if (SelectMatched(dgv, iRowKey) || + SelectMatched(dgv, 0)) + { + CheckMenuOpenerStop(iMenuBefore, iRowBefore, dgvBefore); + CheckMenuOpenerStart(dgv, iRowKey); + toClear = true; + } + break; + case Keys.Left: + FadeInIfNeeded(); + int iMenuKeyNext = iMenuKey + 1; + if (isStillSelected) + { + if (menuFromSelected != null && + menuFromSelected == menus[iMenuKeyNext]) + { + dgv = menuFromSelected.GetDataGridView(); + if (dgv.Rows.Count > 0) + { + iMenuKey += 1; + iRowKey = -1; + if (SelectMatched(dgv, iRowKey) || + SelectMatched(dgv, 0)) + { + CheckMenuOpenerStop(iMenuBefore, + iRowBefore, dgvBefore); + CheckMenuOpenerStart(dgv, iRowKey); + toClear = true; + } + } + } + } + else + { + iRowKey = -1; + iMenuKey = menus.Where(m => m != null).Count() - 1; + if (menus[iMenuKey] != null) + { + dgv = menus[iMenuKey].GetDataGridView(); + if (SelectMatched(dgv, iRowKey) || + SelectMatched(dgv, 0)) + { + CheckMenuOpenerStop(iMenuBefore, iRowBefore, dgvBefore); + CheckMenuOpenerStart(dgv, iRowKey); + toClear = true; + } + } + else + { + log.Info("indexMenuByKey = menus.Where(m => m != null).Count()" + + "=> menus[iMenuKey] == null"); + } + } + break; + case Keys.Right: + if (iMenuKey > 0) + { + if (menus[iMenuKey - 1] != null) + { + iMenuKey -= 1; + iRowKey = -1; + menu = menus[iMenuKey]; + dgv = menu.GetDataGridView(); + if (SelectMatched(dgv, dgv.SelectedRows[0].Index) || + SelectMatched(dgv, 0)) + { + CheckMenuOpenerStop(iMenuBefore, iRowBefore, dgvBefore); + CheckMenuOpenerStart(dgv, iRowKey); + toClear = true; + } + } + } + else + { + CheckMenuOpenerStop(iMenuBefore, iRowBefore, dgvBefore); + iMenuKey = 0; + iRowKey = -1; + toClear = true; + FadeHalfOrOutIfNeeded(); + } + break; + case Keys.Escape: + CheckMenuOpenerStop(iMenuBefore, iRowBefore, dgvBefore); + iMenuKey = 0; + iRowKey = -1; + toClear = true; + isMainMenuOpen = false; + MenusFadeOut(); + break; + default: if (!string.IsNullOrEmpty(keyInput)) { - if (SelectMatched(dgv, iRowKey, keyInput) || + if (SelectMatched(dgv, iRowKey, keyInput) || SelectMatched(dgv, 0, keyInput)) { FadeInIfNeeded(); @@ -959,167 +959,167 @@ namespace SystemTrayMenu iRowKey = iRowBefore; } } - } - break; - } - if (isStillSelected && toClear) - { - ClearIsSelectedByKey(iMenuBefore, - iRowBefore); - } - - } - - private bool SelectMatched(DataGridView dgv, - int indexStart, string keyInput = "") - { - bool found = false; - for (int i = indexStart; i < dgv.Rows.Count; i++) - { - if (Select(dgv, i, keyInput)) - { - found = true; - break; - } - } - return found; - } - - private bool SelectMatchedReverse(DataGridView dgv, - int indexStart, string keyInput = "") - { - bool found = false; - for (int i = indexStart; i > -1; i--) - { - if (Select(dgv, i, keyInput)) - { - found = true; - break; - } - } - return found; - } - - private bool Select(DataGridView dgv, int i, - string keyInput = "") - { - bool found = false; - if (i > -1 && - i != iRowKey && - dgv.Rows.Count > i) - { - DataGridViewRow row = dgv.Rows[i]; - RowData rowData = (RowData)row.Tag; - string text = row.Cells[1].Value.ToString(); - if (text.ToLower().StartsWith(keyInput.ToLower())) - { - iRowKey = rowData.RowIndex; - rowData.IsSelectedByKeyboard = true; - row.Selected = false; //event trigger - row.Selected = true; //event trigger - if (row.Index < dgv.FirstDisplayedScrollingRowIndex) - { - dgv.FirstDisplayedScrollingRowIndex = row.Index; - } - else if(row.Index >= - dgv.FirstDisplayedScrollingRowIndex + - dgv.DisplayedRowCount(false)) - { - dgv.FirstDisplayedScrollingRowIndex = row.Index - - dgv.DisplayedRowCount(false) + 1; - } - - found = true; - } - } - return found; - } - - private void ClearIsSelectedByKey(int menuIndex, int rowIndex) - { - Menu menu = menus[menuIndex]; - if (menu != null && rowIndex > -1) - { - DataGridView dgv = menu.GetDataGridView(); - if (dgv.Rows.Count > rowIndex) - { - DataGridViewRow row = dgv.Rows[rowIndex]; - RowData rowData = (RowData)row.Tag; - rowData.IsSelectedByKeyboard = false; - row.Selected = false; //event trigger - } - } - } - - private void AddItemsToMenu(List data, Menu menu) - { - foreach (RowData rowData in data) - { - CreateMenuRow(rowData, menu); - } - } - - private void CreateMenuRow(RowData rowData, Menu menu) - { - rowData.SetData(rowData, menu.GetDataGridView()); - rowData.OpenMenu += OpenSubMenu; - rowData.Reading.WorkerSupportsCancellation = true; - rowData.Reading.DoWork += ReadMenu_DoWork; - void ReadMenu_DoWork(object senderDoWork, - DoWorkEventArgs eDoWork) - { - int level = (int)eDoWork.Argument; - BackgroundWorker worker = (BackgroundWorker)senderDoWork; - rowData.RestartLoading = false; - eDoWork.Result = ReadMenu(worker, rowData.TargetFilePath, level); - } - - rowData.Reading.RunWorkerCompleted += ReadMenu_RunWorkerCompleted; - void ReadMenu_RunWorkerCompleted(object senderCompleted, - RunWorkerCompletedEventArgs e) - { - MenuData menuData = (MenuData)e.Result; - if (rowData.RestartLoading) - { - rowData.Reading.RunWorkerAsync(menuData.Level); - } - else - { - menuNotifyIcon.LoadingStop(); - menuNotifyIcon.LoadWait(); - if (menuData.Validity != MenuDataValidity.Invalid) - { - menu = CreateMenu(menuData); - if (menuData.RowDatas.Count > 0) - { - menu.SetTypeSub(); - } - else if (menuData.Validity == MenuDataValidity.NoAccess) - { - menu.SetTypeNoAccess(); - } - else - { - menu.SetTypeEmpty(); - } - menu.Tag = rowData; - rowData.SubMenu = menu; - rowData.MenuLoaded(); - } - menuNotifyIcon.LoadStop(); - } - } - } - } - - class WindowsExplorerSort : IComparer - { - [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)] - static extern int StrCmpLogicalW(String x, String y); - - public int Compare(string x, string y) - { - return StrCmpLogicalW(x, y); - } - } + } + break; + } + if (isStillSelected && toClear) + { + ClearIsSelectedByKey(iMenuBefore, + iRowBefore); + } + + } + + private bool SelectMatched(DataGridView dgv, + int indexStart, string keyInput = "") + { + bool found = false; + for (int i = indexStart; i < dgv.Rows.Count; i++) + { + if (Select(dgv, i, keyInput)) + { + found = true; + break; + } + } + return found; + } + + private bool SelectMatchedReverse(DataGridView dgv, + int indexStart, string keyInput = "") + { + bool found = false; + for (int i = indexStart; i > -1; i--) + { + if (Select(dgv, i, keyInput)) + { + found = true; + break; + } + } + return found; + } + + private bool Select(DataGridView dgv, int i, + string keyInput = "") + { + bool found = false; + if (i > -1 && + i != iRowKey && + dgv.Rows.Count > i) + { + DataGridViewRow row = dgv.Rows[i]; + RowData rowData = (RowData)row.Tag; + string text = row.Cells[1].Value.ToString(); + if (text.ToLower().StartsWith(keyInput.ToLower())) + { + iRowKey = rowData.RowIndex; + rowData.IsSelectedByKeyboard = true; + row.Selected = false; //event trigger + row.Selected = true; //event trigger + if (row.Index < dgv.FirstDisplayedScrollingRowIndex) + { + dgv.FirstDisplayedScrollingRowIndex = row.Index; + } + else if(row.Index >= + dgv.FirstDisplayedScrollingRowIndex + + dgv.DisplayedRowCount(false)) + { + dgv.FirstDisplayedScrollingRowIndex = row.Index - + dgv.DisplayedRowCount(false) + 1; + } + + found = true; + } + } + return found; + } + + private void ClearIsSelectedByKey(int menuIndex, int rowIndex) + { + Menu menu = menus[menuIndex]; + if (menu != null && rowIndex > -1) + { + DataGridView dgv = menu.GetDataGridView(); + if (dgv.Rows.Count > rowIndex) + { + DataGridViewRow row = dgv.Rows[rowIndex]; + RowData rowData = (RowData)row.Tag; + rowData.IsSelectedByKeyboard = false; + row.Selected = false; //event trigger + } + } + } + + private void AddItemsToMenu(List data, Menu menu) + { + foreach (RowData rowData in data) + { + CreateMenuRow(rowData, menu); + } + } + + private void CreateMenuRow(RowData rowData, Menu menu) + { + rowData.SetData(rowData, menu.GetDataGridView()); + rowData.OpenMenu += OpenSubMenu; + rowData.Reading.WorkerSupportsCancellation = true; + rowData.Reading.DoWork += ReadMenu_DoWork; + void ReadMenu_DoWork(object senderDoWork, + DoWorkEventArgs eDoWork) + { + int level = (int)eDoWork.Argument; + BackgroundWorker worker = (BackgroundWorker)senderDoWork; + rowData.RestartLoading = false; + eDoWork.Result = ReadMenu(worker, rowData.TargetFilePath, level); + } + + rowData.Reading.RunWorkerCompleted += ReadMenu_RunWorkerCompleted; + void ReadMenu_RunWorkerCompleted(object senderCompleted, + RunWorkerCompletedEventArgs e) + { + MenuData menuData = (MenuData)e.Result; + if (rowData.RestartLoading) + { + rowData.Reading.RunWorkerAsync(menuData.Level); + } + else + { + menuNotifyIcon.LoadingStop(); + menuNotifyIcon.LoadWait(); + if (menuData.Validity != MenuDataValidity.Invalid) + { + menu = CreateMenu(menuData); + if (menuData.RowDatas.Count > 0) + { + menu.SetTypeSub(); + } + else if (menuData.Validity == MenuDataValidity.NoAccess) + { + menu.SetTypeNoAccess(); + } + else + { + menu.SetTypeEmpty(); + } + menu.Tag = rowData; + rowData.SubMenu = menu; + rowData.MenuLoaded(); + } + menuNotifyIcon.LoadStop(); + } + } + } + } + + class WindowsExplorerSort : IComparer + { + [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)] + static extern int StrCmpLogicalW(String x, String y); + + public int Compare(string x, string y) + { + return StrCmpLogicalW(x, y); + } + } } \ No newline at end of file