2020-09-27 01:54:24 +12:00
|
|
|
|
// <copyright file="Menus.cs" company="PlaceholderCompany">
|
|
|
|
|
// Copyright (c) PlaceholderCompany. All rights reserved.
|
|
|
|
|
// </copyright>
|
|
|
|
|
|
|
|
|
|
namespace SystemTrayMenu.Business
|
|
|
|
|
{
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.ComponentModel;
|
|
|
|
|
using System.Data;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
using SystemTrayMenu.DataClasses;
|
|
|
|
|
using SystemTrayMenu.Handler;
|
|
|
|
|
using SystemTrayMenu.Helper;
|
|
|
|
|
using SystemTrayMenu.Utilities;
|
2021-06-27 21:35:07 +12:00
|
|
|
|
using Menu = SystemTrayMenu.UserInterface.Menu;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
using Timer = System.Windows.Forms.Timer;
|
|
|
|
|
|
|
|
|
|
internal class Menus : IDisposable
|
|
|
|
|
{
|
|
|
|
|
private readonly Menu[] menus = new Menu[MenuDefines.MenusMax];
|
2021-11-17 12:13:46 +13:00
|
|
|
|
private readonly BackgroundWorker workerMainMenu = new();
|
|
|
|
|
private readonly List<BackgroundWorker> workersSubMenu = new();
|
2020-09-27 01:54:24 +12:00
|
|
|
|
|
2021-11-17 12:13:46 +13:00
|
|
|
|
private readonly DgvMouseRow dgvMouseRow = new();
|
|
|
|
|
private readonly WaitToLoadMenu waitToOpenMenu = new();
|
2021-04-17 12:39:48 +12:00
|
|
|
|
private readonly KeyboardInput keyboardInput;
|
2021-11-17 12:13:46 +13:00
|
|
|
|
private readonly Timer timerShowProcessStartedAsLoadingIcon = new();
|
|
|
|
|
private readonly Timer timerStillActiveCheck = new();
|
|
|
|
|
private readonly WaitLeave waitLeave = new(Properties.Settings.Default.TimeUntilCloses);
|
2020-09-27 01:54:24 +12:00
|
|
|
|
private DateTime deactivatedTime = DateTime.MinValue;
|
2021-11-10 03:12:52 +13:00
|
|
|
|
private DateTime dateTimeLastOpening = DateTime.MinValue;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
private OpenCloseState openCloseState = OpenCloseState.Default;
|
2021-04-17 12:39:48 +12:00
|
|
|
|
private bool showingMessageBox;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
private TaskbarPosition taskbarPosition = new WindowsTaskbar().Position;
|
2021-04-17 12:39:48 +12:00
|
|
|
|
private bool searchTextChanging;
|
2021-10-29 03:29:04 +13:00
|
|
|
|
private bool waitingForReactivate;
|
2021-12-31 00:36:00 +13:00
|
|
|
|
private int lastMouseDownRowIndex = -1;
|
2021-11-26 11:49:50 +13:00
|
|
|
|
private bool showMenuAfterMainPreload;
|
2021-12-31 00:36:00 +13:00
|
|
|
|
private int dragSwipeScrollingStartRowIndex = -1;
|
|
|
|
|
private bool isDraggingSwipeScrolling;
|
|
|
|
|
private bool isDragSwipeScrolled;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
|
|
|
|
|
public Menus()
|
|
|
|
|
{
|
|
|
|
|
workerMainMenu.WorkerSupportsCancellation = true;
|
|
|
|
|
workerMainMenu.DoWork += LoadMenu;
|
|
|
|
|
|
|
|
|
|
workerMainMenu.RunWorkerCompleted += LoadMainMenuCompleted;
|
|
|
|
|
void LoadMainMenuCompleted(object sender, RunWorkerCompletedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
keyboardInput.ResetSelectedByKey();
|
|
|
|
|
LoadStopped();
|
2021-11-11 11:39:52 +13:00
|
|
|
|
|
|
|
|
|
if (e.Result == null)
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
2021-11-11 11:39:52 +13:00
|
|
|
|
// Clean up menu status IsMenuOpen for previous one
|
|
|
|
|
DataGridView dgvMainMenu = menus[0].GetDataGridView();
|
|
|
|
|
foreach (DataRow row in ((DataTable)dgvMainMenu.DataSource).Rows)
|
|
|
|
|
{
|
|
|
|
|
RowData rowDataToClear = (RowData)row[2];
|
|
|
|
|
rowDataToClear.IsMenuOpen = false;
|
|
|
|
|
rowDataToClear.IsSelected = false;
|
|
|
|
|
rowDataToClear.IsContextMenuOpen = false;
|
|
|
|
|
}
|
2020-09-27 01:54:24 +12:00
|
|
|
|
|
2021-11-11 11:39:52 +13:00
|
|
|
|
RefreshSelection(dgvMainMenu);
|
2020-09-27 01:54:24 +12:00
|
|
|
|
|
2021-11-29 01:40:42 +13:00
|
|
|
|
if (Properties.Settings.Default.CacheMainMenu &&
|
|
|
|
|
Properties.Settings.Default.AppearAtMouseLocation)
|
2021-11-21 07:45:41 +13:00
|
|
|
|
{
|
|
|
|
|
menus[0].Tag = null;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-11 11:39:52 +13:00
|
|
|
|
AsEnumerable.ToList().ForEach(m => { m.ShowWithFade(); });
|
|
|
|
|
menus[0].ResetSearchText();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
MenuData menuData = (MenuData)e.Result;
|
|
|
|
|
switch (menuData.Validity)
|
|
|
|
|
{
|
|
|
|
|
case MenuDataValidity.Valid:
|
2021-11-13 20:18:33 +13:00
|
|
|
|
if (Properties.Settings.Default.CacheMainMenu)
|
|
|
|
|
{
|
|
|
|
|
if (IconReader.MainPreload)
|
|
|
|
|
{
|
|
|
|
|
workerMainMenu.DoWork -= LoadMenu;
|
|
|
|
|
menus[0] = Create(menuData, Path.GetFileName(Config.Path));
|
|
|
|
|
IconReader.MainPreload = false;
|
2021-11-26 11:49:50 +13:00
|
|
|
|
|
|
|
|
|
if (showMenuAfterMainPreload)
|
|
|
|
|
{
|
|
|
|
|
AsEnumerable.ToList().ForEach(m => { m.ShowWithFade(); });
|
|
|
|
|
}
|
2021-11-13 20:18:33 +13:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
AsEnumerable.ToList().ForEach(m => { m.ShowWithFade(); });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
2021-11-11 11:39:52 +13:00
|
|
|
|
{
|
|
|
|
|
DisposeMenu(menus[menuData.Level]);
|
|
|
|
|
menus[0] = Create(menuData, Path.GetFileName(Config.Path));
|
2021-11-14 01:55:01 +13:00
|
|
|
|
|
|
|
|
|
if (IconReader.MainPreload)
|
|
|
|
|
{
|
|
|
|
|
IconReader.MainPreload = false;
|
2021-11-26 11:49:50 +13:00
|
|
|
|
|
|
|
|
|
if (showMenuAfterMainPreload)
|
|
|
|
|
{
|
|
|
|
|
AsEnumerable.ToList().ForEach(m => { m.ShowWithFade(); });
|
|
|
|
|
}
|
2021-11-14 01:55:01 +13:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
AsEnumerable.ToList().ForEach(m => { m.ShowWithFade(); });
|
|
|
|
|
}
|
2021-11-11 11:39:52 +13:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
case MenuDataValidity.Empty:
|
2022-01-08 03:49:33 +13:00
|
|
|
|
IconReader.MainPreload = false;
|
2021-11-11 11:39:52 +13:00
|
|
|
|
if (!showingMessageBox)
|
|
|
|
|
{
|
|
|
|
|
showingMessageBox = true;
|
|
|
|
|
MessageBox.Show(Translator.GetText(
|
|
|
|
|
"MessageRootFolderEmpty"));
|
|
|
|
|
OpenFolder();
|
|
|
|
|
Config.SetFolderByUser();
|
|
|
|
|
showingMessageBox = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
case MenuDataValidity.NoAccess:
|
2022-01-08 03:49:33 +13:00
|
|
|
|
IconReader.MainPreload = false;
|
2021-11-11 11:39:52 +13:00
|
|
|
|
if (!showingMessageBox)
|
|
|
|
|
{
|
|
|
|
|
showingMessageBox = true;
|
|
|
|
|
MessageBox.Show(Translator.GetText(
|
|
|
|
|
"MessageRootFolderNoAccess"));
|
|
|
|
|
OpenFolder();
|
|
|
|
|
Config.SetFolderByUser();
|
|
|
|
|
showingMessageBox = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
case MenuDataValidity.AbortedOrUnknown:
|
|
|
|
|
Log.Info("MenuDataValidity.AbortedOrUnknown");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
2021-11-10 03:12:52 +13:00
|
|
|
|
|
|
|
|
|
openCloseState = OpenCloseState.Default;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
waitToOpenMenu.StopLoadMenu += WaitToOpenMenu_StopLoadMenu;
|
|
|
|
|
void WaitToOpenMenu_StopLoadMenu()
|
|
|
|
|
{
|
|
|
|
|
foreach (BackgroundWorker workerSubMenu in workersSubMenu.
|
|
|
|
|
Where(w => w.IsBusy))
|
|
|
|
|
{
|
|
|
|
|
workerSubMenu.CancelAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LoadStopped();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
waitToOpenMenu.StartLoadMenu += StartLoadMenu;
|
|
|
|
|
void StartLoadMenu(RowData rowData)
|
|
|
|
|
{
|
|
|
|
|
if (menus[0].IsUsable &&
|
|
|
|
|
(menus[rowData.MenuLevel + 1] == null ||
|
|
|
|
|
menus[rowData.MenuLevel + 1].Tag as RowData != rowData))
|
|
|
|
|
{
|
2021-10-04 07:24:22 +13:00
|
|
|
|
CreateAndShowLoadingMenu(rowData);
|
|
|
|
|
void CreateAndShowLoadingMenu(RowData rowData)
|
|
|
|
|
{
|
2021-11-17 12:13:46 +13:00
|
|
|
|
MenuData menuDataLoading = new()
|
2021-10-04 07:24:22 +13:00
|
|
|
|
{
|
|
|
|
|
RowDatas = new List<RowData>(),
|
|
|
|
|
Validity = MenuDataValidity.Valid,
|
|
|
|
|
Level = rowData.MenuLevel + 1,
|
|
|
|
|
};
|
|
|
|
|
|
2021-12-10 08:00:33 +13:00
|
|
|
|
Menu menuLoading = Create(menuDataLoading, Path.GetFileName(rowData.TargetFilePathOrig));
|
2021-10-04 07:24:22 +13:00
|
|
|
|
menuLoading.IsLoadingMenu = true;
|
|
|
|
|
AdjustMenusSizeAndLocation();
|
|
|
|
|
menus[rowData.MenuLevel + 1] = menuLoading;
|
|
|
|
|
menuLoading.Tag = menuDataLoading.RowDataParent = rowData;
|
|
|
|
|
menuDataLoading.RowDataParent.SubMenu = menuLoading;
|
|
|
|
|
menuLoading.SetTypeLoading();
|
|
|
|
|
ShowSubMenu(menuLoading);
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-27 01:54:24 +12:00
|
|
|
|
BackgroundWorker workerSubMenu = workersSubMenu.
|
|
|
|
|
Where(w => !w.IsBusy).FirstOrDefault();
|
|
|
|
|
if (workerSubMenu == null)
|
|
|
|
|
{
|
|
|
|
|
workerSubMenu = new BackgroundWorker
|
|
|
|
|
{
|
|
|
|
|
WorkerSupportsCancellation = true,
|
|
|
|
|
};
|
|
|
|
|
workerSubMenu.DoWork += LoadMenu;
|
|
|
|
|
workerSubMenu.RunWorkerCompleted += LoadSubMenuCompleted;
|
|
|
|
|
workersSubMenu.Add(workerSubMenu);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
workerSubMenu.RunWorkerAsync(rowData);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LoadSubMenuCompleted(object senderCompleted, RunWorkerCompletedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
MenuData menuData = (MenuData)e.Result;
|
2021-10-05 04:47:39 +13:00
|
|
|
|
|
|
|
|
|
Menu menuLoading = menus[menuData.Level];
|
2021-12-10 08:00:33 +13:00
|
|
|
|
string userSearchText = string.Empty;
|
2022-02-05 03:49:45 +13:00
|
|
|
|
bool closedLoadingMenu = false;
|
2021-10-05 04:47:39 +13:00
|
|
|
|
if (menuLoading != null && menuLoading.IsLoadingMenu)
|
2021-10-04 07:24:22 +13:00
|
|
|
|
{
|
2021-10-07 10:22:58 +13:00
|
|
|
|
menuLoading.HideWithFade();
|
2022-02-05 03:49:45 +13:00
|
|
|
|
userSearchText = menuLoading.GetSearchText();
|
2021-10-07 10:22:58 +13:00
|
|
|
|
menus[menuLoading.Level] = null;
|
2022-02-05 03:49:45 +13:00
|
|
|
|
closedLoadingMenu = true;
|
2021-10-04 07:24:22 +13:00
|
|
|
|
}
|
2021-10-05 04:47:39 +13:00
|
|
|
|
|
|
|
|
|
if (menuData.Validity != MenuDataValidity.AbortedOrUnknown &&
|
|
|
|
|
menus[0].IsUsable)
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
|
|
|
|
Menu menu = Create(menuData);
|
|
|
|
|
switch (menuData.Validity)
|
|
|
|
|
{
|
|
|
|
|
case MenuDataValidity.Valid:
|
|
|
|
|
menu.SetTypeSub();
|
|
|
|
|
break;
|
|
|
|
|
case MenuDataValidity.Empty:
|
|
|
|
|
menu.SetTypeEmpty();
|
|
|
|
|
break;
|
|
|
|
|
case MenuDataValidity.NoAccess:
|
|
|
|
|
menu.SetTypeNoAccess();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
menu.Tag = menuData.RowDataParent;
|
|
|
|
|
menuData.RowDataParent.SubMenu = menu;
|
|
|
|
|
if (menus[0].IsUsable)
|
|
|
|
|
{
|
2021-12-10 08:00:33 +13:00
|
|
|
|
if (!string.IsNullOrEmpty(userSearchText))
|
|
|
|
|
{
|
|
|
|
|
menu.SetSearchText(userSearchText);
|
|
|
|
|
}
|
2022-02-05 03:49:45 +13:00
|
|
|
|
|
|
|
|
|
ShowSubMenu(menu);
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-02-05 03:49:45 +13:00
|
|
|
|
else if (closedLoadingMenu && menus[0].IsUsable)
|
|
|
|
|
{
|
|
|
|
|
menuData.RowDataParent.IsSelected = false;
|
|
|
|
|
menuData.RowDataParent.IsMenuOpen = false;
|
|
|
|
|
RefreshSelection(menus[menuLoading.Level - 1].GetDataGridView());
|
|
|
|
|
}
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
waitToOpenMenu.CloseMenu += CloseMenu;
|
|
|
|
|
void CloseMenu(int level)
|
|
|
|
|
{
|
2021-10-11 04:33:54 +13:00
|
|
|
|
if (level < menus.Length && menus[level] != null)
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
|
|
|
|
HideOldMenu(menus[level]);
|
|
|
|
|
}
|
2021-05-14 22:22:15 +12:00
|
|
|
|
|
2021-10-11 04:33:54 +13:00
|
|
|
|
if (level - 1 < menus.Length && menus[level - 1] != null)
|
2021-05-14 22:22:15 +12:00
|
|
|
|
{
|
|
|
|
|
menus[level - 1].FocusTextBox();
|
|
|
|
|
}
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
waitToOpenMenu.MouseEnterOk += MouseEnterOk;
|
|
|
|
|
void MouseEnterOk(DataGridView dgv, int rowIndex)
|
|
|
|
|
{
|
|
|
|
|
if (menus[0].IsUsable)
|
|
|
|
|
{
|
|
|
|
|
if (keyboardInput.InUse)
|
|
|
|
|
{
|
|
|
|
|
keyboardInput.ClearIsSelectedByKey();
|
|
|
|
|
keyboardInput.InUse = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
keyboardInput.Select(dgv, rowIndex, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dgvMouseRow.RowMouseEnter += waitToOpenMenu.MouseEnter;
|
|
|
|
|
dgvMouseRow.RowMouseLeave += waitToOpenMenu.MouseLeave;
|
2021-11-24 11:08:19 +13:00
|
|
|
|
dgvMouseRow.RowMouseLeave += Dgv_RowMouseLeave;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
|
|
|
|
|
keyboardInput = new KeyboardInput(menus);
|
|
|
|
|
keyboardInput.RegisterHotKey();
|
2021-10-26 05:55:34 +13:00
|
|
|
|
keyboardInput.HotKeyPressed += () => SwitchOpenClose(false);
|
2020-09-27 01:54:24 +12:00
|
|
|
|
keyboardInput.ClosePressed += MenusFadeOut;
|
|
|
|
|
keyboardInput.RowDeselected += waitToOpenMenu.RowDeselected;
|
|
|
|
|
keyboardInput.EnterPressed += waitToOpenMenu.EnterOpensInstantly;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
keyboardInput.RowSelected += waitToOpenMenu.RowSelected;
|
|
|
|
|
keyboardInput.RowSelected += AdjustScrollbarToDisplayedRow;
|
|
|
|
|
void AdjustScrollbarToDisplayedRow(DataGridView dgv, int index)
|
|
|
|
|
{
|
2021-06-26 23:24:56 +12:00
|
|
|
|
Menu menu = (Menu)dgv.FindForm();
|
2021-06-03 22:52:47 +12:00
|
|
|
|
menu.AdjustScrollbar();
|
|
|
|
|
}
|
2020-09-27 01:54:24 +12:00
|
|
|
|
|
2021-10-27 09:09:40 +13:00
|
|
|
|
timerShowProcessStartedAsLoadingIcon.Interval = Properties.Settings.Default.TimeUntilClosesAfterEnterPressed;
|
2021-10-29 03:29:04 +13:00
|
|
|
|
timerStillActiveCheck.Interval = Properties.Settings.Default.TimeUntilClosesAfterEnterPressed + 20;
|
2021-10-27 09:09:40 +13:00
|
|
|
|
timerStillActiveCheck.Tick += (sender, e) => StillActiveTick();
|
|
|
|
|
void StillActiveTick()
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
|
|
|
|
if (!IsActive())
|
|
|
|
|
{
|
|
|
|
|
FadeHalfOrOutIfNeeded();
|
|
|
|
|
}
|
2021-10-29 03:29:04 +13:00
|
|
|
|
|
|
|
|
|
timerStillActiveCheck.Stop();
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-26 05:55:34 +13:00
|
|
|
|
waitLeave.LeaveTriggered += FadeHalfOrOutIfNeeded;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal event EventHandlerEmpty LoadStarted;
|
|
|
|
|
|
|
|
|
|
internal event EventHandlerEmpty LoadStopped;
|
|
|
|
|
|
|
|
|
|
private enum OpenCloseState
|
|
|
|
|
{
|
|
|
|
|
Default,
|
|
|
|
|
Opening,
|
|
|
|
|
Closing,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private IEnumerable<Menu> AsEnumerable => menus.Where(m => m != null && !m.IsDisposed);
|
|
|
|
|
|
|
|
|
|
private List<Menu> AsList => AsEnumerable.ToList();
|
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
workerMainMenu.Dispose();
|
|
|
|
|
foreach (BackgroundWorker worker in workersSubMenu)
|
|
|
|
|
{
|
|
|
|
|
worker.Dispose();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
waitToOpenMenu.Dispose();
|
|
|
|
|
keyboardInput.Dispose();
|
2021-10-26 08:45:49 +13:00
|
|
|
|
timerShowProcessStartedAsLoadingIcon.Dispose();
|
2020-09-27 01:54:24 +12:00
|
|
|
|
timerStillActiveCheck.Dispose();
|
|
|
|
|
waitLeave.Dispose();
|
|
|
|
|
IconReader.Dispose();
|
|
|
|
|
DisposeMenu(menus[0]);
|
|
|
|
|
dgvMouseRow.Dispose();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal static MenuData GetData(BackgroundWorker worker, string path, int level)
|
|
|
|
|
{
|
2021-11-17 12:13:46 +13:00
|
|
|
|
MenuData menuData = new()
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
|
|
|
|
RowDatas = new List<RowData>(),
|
|
|
|
|
Validity = MenuDataValidity.AbortedOrUnknown,
|
|
|
|
|
Level = level,
|
|
|
|
|
};
|
2021-11-11 11:39:52 +13:00
|
|
|
|
|
|
|
|
|
string[] directoriesToAddToMainMenu = Array.Empty<string>();
|
|
|
|
|
string[] filesToAddToMainMenu = Array.Empty<string>();
|
|
|
|
|
if (level == 0)
|
|
|
|
|
{
|
|
|
|
|
AddFoldersToMainMenu(ref directoriesToAddToMainMenu, ref filesToAddToMainMenu);
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-27 01:54:24 +12:00
|
|
|
|
if (!worker.CancellationPending)
|
|
|
|
|
{
|
|
|
|
|
string[] directories = Array.Empty<string>();
|
2021-12-13 04:52:40 +13:00
|
|
|
|
bool isSharedDirectory = false;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
2021-05-21 06:36:59 +12:00
|
|
|
|
if (string.IsNullOrEmpty(path))
|
|
|
|
|
{
|
|
|
|
|
Log.Info($"path is null or empty");
|
|
|
|
|
}
|
|
|
|
|
else if (FileLnk.IsNetworkRoot(path))
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
2021-12-13 04:52:40 +13:00
|
|
|
|
isSharedDirectory = true;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
directories = GetDirectoriesInNetworkLocation(path);
|
|
|
|
|
static string[] GetDirectoriesInNetworkLocation(string networkLocationRootPath)
|
|
|
|
|
{
|
2021-11-17 12:13:46 +13:00
|
|
|
|
List<string> directories = new();
|
|
|
|
|
Process cmd = new();
|
2020-09-27 01:54:24 +12:00
|
|
|
|
cmd.StartInfo.FileName = "cmd.exe";
|
|
|
|
|
cmd.StartInfo.RedirectStandardInput = true;
|
|
|
|
|
cmd.StartInfo.RedirectStandardOutput = true;
|
|
|
|
|
cmd.StartInfo.CreateNoWindow = true;
|
|
|
|
|
cmd.StartInfo.UseShellExecute = false;
|
|
|
|
|
cmd.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
|
|
|
|
cmd.Start();
|
|
|
|
|
cmd.StandardInput.WriteLine($"net view {networkLocationRootPath}");
|
|
|
|
|
cmd.StandardInput.Flush();
|
|
|
|
|
cmd.StandardInput.Close();
|
|
|
|
|
|
|
|
|
|
string output = cmd.StandardOutput.ReadToEnd();
|
|
|
|
|
|
|
|
|
|
cmd.WaitForExit();
|
|
|
|
|
cmd.Close();
|
|
|
|
|
|
|
|
|
|
bool resolvedSomething = false;
|
|
|
|
|
|
|
|
|
|
List<string> lines = output
|
|
|
|
|
.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
|
|
|
|
if (lines.Count > 8)
|
|
|
|
|
{
|
|
|
|
|
foreach (string line in lines.Skip(6).SkipLast(2))
|
|
|
|
|
{
|
2020-10-25 09:31:56 +13:00
|
|
|
|
int indexOfFirstSpace = line.IndexOf(" ", StringComparison.InvariantCulture);
|
2020-09-27 01:54:24 +12:00
|
|
|
|
if (indexOfFirstSpace > 0)
|
|
|
|
|
{
|
|
|
|
|
string directory = Path.Combine(
|
2020-10-25 00:12:59 +13:00
|
|
|
|
networkLocationRootPath,
|
2021-12-12 02:34:28 +13:00
|
|
|
|
line[..indexOfFirstSpace]);
|
2020-10-25 00:12:59 +13:00
|
|
|
|
|
2020-09-27 03:00:41 +13:00
|
|
|
|
directories.Add(directory);
|
|
|
|
|
resolvedSomething = true;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!resolvedSomething)
|
|
|
|
|
{
|
|
|
|
|
Log.Info($"Could not resolve network root folder: {networkLocationRootPath} , output:{output}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return directories.ToArray();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
directories = Directory.GetDirectories(path);
|
2021-11-11 11:39:52 +13:00
|
|
|
|
directories = directories.Concat(directoriesToAddToMainMenu).ToArray();
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Array.Sort(directories, new WindowsExplorerSort());
|
|
|
|
|
}
|
|
|
|
|
catch (UnauthorizedAccessException ex)
|
|
|
|
|
{
|
|
|
|
|
Log.Warn($"path:'{path}'", ex);
|
|
|
|
|
menuData.Validity = MenuDataValidity.NoAccess;
|
|
|
|
|
}
|
2021-09-30 09:21:02 +13:00
|
|
|
|
catch (Exception ex)
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
|
|
|
|
Log.Warn($"path:'{path}'", ex);
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-21 06:36:59 +12:00
|
|
|
|
foreach (string directoryWithIllegalCharacters in directories)
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
|
|
|
|
if (worker != null && worker.CancellationPending)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-21 06:36:59 +12:00
|
|
|
|
// https://github.com/Hofknecht/SystemTrayMenu/issues/171
|
|
|
|
|
string directory = directoryWithIllegalCharacters.Replace("\x00", string.Empty);
|
|
|
|
|
|
2020-09-27 01:54:24 +12:00
|
|
|
|
bool hiddenEntry = false;
|
2021-12-13 04:52:40 +13:00
|
|
|
|
if (!isSharedDirectory &&
|
|
|
|
|
FolderOptions.IsHidden(directory, ref hiddenEntry))
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-02 00:37:33 +13:00
|
|
|
|
RowData rowData = ReadRowData(directory, false, true);
|
2020-09-27 01:54:24 +12:00
|
|
|
|
rowData.HiddenEntry = hiddenEntry;
|
|
|
|
|
string resolvedLnkPath = string.Empty;
|
2021-11-19 09:12:03 +13:00
|
|
|
|
rowData.ReadIcon(true, ref resolvedLnkPath, level);
|
2020-09-27 01:54:24 +12:00
|
|
|
|
rowData.MenuLevel = level;
|
|
|
|
|
menuData.RowDatas.Add(rowData);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!worker.CancellationPending)
|
|
|
|
|
{
|
|
|
|
|
string[] files = Array.Empty<string>();
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
2021-05-21 06:36:59 +12:00
|
|
|
|
if (string.IsNullOrEmpty(path))
|
|
|
|
|
{
|
|
|
|
|
Log.Info($"path is null or empty");
|
|
|
|
|
}
|
|
|
|
|
else if (!FileLnk.IsNetworkRoot(path))
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
|
|
|
|
files = Directory.GetFiles(path);
|
2021-11-11 11:39:52 +13:00
|
|
|
|
files = files.Concat(filesToAddToMainMenu).ToArray();
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Array.Sort(files, new WindowsExplorerSort());
|
|
|
|
|
}
|
|
|
|
|
catch (UnauthorizedAccessException ex)
|
|
|
|
|
{
|
|
|
|
|
Log.Warn($"path:'{path}'", ex);
|
|
|
|
|
menuData.Validity = MenuDataValidity.NoAccess;
|
|
|
|
|
}
|
2021-09-30 09:21:02 +13:00
|
|
|
|
catch (Exception ex)
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
|
|
|
|
Log.Warn($"path:'{path}'", ex);
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-22 01:40:43 +12:00
|
|
|
|
foreach (string fileWithIllegalCharacters in files)
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
|
|
|
|
if (worker != null && worker.CancellationPending)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-22 01:40:43 +12:00
|
|
|
|
// https://github.com/Hofknecht/SystemTrayMenu/issues/171
|
|
|
|
|
string file = fileWithIllegalCharacters.Replace("\x00", string.Empty);
|
|
|
|
|
|
2020-09-27 01:54:24 +12:00
|
|
|
|
bool hiddenEntry = false;
|
|
|
|
|
if (FolderOptions.IsHidden(file, ref hiddenEntry))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-02 00:37:33 +13:00
|
|
|
|
RowData rowData = ReadRowData(file, false, false);
|
2022-01-08 00:40:55 +13:00
|
|
|
|
rowData.HiddenEntry = hiddenEntry;
|
2022-01-08 23:39:23 +13:00
|
|
|
|
if (Properties.Settings.Default.ShowOnlyAsSearchResult)
|
|
|
|
|
{
|
|
|
|
|
rowData.ShowOnlyWhenSearch = filesToAddToMainMenu.Contains(fileWithIllegalCharacters);
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-27 01:54:24 +12:00
|
|
|
|
string resolvedLnkPath = string.Empty;
|
2021-11-19 09:12:03 +13:00
|
|
|
|
if (rowData.ReadIcon(false, ref resolvedLnkPath, level))
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
2022-01-02 00:37:33 +13:00
|
|
|
|
rowData = ReadRowData(resolvedLnkPath, true, true, rowData);
|
2020-09-27 01:54:24 +12:00
|
|
|
|
rowData.HiddenEntry = hiddenEntry;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
menuData.RowDatas.Add(rowData);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!worker.CancellationPending)
|
|
|
|
|
{
|
|
|
|
|
if (menuData.Validity == MenuDataValidity.AbortedOrUnknown)
|
|
|
|
|
{
|
|
|
|
|
if (menuData.RowDatas.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
menuData.Validity = MenuDataValidity.Empty;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
menuData.Validity = MenuDataValidity.Valid;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return menuData;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-10 05:41:39 +13:00
|
|
|
|
internal void SwitchOpenCloseByTaskbarItem()
|
|
|
|
|
{
|
|
|
|
|
SwitchOpenClose(true);
|
|
|
|
|
timerStillActiveCheck.Start();
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-26 05:55:34 +13:00
|
|
|
|
internal bool IsOpenCloseStateOpening()
|
|
|
|
|
{
|
2022-02-05 02:34:32 +13:00
|
|
|
|
return openCloseState == OpenCloseState.Opening;
|
2021-10-26 05:55:34 +13:00
|
|
|
|
}
|
|
|
|
|
|
2021-11-24 11:48:59 +13:00
|
|
|
|
internal void SwitchOpenClose(bool byClick, bool isMainPreload = false)
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
2021-11-24 11:48:59 +13:00
|
|
|
|
// Ignore open close events during main preload #248
|
|
|
|
|
if (IconReader.MainPreload && !isMainPreload)
|
|
|
|
|
{
|
2021-11-26 11:49:50 +13:00
|
|
|
|
showMenuAfterMainPreload = true;
|
2021-11-24 11:48:59 +13:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-27 01:54:24 +12:00
|
|
|
|
waitToOpenMenu.MouseActive = byClick;
|
2021-06-26 23:24:56 +12:00
|
|
|
|
if (byClick &&
|
|
|
|
|
!Config.AlwaysOpenByPin &&
|
|
|
|
|
(DateTime.Now - deactivatedTime).TotalMilliseconds < 200)
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
|
|
|
|
// By click on notifyicon the menu gets deactivated and closed
|
|
|
|
|
}
|
|
|
|
|
else if (string.IsNullOrEmpty(Config.Path))
|
|
|
|
|
{
|
|
|
|
|
// Case when Folder Dialog open
|
|
|
|
|
}
|
|
|
|
|
else if (openCloseState == OpenCloseState.Opening ||
|
|
|
|
|
(menus[0] != null && menus[0].Visible && openCloseState == OpenCloseState.Default))
|
|
|
|
|
{
|
|
|
|
|
openCloseState = OpenCloseState.Closing;
|
|
|
|
|
MenusFadeOut();
|
|
|
|
|
StopWorker();
|
|
|
|
|
if (!AsEnumerable.Any(m => m.Visible))
|
|
|
|
|
{
|
|
|
|
|
openCloseState = OpenCloseState.Default;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
openCloseState = OpenCloseState.Opening;
|
|
|
|
|
StartWorker();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
deactivatedTime = DateTime.MinValue;
|
2021-11-10 03:12:52 +13:00
|
|
|
|
dateTimeLastOpening = DateTime.Now;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void DisposeMenu(Menu menuToDispose)
|
|
|
|
|
{
|
|
|
|
|
if (menuToDispose != null)
|
|
|
|
|
{
|
|
|
|
|
menuToDispose.MouseWheel -= AdjustMenusSizeAndLocation;
|
|
|
|
|
menuToDispose.MouseLeave -= waitLeave.Start;
|
|
|
|
|
menuToDispose.MouseEnter -= waitLeave.Stop;
|
|
|
|
|
menuToDispose.KeyPress -= keyboardInput.KeyPress;
|
|
|
|
|
menuToDispose.CmdKeyProcessed -= keyboardInput.CmdKeyProcessed;
|
|
|
|
|
menuToDispose.SearchTextChanging -= keyboardInput.SearchTextChanging;
|
|
|
|
|
menuToDispose.SearchTextChanged -= Menu_SearchTextChanged;
|
2021-04-17 12:39:48 +12:00
|
|
|
|
DataGridView dgv = menuToDispose.GetDataGridView();
|
2020-10-10 20:47:30 +13:00
|
|
|
|
if (dgv != null)
|
|
|
|
|
{
|
|
|
|
|
dgv.CellMouseEnter -= dgvMouseRow.CellMouseEnter;
|
|
|
|
|
dgv.CellMouseLeave -= dgvMouseRow.CellMouseLeave;
|
|
|
|
|
dgv.MouseLeave -= dgvMouseRow.MouseLeave;
|
2021-12-30 23:56:34 +13:00
|
|
|
|
dgv.MouseLeave -= Dgv_MouseLeave;
|
2020-10-10 20:47:30 +13:00
|
|
|
|
dgv.MouseMove -= waitToOpenMenu.MouseMove;
|
2021-12-30 23:56:34 +13:00
|
|
|
|
dgv.MouseMove -= Dgv_MouseMove;
|
2020-10-10 20:47:30 +13:00
|
|
|
|
dgv.MouseDown -= Dgv_MouseDown;
|
2021-11-24 11:08:19 +13:00
|
|
|
|
dgv.MouseUp -= Dgv_MouseUp;
|
|
|
|
|
dgv.MouseClick -= Dgv_MouseClick;
|
2020-10-10 20:47:30 +13:00
|
|
|
|
dgv.MouseDoubleClick -= Dgv_MouseDoubleClick;
|
|
|
|
|
dgv.SelectionChanged -= Dgv_SelectionChanged;
|
|
|
|
|
dgv.RowPostPaint -= Dgv_RowPostPaint;
|
|
|
|
|
dgv.ClearSelection();
|
|
|
|
|
|
|
|
|
|
foreach (DataGridViewRow row in dgv.Rows)
|
|
|
|
|
{
|
|
|
|
|
RowData rowData = (RowData)row.Cells[2].Value;
|
|
|
|
|
DisposeMenu(rowData.SubMenu);
|
|
|
|
|
}
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-17 12:39:48 +12:00
|
|
|
|
menuToDispose.Dispose();
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-28 00:22:52 +13:00
|
|
|
|
internal void ReAdjustSizeAndLocation()
|
|
|
|
|
{
|
|
|
|
|
if (menus[0].IsUsable)
|
|
|
|
|
{
|
|
|
|
|
menus[0].Tag = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-27 01:54:24 +12:00
|
|
|
|
internal void MainPreload()
|
|
|
|
|
{
|
2021-11-13 20:18:33 +13:00
|
|
|
|
IconReader.MainPreload = true;
|
|
|
|
|
|
|
|
|
|
timerShowProcessStartedAsLoadingIcon.Tick += Tick;
|
2021-11-29 07:42:35 +13:00
|
|
|
|
timerShowProcessStartedAsLoadingIcon.Interval = 5;
|
2021-11-13 20:18:33 +13:00
|
|
|
|
timerShowProcessStartedAsLoadingIcon.Start();
|
|
|
|
|
void Tick(object sender, EventArgs e)
|
2021-11-11 11:39:52 +13:00
|
|
|
|
{
|
2021-11-13 20:18:33 +13:00
|
|
|
|
timerShowProcessStartedAsLoadingIcon.Tick -= Tick;
|
2021-11-24 11:48:59 +13:00
|
|
|
|
timerShowProcessStartedAsLoadingIcon.Interval = Properties.Settings.Default.TimeUntilClosesAfterEnterPressed;
|
|
|
|
|
SwitchOpenClose(false, true);
|
2021-11-11 11:39:52 +13:00
|
|
|
|
}
|
|
|
|
|
|
2021-11-13 20:18:33 +13:00
|
|
|
|
if (!Properties.Settings.Default.CacheMainMenu)
|
2021-09-24 08:53:46 +12:00
|
|
|
|
{
|
2021-11-13 20:18:33 +13:00
|
|
|
|
DisposeMenu(menus[0]);
|
2021-09-24 08:53:46 +12:00
|
|
|
|
}
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void StartWorker()
|
|
|
|
|
{
|
|
|
|
|
if (!workerMainMenu.IsBusy)
|
|
|
|
|
{
|
|
|
|
|
LoadStarted();
|
|
|
|
|
workerMainMenu.RunWorkerAsync(
|
|
|
|
|
new object[] { Config.Path, 0 });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void StopWorker()
|
|
|
|
|
{
|
|
|
|
|
if (workerMainMenu.IsBusy)
|
|
|
|
|
{
|
|
|
|
|
workerMainMenu.CancelAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-11 11:39:52 +13:00
|
|
|
|
private static void LoadMenu(object senderDoWork, DoWorkEventArgs eDoWork)
|
|
|
|
|
{
|
|
|
|
|
string path = Config.Path;
|
|
|
|
|
int level = 0;
|
|
|
|
|
RowData rowData = eDoWork.Argument as RowData;
|
|
|
|
|
if (rowData != null)
|
|
|
|
|
{
|
|
|
|
|
path = rowData.TargetFilePath;
|
|
|
|
|
level = rowData.MenuLevel + 1;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-11 03:20:24 +13:00
|
|
|
|
if (Properties.Settings.Default.GenerateShortcutsToDrives)
|
|
|
|
|
{
|
|
|
|
|
GenerateDriveShortcuts.Start();
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-11 11:39:52 +13:00
|
|
|
|
MenuData menuData = GetData((BackgroundWorker)senderDoWork, path, level);
|
|
|
|
|
menuData.RowDataParent = rowData;
|
|
|
|
|
eDoWork.Result = menuData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void AddFoldersToMainMenu(ref string[] directoriesToAddToMainMenu, ref string[] filesToAddToMainMenu)
|
|
|
|
|
{
|
|
|
|
|
string pathAddToMainMenu = string.Empty;
|
|
|
|
|
bool recursive = false;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
foreach (string pathAndRecursivString in Properties.Settings.Default.PathsAddToMainMenu.Split(@"|"))
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(pathAndRecursivString))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pathAddToMainMenu = pathAndRecursivString.Split("recursiv:")[0].Trim();
|
|
|
|
|
recursive = pathAndRecursivString.Split("recursiv:")[1].StartsWith("True");
|
|
|
|
|
bool onlyFiles = pathAndRecursivString.Split("onlyFiles:")[1].StartsWith("True");
|
|
|
|
|
|
|
|
|
|
string[] directoriesToConcat = Array.Empty<string>();
|
|
|
|
|
string[] filesToAddToConcat = Array.Empty<string>();
|
|
|
|
|
if (recursive)
|
|
|
|
|
{
|
|
|
|
|
GetDirectoriesAndFilesRecursive(ref directoriesToConcat, ref filesToAddToConcat, pathAddToMainMenu);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
directoriesToConcat = Directory.GetDirectories(pathAddToMainMenu);
|
|
|
|
|
filesToAddToConcat = Directory.GetFiles(pathAddToMainMenu);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!onlyFiles)
|
|
|
|
|
{
|
|
|
|
|
directoriesToAddToMainMenu = directoriesToAddToMainMenu.Concat(directoriesToConcat).ToArray();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
filesToAddToMainMenu = filesToAddToMainMenu.Concat(filesToAddToConcat).ToArray();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Log.Warn($"path:'{pathAddToMainMenu}' recursiv:{recursive}", ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void GetDirectoriesAndFilesRecursive(ref string[] directoriesToConcat, ref string[] filesToAddToConcat, string pathAddToMainMenu)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
string[] directories = Directory.GetDirectories(pathAddToMainMenu);
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
filesToAddToConcat = filesToAddToConcat.Concat(Directory.GetFiles(pathAddToMainMenu)).ToArray();
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Log.Warn($"GetDirectoriesAndFilesRecursive path:'{pathAddToMainMenu}'", ex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (string directory in directories)
|
|
|
|
|
{
|
|
|
|
|
GetDirectoriesAndFilesRecursive(ref directoriesToConcat, ref filesToAddToConcat, directory);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
directoriesToConcat = directoriesToConcat.Concat(directories).ToArray();
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Log.Warn($"GetDirectoriesAndFilesRecursive path:'{pathAddToMainMenu}'", ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-02 00:37:33 +13:00
|
|
|
|
private static RowData ReadRowData(string fileName, bool isResolvedLnk, bool containsMenu, RowData rowData = null)
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
|
|
|
|
if (rowData == null)
|
|
|
|
|
{
|
|
|
|
|
rowData = new RowData();
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-02 00:37:33 +13:00
|
|
|
|
rowData.ContainsMenu = containsMenu;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
rowData.IsResolvedLnk = isResolvedLnk;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
rowData.FileInfo = new FileInfo(fileName);
|
|
|
|
|
rowData.TargetFilePath = rowData.FileInfo.FullName;
|
|
|
|
|
if (!isResolvedLnk)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(rowData.FileInfo.Name))
|
|
|
|
|
{
|
|
|
|
|
string path = rowData.FileInfo.FullName;
|
|
|
|
|
int directoryNameBegin = path.LastIndexOf(@"\", StringComparison.InvariantCulture) + 1;
|
2021-10-11 04:33:54 +13:00
|
|
|
|
rowData.SetText(path[directoryNameBegin..]);
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
2022-01-02 00:37:33 +13:00
|
|
|
|
else if (!rowData.ContainsMenu && Config.IsHideFileExtension())
|
|
|
|
|
{
|
|
|
|
|
rowData.SetText(Path.GetFileNameWithoutExtension(rowData.FileInfo.Name));
|
|
|
|
|
}
|
2020-09-27 01:54:24 +12:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rowData.SetText(rowData.FileInfo.Name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rowData.TargetFilePathOrig = rowData.FileInfo.FullName;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
2021-09-30 09:21:02 +13:00
|
|
|
|
Log.Warn($"fileName:'{fileName}'", ex);
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return rowData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static bool IsActive()
|
|
|
|
|
{
|
2021-11-10 05:41:39 +13:00
|
|
|
|
return Form.ActiveForm is Menu ||
|
|
|
|
|
Form.ActiveForm is UserInterface.TaskbarForm;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-06-26 23:24:56 +12:00
|
|
|
|
private static void OpenFolder(string pathToFolder = "")
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
2021-06-26 23:24:56 +12:00
|
|
|
|
string path = pathToFolder;
|
|
|
|
|
if (string.IsNullOrEmpty(path))
|
|
|
|
|
{
|
|
|
|
|
path = Config.Path;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Log.ProcessStart(path);
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Menu Create(MenuData menuData, string title = null)
|
|
|
|
|
{
|
2021-11-17 12:13:46 +13:00
|
|
|
|
Menu menu = new();
|
2020-09-27 01:54:24 +12:00
|
|
|
|
|
2021-06-28 00:44:12 +12:00
|
|
|
|
string path = Config.Path;
|
|
|
|
|
if (title == null)
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
2021-06-28 00:44:12 +12:00
|
|
|
|
title = Path.GetFileName(menuData.RowDataParent.TargetFilePath);
|
|
|
|
|
path = menuData.RowDataParent.TargetFilePath;
|
|
|
|
|
}
|
2020-09-27 01:54:24 +12:00
|
|
|
|
|
2021-06-28 00:44:12 +12:00
|
|
|
|
if (string.IsNullOrEmpty(title))
|
|
|
|
|
{
|
|
|
|
|
title = Path.GetPathRoot(path);
|
2021-06-26 23:24:56 +12:00
|
|
|
|
}
|
2021-06-28 00:44:12 +12:00
|
|
|
|
|
|
|
|
|
menu.SetTitle(title);
|
2021-10-26 05:55:34 +13:00
|
|
|
|
menu.UserClickedOpenFolder += () => OpenFolder(path);
|
2020-09-27 01:54:24 +12:00
|
|
|
|
menu.Level = menuData.Level;
|
|
|
|
|
menu.MouseWheel += AdjustMenusSizeAndLocation;
|
|
|
|
|
menu.MouseLeave += waitLeave.Start;
|
|
|
|
|
menu.MouseEnter += waitLeave.Stop;
|
|
|
|
|
menu.KeyPress += keyboardInput.KeyPress;
|
|
|
|
|
menu.CmdKeyProcessed += keyboardInput.CmdKeyProcessed;
|
2020-10-10 20:47:30 +13:00
|
|
|
|
menu.SearchTextChanging += Menu_SearchTextChanging;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
menu.SearchTextChanged += Menu_SearchTextChanged;
|
2021-11-25 07:01:59 +13:00
|
|
|
|
menu.UserDragsMenu += Menu_UserDragsMenu;
|
|
|
|
|
void Menu_UserDragsMenu()
|
|
|
|
|
{
|
|
|
|
|
if (menus[1] != null)
|
|
|
|
|
{
|
|
|
|
|
HideOldMenu(menus[1]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-27 01:54:24 +12:00
|
|
|
|
menu.Deactivate += Deactivate;
|
|
|
|
|
void Deactivate(object sender, EventArgs e)
|
|
|
|
|
{
|
2021-11-10 03:12:52 +13:00
|
|
|
|
if (IsOpenCloseStateOpening())
|
|
|
|
|
{
|
|
|
|
|
Log.Info("Ignored Deactivate, because openCloseState == OpenCloseState.Opening");
|
|
|
|
|
}
|
|
|
|
|
else if (!Properties.Settings.Default.StaysOpenWhenFocusLostAfterEnterPressed ||
|
2021-10-29 03:29:04 +13:00
|
|
|
|
!waitingForReactivate)
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
2021-10-27 09:09:40 +13:00
|
|
|
|
FadeHalfOrOutIfNeeded();
|
|
|
|
|
if (!IsActive())
|
|
|
|
|
{
|
|
|
|
|
deactivatedTime = DateTime.Now;
|
|
|
|
|
}
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-27 09:09:40 +13:00
|
|
|
|
menu.Activated += (sender, e) => Activated();
|
|
|
|
|
void Activated()
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
2021-10-27 09:09:40 +13:00
|
|
|
|
if (IsActive() && menus[0].IsUsable)
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
|
|
|
|
AsList.ForEach(m => m.ShowWithFade());
|
2021-10-27 09:09:40 +13:00
|
|
|
|
timerStillActiveCheck.Stop();
|
2020-09-27 01:54:24 +12:00
|
|
|
|
timerStillActiveCheck.Start();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
menu.VisibleChanged += MenuVisibleChanged;
|
2021-06-28 00:44:12 +12:00
|
|
|
|
AddItemsToMenu(menuData.RowDatas, menu, out int foldersCount, out int filesCount);
|
|
|
|
|
static void AddItemsToMenu(List<RowData> data, Menu menu, out int foldersCount, out int filesCount)
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
2021-06-28 00:44:12 +12:00
|
|
|
|
foldersCount = 0;
|
|
|
|
|
filesCount = 0;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
DataGridView dgv = menu.GetDataGridView();
|
2021-11-17 12:13:46 +13:00
|
|
|
|
DataTable dataTable = new();
|
2020-09-27 01:54:24 +12:00
|
|
|
|
dataTable.Columns.Add(dgv.Columns[0].Name, typeof(Icon));
|
|
|
|
|
dataTable.Columns.Add(dgv.Columns[1].Name, typeof(string));
|
|
|
|
|
dataTable.Columns.Add("data", typeof(RowData));
|
2021-04-15 07:06:54 +12:00
|
|
|
|
dataTable.Columns.Add("SortIndex");
|
2020-09-27 01:54:24 +12:00
|
|
|
|
foreach (RowData rowData in data)
|
|
|
|
|
{
|
2022-01-08 23:39:23 +13:00
|
|
|
|
if (!rowData.ShowOnlyWhenSearch)
|
2021-06-28 00:44:12 +12:00
|
|
|
|
{
|
2022-01-08 23:39:23 +13:00
|
|
|
|
if (rowData.ContainsMenu)
|
|
|
|
|
{
|
|
|
|
|
foldersCount++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
filesCount++;
|
|
|
|
|
}
|
2021-06-28 00:44:12 +12:00
|
|
|
|
}
|
|
|
|
|
|
2020-09-27 01:54:24 +12:00
|
|
|
|
rowData.SetData(rowData, dataTable);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dgv.DataSource = dataTable;
|
2021-05-29 19:13:14 +12:00
|
|
|
|
dgv.Columns["data"].Visible = false;
|
2021-06-03 22:52:47 +12:00
|
|
|
|
dgv.Columns["SortIndex"].Visible = false;
|
2022-01-08 23:39:23 +13:00
|
|
|
|
|
|
|
|
|
string columnSortIndex = "SortIndex";
|
|
|
|
|
foreach (DataRow row in dataTable.Rows)
|
|
|
|
|
{
|
|
|
|
|
RowData rowData = (RowData)row[2];
|
|
|
|
|
if (rowData.ShowOnlyWhenSearch)
|
|
|
|
|
{
|
|
|
|
|
row[columnSortIndex] = 99;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
row[columnSortIndex] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DataGridView dgv = menu.GetDataGridView();
|
|
|
|
|
dgv.CellMouseEnter += dgvMouseRow.CellMouseEnter;
|
|
|
|
|
dgv.CellMouseLeave += dgvMouseRow.CellMouseLeave;
|
|
|
|
|
dgv.MouseLeave += dgvMouseRow.MouseLeave;
|
2021-12-30 23:56:34 +13:00
|
|
|
|
dgv.MouseLeave += Dgv_MouseLeave;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
dgv.MouseMove += waitToOpenMenu.MouseMove;
|
2021-12-30 23:56:34 +13:00
|
|
|
|
dgv.MouseMove += Dgv_MouseMove;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
dgv.MouseDown += Dgv_MouseDown;
|
2021-11-24 11:08:19 +13:00
|
|
|
|
dgv.MouseUp += Dgv_MouseUp;
|
|
|
|
|
dgv.MouseClick += Dgv_MouseClick;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
dgv.MouseDoubleClick += Dgv_MouseDoubleClick;
|
|
|
|
|
dgv.SelectionChanged += Dgv_SelectionChanged;
|
|
|
|
|
dgv.RowPostPaint += Dgv_RowPostPaint;
|
2021-06-04 01:00:53 +12:00
|
|
|
|
dgv.DataError += Dgv_DataError;
|
|
|
|
|
void Dgv_DataError(object sender, DataGridViewDataErrorEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
// WARN Dgv_DataError occured System.ObjectDisposedException: Cannot access a disposed object. Object name: 'Icon'
|
|
|
|
|
// => Rare times occured (e.g. when focused an close other application => closed and activated at same time)
|
|
|
|
|
Log.Warn("Dgv_DataError occured", e.Exception);
|
|
|
|
|
}
|
2020-09-27 01:54:24 +12:00
|
|
|
|
|
2021-06-28 00:44:12 +12:00
|
|
|
|
menu.SetCounts(foldersCount, filesCount);
|
|
|
|
|
|
2020-09-27 01:54:24 +12:00
|
|
|
|
return menu;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void MenuVisibleChanged(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
Menu menu = (Menu)sender;
|
|
|
|
|
if (menu.IsUsable)
|
|
|
|
|
{
|
|
|
|
|
AdjustMenusSizeAndLocation();
|
2022-01-08 23:39:23 +13:00
|
|
|
|
|
|
|
|
|
if (menu.Level == 0)
|
|
|
|
|
{
|
|
|
|
|
DataGridView dgv = menu.GetDataGridView();
|
|
|
|
|
((DataTable)dgv.DataSource).DefaultView.RowFilter = "[SortIndex] LIKE '%0%'";
|
2022-01-10 01:33:44 +13:00
|
|
|
|
AdjustMenusSizeAndLocation();
|
2022-01-08 23:39:23 +13:00
|
|
|
|
}
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-11-11 11:39:52 +13:00
|
|
|
|
if (!menu.Visible && menu.Level != 0)
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
|
|
|
|
DisposeMenu(menu);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!AsEnumerable.Any(m => m.Visible))
|
|
|
|
|
{
|
2021-10-07 10:22:58 +13:00
|
|
|
|
if (IconReader.ClearIfCacheTooBig())
|
|
|
|
|
{
|
|
|
|
|
GC.Collect();
|
2021-11-19 09:12:03 +13:00
|
|
|
|
|
|
|
|
|
if (!Properties.Settings.Default.CacheMainMenu)
|
|
|
|
|
{
|
|
|
|
|
MainPreload();
|
|
|
|
|
}
|
2021-10-07 10:22:58 +13:00
|
|
|
|
}
|
2021-10-14 04:13:11 +13:00
|
|
|
|
|
|
|
|
|
openCloseState = OpenCloseState.Default;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-30 23:56:34 +13:00
|
|
|
|
private void Dgv_MouseMove(object sender, MouseEventArgs e)
|
|
|
|
|
{
|
2021-12-31 00:36:00 +13:00
|
|
|
|
if (isDraggingSwipeScrolling)
|
2021-12-30 23:56:34 +13:00
|
|
|
|
{
|
|
|
|
|
DataGridView dgv = (DataGridView)sender;
|
|
|
|
|
int newRow = GetRowUnderCursor(dgv, e.Location);
|
|
|
|
|
if (newRow > -1)
|
|
|
|
|
{
|
2021-12-31 00:36:00 +13:00
|
|
|
|
int delta = dragSwipeScrollingStartRowIndex - newRow;
|
2022-01-10 05:13:10 +13:00
|
|
|
|
if (DoScroll(dgv, ref delta))
|
|
|
|
|
{
|
|
|
|
|
dragSwipeScrollingStartRowIndex += delta;
|
|
|
|
|
}
|
2021-12-30 23:56:34 +13:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-10 05:13:10 +13:00
|
|
|
|
private bool DoScroll(DataGridView dgv, ref int delta)
|
2021-12-30 23:56:34 +13:00
|
|
|
|
{
|
2022-01-10 05:13:10 +13:00
|
|
|
|
bool scrolled = false;
|
2021-12-30 23:56:34 +13:00
|
|
|
|
if (delta != 0)
|
|
|
|
|
{
|
|
|
|
|
if (delta < 0 && dgv.FirstDisplayedScrollingRowIndex == 0)
|
|
|
|
|
{
|
|
|
|
|
delta = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-10 05:13:10 +13:00
|
|
|
|
int newFirstDisplayedScrollingRowIndex = dgv.FirstDisplayedScrollingRowIndex + (delta * 2);
|
|
|
|
|
|
|
|
|
|
if (newFirstDisplayedScrollingRowIndex < 0 || newFirstDisplayedScrollingRowIndex >= dgv.RowCount)
|
|
|
|
|
{
|
|
|
|
|
newFirstDisplayedScrollingRowIndex = dgv.FirstDisplayedScrollingRowIndex + delta;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-30 23:56:34 +13:00
|
|
|
|
if (newFirstDisplayedScrollingRowIndex > -1 && newFirstDisplayedScrollingRowIndex < dgv.RowCount)
|
|
|
|
|
{
|
2021-12-31 00:36:00 +13:00
|
|
|
|
isDragSwipeScrolled = true;
|
2021-12-30 23:56:34 +13:00
|
|
|
|
dgv.FirstDisplayedScrollingRowIndex = newFirstDisplayedScrollingRowIndex;
|
|
|
|
|
Menu menu = (Menu)dgv.FindForm();
|
|
|
|
|
menu.AdjustScrollbar();
|
2022-01-10 05:13:10 +13:00
|
|
|
|
scrolled = dgv.FirstDisplayedScrollingRowIndex == newFirstDisplayedScrollingRowIndex;
|
2021-12-30 23:56:34 +13:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-01-10 05:13:10 +13:00
|
|
|
|
|
|
|
|
|
return scrolled;
|
2021-12-30 23:56:34 +13:00
|
|
|
|
}
|
|
|
|
|
|
2020-09-27 01:54:24 +12:00
|
|
|
|
private void Dgv_MouseDown(object sender, MouseEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
DataGridView dgv = (DataGridView)sender;
|
|
|
|
|
DataGridView.HitTestInfo hitTestInfo;
|
|
|
|
|
hitTestInfo = dgv.HitTest(e.X, e.Y);
|
2021-11-24 12:22:38 +13:00
|
|
|
|
if (hitTestInfo.RowIndex > -1 &&
|
|
|
|
|
hitTestInfo.RowIndex < dgv.Rows.Count)
|
|
|
|
|
{
|
|
|
|
|
RowData rowData = (RowData)dgv.Rows[hitTestInfo.RowIndex].Cells[2].Value;
|
|
|
|
|
rowData.MouseDown(dgv, e);
|
|
|
|
|
}
|
2021-11-24 11:08:19 +13:00
|
|
|
|
|
|
|
|
|
if (e.Button == MouseButtons.Left)
|
|
|
|
|
{
|
2021-12-31 00:36:00 +13:00
|
|
|
|
lastMouseDownRowIndex = hitTestInfo.RowIndex;
|
2021-11-24 11:08:19 +13:00
|
|
|
|
}
|
2021-12-30 23:56:34 +13:00
|
|
|
|
|
2021-12-31 00:36:00 +13:00
|
|
|
|
Menu menu = (Menu)((DataGridView)sender).FindForm();
|
2022-01-09 23:51:21 +13:00
|
|
|
|
if (menu != null && menu.ScrollbarVisible)
|
2021-12-31 00:36:00 +13:00
|
|
|
|
{
|
|
|
|
|
isDraggingSwipeScrolling = true;
|
|
|
|
|
dragSwipeScrollingStartRowIndex = GetRowUnderCursor(dgv, e.Location);
|
|
|
|
|
}
|
2021-12-30 23:56:34 +13:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private int GetRowUnderCursor(DataGridView dgv, Point location)
|
|
|
|
|
{
|
|
|
|
|
DataGridView.HitTestInfo myHitTest = dgv.HitTest(location.X, location.Y);
|
|
|
|
|
return myHitTest.RowIndex;
|
2021-11-24 11:08:19 +13:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Dgv_MouseUp(object sender, MouseEventArgs e)
|
|
|
|
|
{
|
2021-12-31 00:36:00 +13:00
|
|
|
|
lastMouseDownRowIndex = -1;
|
|
|
|
|
isDraggingSwipeScrolling = false;
|
|
|
|
|
isDragSwipeScrolled = false;
|
2021-12-30 23:56:34 +13:00
|
|
|
|
|
|
|
|
|
// In case during mouse down move mouse out of dgv (it has own scrollbehavior) which we need to refresh
|
|
|
|
|
Menu menu = (Menu)((DataGridView)sender).FindForm();
|
|
|
|
|
menu.AdjustScrollbar();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Dgv_MouseLeave(object sender, EventArgs e)
|
|
|
|
|
{
|
2021-12-31 00:36:00 +13:00
|
|
|
|
isDraggingSwipeScrolling = false;
|
|
|
|
|
isDragSwipeScrolled = false;
|
2021-11-24 11:08:19 +13:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Dgv_RowMouseLeave(object sender, DataGridViewCellEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
DataGridView dgv = (DataGridView)sender;
|
|
|
|
|
|
2021-12-31 00:36:00 +13:00
|
|
|
|
if (!isDragSwipeScrolled &&
|
|
|
|
|
e.RowIndex == lastMouseDownRowIndex &&
|
2021-11-24 11:08:19 +13:00
|
|
|
|
e.RowIndex > -1 &&
|
|
|
|
|
e.RowIndex < dgv.Rows.Count)
|
|
|
|
|
{
|
2021-12-31 00:36:00 +13:00
|
|
|
|
lastMouseDownRowIndex = -1;
|
2021-11-24 11:08:19 +13:00
|
|
|
|
RowData rowData = (RowData)dgv.Rows[e.RowIndex].Cells[2].Value;
|
|
|
|
|
string[] files = new string[] { rowData.TargetFilePathOrig };
|
|
|
|
|
|
|
|
|
|
// Update position raises move event which prevent DoDragDrop blocking UI when mouse not moved
|
|
|
|
|
Cursor.Position = new Point(Cursor.Position.X, Cursor.Position.Y);
|
|
|
|
|
|
|
|
|
|
dgv.DoDragDrop(new DataObject(DataFormats.FileDrop, files), DragDropEffects.Copy);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Dgv_MouseClick(object sender, MouseEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
DataGridView dgv = (DataGridView)sender;
|
|
|
|
|
DataGridView.HitTestInfo hitTestInfo;
|
|
|
|
|
hitTestInfo = dgv.HitTest(e.X, e.Y);
|
2022-01-09 11:23:14 +13:00
|
|
|
|
if (!isDragSwipeScrolled &&
|
2021-12-31 00:36:00 +13:00
|
|
|
|
hitTestInfo.RowIndex == lastMouseDownRowIndex &&
|
2021-11-24 11:08:19 +13:00
|
|
|
|
hitTestInfo.RowIndex > -1 &&
|
|
|
|
|
hitTestInfo.RowIndex < dgv.Rows.Count)
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
|
|
|
|
RowData rowData = (RowData)dgv.Rows[hitTestInfo.RowIndex].Cells[2].Value;
|
2021-11-24 12:22:38 +13:00
|
|
|
|
rowData.MouseClick(e, out bool toCloseByClick);
|
2020-09-27 01:54:24 +12:00
|
|
|
|
waitToOpenMenu.ClickOpensInstantly(dgv, hitTestInfo.RowIndex);
|
2021-05-02 23:12:18 +12:00
|
|
|
|
if (toCloseByClick)
|
|
|
|
|
{
|
|
|
|
|
MenusFadeOut();
|
|
|
|
|
}
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
2021-11-24 11:08:19 +13:00
|
|
|
|
|
2021-12-31 00:36:00 +13:00
|
|
|
|
lastMouseDownRowIndex = -1;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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].Cells[2].Value;
|
2021-05-02 23:12:18 +12:00
|
|
|
|
trigger.DoubleClick(e, out bool toCloseByDoubleClick);
|
|
|
|
|
if (toCloseByDoubleClick)
|
|
|
|
|
{
|
|
|
|
|
MenusFadeOut();
|
|
|
|
|
}
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
2021-11-24 11:08:19 +13:00
|
|
|
|
|
2021-12-31 00:36:00 +13:00
|
|
|
|
lastMouseDownRowIndex = -1;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Dgv_SelectionChanged(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
RefreshSelection((DataGridView)sender);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void RefreshSelection(DataGridView dgv)
|
|
|
|
|
{
|
2020-10-10 20:47:30 +13:00
|
|
|
|
dgv.SelectionChanged -= Dgv_SelectionChanged;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
foreach (DataGridViewRow row in dgv.Rows)
|
|
|
|
|
{
|
|
|
|
|
RowData rowData = (RowData)row.Cells[2].Value;
|
|
|
|
|
|
|
|
|
|
if (rowData == null)
|
|
|
|
|
{
|
|
|
|
|
// Case when filtering a previous menu
|
|
|
|
|
}
|
|
|
|
|
else if (!menus[0].IsUsable)
|
|
|
|
|
{
|
|
|
|
|
row.DefaultCellStyle.SelectionBackColor = Color.White;
|
|
|
|
|
row.Selected = false;
|
|
|
|
|
}
|
|
|
|
|
else if (rowData.IsContextMenuOpen || (rowData.IsMenuOpen && rowData.IsSelected))
|
|
|
|
|
{
|
|
|
|
|
row.Selected = true;
|
|
|
|
|
}
|
|
|
|
|
else if (rowData.IsMenuOpen)
|
|
|
|
|
{
|
|
|
|
|
row.Selected = true;
|
|
|
|
|
}
|
|
|
|
|
else if (rowData.IsSelected)
|
|
|
|
|
{
|
|
|
|
|
row.DefaultCellStyle.SelectionBackColor = MenuDefines.ColorSelectedItem;
|
|
|
|
|
row.Selected = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
row.DefaultCellStyle.SelectionBackColor = Color.White;
|
|
|
|
|
row.Selected = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-10 20:47:30 +13:00
|
|
|
|
dgv.SelectionChanged += Dgv_SelectionChanged;
|
|
|
|
|
|
|
|
|
|
if (!searchTextChanging)
|
|
|
|
|
{
|
2021-06-03 22:52:47 +12:00
|
|
|
|
dgv.Invalidate();
|
2020-10-10 20:47:30 +13:00
|
|
|
|
}
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Dgv_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
DataGridView dgv = (DataGridView)sender;
|
|
|
|
|
DataGridViewRow row = dgv.Rows[e.RowIndex];
|
|
|
|
|
|
|
|
|
|
if (row.Selected)
|
|
|
|
|
{
|
|
|
|
|
RowData rowData = (RowData)row.Cells[2].Value;
|
|
|
|
|
|
|
|
|
|
int width = dgv.Columns[0].Width + dgv.Columns[1].Width;
|
2021-11-17 12:13:46 +13:00
|
|
|
|
Rectangle rowBounds = new(0, e.RowBounds.Top, width, e.RowBounds.Height);
|
2020-09-27 01:54:24 +12:00
|
|
|
|
|
|
|
|
|
if (rowData.IsContextMenuOpen || (rowData.IsMenuOpen && rowData.IsSelected))
|
|
|
|
|
{
|
|
|
|
|
ControlPaint.DrawBorder(e.Graphics, rowBounds, MenuDefines.ColorSelectedItemBorder, ButtonBorderStyle.Solid);
|
|
|
|
|
row.DefaultCellStyle.SelectionBackColor = MenuDefines.ColorSelectedItem;
|
|
|
|
|
}
|
|
|
|
|
else if (rowData.IsMenuOpen)
|
|
|
|
|
{
|
|
|
|
|
ControlPaint.DrawBorder(e.Graphics, rowBounds, MenuDefines.ColorOpenFolderBorder, ButtonBorderStyle.Solid);
|
|
|
|
|
row.DefaultCellStyle.SelectionBackColor = MenuDefines.ColorOpenFolder;
|
|
|
|
|
}
|
2021-10-26 08:45:49 +13:00
|
|
|
|
|
|
|
|
|
if (rowData.ProcessStarted)
|
|
|
|
|
{
|
2021-10-29 03:29:04 +13:00
|
|
|
|
waitingForReactivate = true;
|
2021-10-26 08:45:49 +13:00
|
|
|
|
rowData.ProcessStarted = false;
|
|
|
|
|
row.Cells[0].Value = Resources.StaticResources.LoadingIcon;
|
|
|
|
|
timerShowProcessStartedAsLoadingIcon.Tick += Tick;
|
|
|
|
|
void Tick(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
timerShowProcessStartedAsLoadingIcon.Tick -= Tick;
|
|
|
|
|
timerShowProcessStartedAsLoadingIcon.Stop();
|
2021-10-29 03:29:04 +13:00
|
|
|
|
row.Cells[0].Value = rowData.ReadLoadedIcon();
|
|
|
|
|
waitingForReactivate = false;
|
2021-10-26 08:45:49 +13:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-27 09:09:40 +13:00
|
|
|
|
timerShowProcessStartedAsLoadingIcon.Stop();
|
2021-10-26 08:45:49 +13:00
|
|
|
|
timerShowProcessStartedAsLoadingIcon.Start();
|
2021-10-27 09:09:40 +13:00
|
|
|
|
timerStillActiveCheck.Stop();
|
|
|
|
|
timerStillActiveCheck.Start();
|
2021-10-26 08:45:49 +13:00
|
|
|
|
}
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ShowSubMenu(Menu menuToShow)
|
|
|
|
|
{
|
|
|
|
|
HideOldMenu(menuToShow, true);
|
|
|
|
|
|
|
|
|
|
menus[menuToShow.Level] = menuToShow;
|
|
|
|
|
AdjustMenusSizeAndLocation();
|
|
|
|
|
menus[menuToShow.Level].ShowWithFadeOrTransparent(IsActive());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void HideOldMenu(Menu menuToShow, bool keepOrSetIsMenuOpen = false)
|
|
|
|
|
{
|
|
|
|
|
Menu menuPrevious = menus[menuToShow.Level - 1];
|
2021-05-14 01:20:40 +12:00
|
|
|
|
if (menuPrevious != null)
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
2021-05-14 01:20:40 +12:00
|
|
|
|
// Clean up menu status IsMenuOpen for previous one
|
|
|
|
|
DataGridView dgvPrevious = menuPrevious.GetDataGridView();
|
|
|
|
|
foreach (DataRow row in ((DataTable)dgvPrevious.DataSource).Rows)
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
2021-05-14 01:20:40 +12:00
|
|
|
|
RowData rowDataToClear = (RowData)row[2];
|
|
|
|
|
if (rowDataToClear == (RowData)menuToShow.Tag)
|
|
|
|
|
{
|
|
|
|
|
rowDataToClear.IsMenuOpen = keepOrSetIsMenuOpen;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rowDataToClear.IsMenuOpen = false;
|
|
|
|
|
}
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-05-14 01:20:40 +12:00
|
|
|
|
RefreshSelection(dgvPrevious);
|
2020-09-27 01:54:24 +12:00
|
|
|
|
|
2021-05-14 01:20:40 +12:00
|
|
|
|
// Hide old menu
|
|
|
|
|
foreach (Menu menuToClose in menus.Where(
|
|
|
|
|
m => m != null && m.Level > menuPrevious.Level))
|
|
|
|
|
{
|
|
|
|
|
menuToClose.HideWithFade();
|
|
|
|
|
menus[menuToClose.Level] = null;
|
|
|
|
|
}
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void FadeHalfOrOutIfNeeded()
|
|
|
|
|
{
|
2021-11-13 20:18:33 +13:00
|
|
|
|
if (menus[0] != null && menus[0].IsUsable)
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
|
|
|
|
if (!IsActive())
|
|
|
|
|
{
|
|
|
|
|
Point position = Control.MousePosition;
|
2021-05-03 01:21:07 +12:00
|
|
|
|
if (Properties.Settings.Default.StaysOpenWhenFocusLost &&
|
|
|
|
|
AsList.Any(m => m.IsMouseOn(position)))
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
|
|
|
|
if (!keyboardInput.InUse)
|
|
|
|
|
{
|
|
|
|
|
AsList.ForEach(menu => menu.ShowTransparent());
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-06-26 23:24:56 +12:00
|
|
|
|
else if (Config.AlwaysOpenByPin)
|
|
|
|
|
{
|
|
|
|
|
AsList.ForEach(menu => menu.ShowTransparent());
|
|
|
|
|
}
|
2020-09-27 01:54:24 +12:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
MenusFadeOut();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void MenusFadeOut()
|
|
|
|
|
{
|
|
|
|
|
openCloseState = OpenCloseState.Closing;
|
|
|
|
|
AsList.ForEach(menu =>
|
|
|
|
|
{
|
|
|
|
|
if (menu.Level > 0)
|
|
|
|
|
{
|
|
|
|
|
menus[menu.Level] = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
menu.HideWithFade();
|
|
|
|
|
});
|
2021-06-26 23:24:56 +12:00
|
|
|
|
|
|
|
|
|
Config.AlwaysOpenByPin = false;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void AdjustMenusSizeAndLocation()
|
|
|
|
|
{
|
2021-11-10 06:48:30 +13:00
|
|
|
|
Rectangle screenBounds;
|
2021-12-28 00:22:52 +13:00
|
|
|
|
bool isCustomLocationOutsideOfScreen = false;
|
2021-11-10 06:48:30 +13:00
|
|
|
|
if (Properties.Settings.Default.AppearAtMouseLocation)
|
|
|
|
|
{
|
|
|
|
|
screenBounds = Screen.FromPoint(Cursor.Position).Bounds;
|
|
|
|
|
}
|
2021-12-10 08:00:33 +13:00
|
|
|
|
else if (Properties.Settings.Default.UseCustomLocation)
|
|
|
|
|
{
|
|
|
|
|
screenBounds = Screen.FromPoint(new Point(
|
|
|
|
|
Properties.Settings.Default.CustomLocationX,
|
|
|
|
|
Properties.Settings.Default.CustomLocationY)).Bounds;
|
2021-12-28 00:22:52 +13:00
|
|
|
|
|
|
|
|
|
isCustomLocationOutsideOfScreen = !screenBounds.Contains(
|
|
|
|
|
new Point(Properties.Settings.Default.CustomLocationX, Properties.Settings.Default.CustomLocationY));
|
2021-12-10 08:00:33 +13:00
|
|
|
|
}
|
2021-11-10 06:48:30 +13:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
screenBounds = Screen.PrimaryScreen.Bounds;
|
|
|
|
|
}
|
2020-09-27 01:54:24 +12:00
|
|
|
|
|
|
|
|
|
// Only apply taskbar position change when no menu is currently open
|
2021-04-29 08:58:33 +12:00
|
|
|
|
List<Menu> list = AsList;
|
2021-11-17 12:13:46 +13:00
|
|
|
|
WindowsTaskbar taskbar = new();
|
2020-09-21 03:26:45 +12:00
|
|
|
|
if (list.Count == 1)
|
|
|
|
|
{
|
|
|
|
|
taskbarPosition = taskbar.Position;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Shrink the usable space depending on taskbar location
|
2021-04-29 08:58:33 +12:00
|
|
|
|
Menu.StartLocation startLocation;
|
2020-09-21 03:26:45 +12:00
|
|
|
|
switch (taskbarPosition)
|
|
|
|
|
{
|
|
|
|
|
case TaskbarPosition.Left:
|
|
|
|
|
screenBounds.X += taskbar.Size.Width;
|
|
|
|
|
screenBounds.Width -= taskbar.Size.Width;
|
2020-09-21 06:45:12 +12:00
|
|
|
|
startLocation = Menu.StartLocation.BottomLeft;
|
2020-09-21 03:26:45 +12:00
|
|
|
|
break;
|
|
|
|
|
case TaskbarPosition.Right:
|
|
|
|
|
screenBounds.Width -= taskbar.Size.Width;
|
2020-09-21 06:45:12 +12:00
|
|
|
|
startLocation = Menu.StartLocation.BottomRight;
|
2020-09-21 03:26:45 +12:00
|
|
|
|
break;
|
|
|
|
|
case TaskbarPosition.Top:
|
|
|
|
|
screenBounds.Y += taskbar.Size.Height;
|
|
|
|
|
screenBounds.Height -= taskbar.Size.Height;
|
2020-09-21 06:45:12 +12:00
|
|
|
|
startLocation = Menu.StartLocation.TopRight;
|
2020-09-21 03:26:45 +12:00
|
|
|
|
break;
|
|
|
|
|
case TaskbarPosition.Bottom:
|
|
|
|
|
default:
|
|
|
|
|
screenBounds.Height -= taskbar.Size.Height;
|
2020-09-21 06:45:12 +12:00
|
|
|
|
startLocation = Menu.StartLocation.BottomRight;
|
2020-09-21 03:26:45 +12:00
|
|
|
|
break;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-12-28 00:22:52 +13:00
|
|
|
|
if (Properties.Settings.Default.AppearAtTheBottomLeft ||
|
|
|
|
|
isCustomLocationOutsideOfScreen)
|
2021-11-10 06:31:29 +13:00
|
|
|
|
{
|
|
|
|
|
startLocation = Menu.StartLocation.BottomLeft;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-29 08:58:33 +12:00
|
|
|
|
Menu menu;
|
|
|
|
|
Menu menuPredecessor = null;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
for (int i = 0; i < list.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
menu = list[i];
|
|
|
|
|
|
|
|
|
|
// Only last one has to be updated as all previous one were already updated in the past
|
2020-09-20 21:14:20 +12:00
|
|
|
|
if (list.Count - 1 == i)
|
2020-09-27 01:54:24 +12:00
|
|
|
|
{
|
2021-12-28 00:22:52 +13:00
|
|
|
|
menu.AdjustSizeAndLocation(screenBounds, menuPredecessor, startLocation, isCustomLocationOutsideOfScreen);
|
2021-06-03 22:52:47 +12:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-06-27 21:35:07 +12:00
|
|
|
|
// workaround added also as else, because need adjust scrollbar after search
|
2021-12-28 00:22:52 +13:00
|
|
|
|
menu.AdjustSizeAndLocation(screenBounds, menuPredecessor, startLocation, isCustomLocationOutsideOfScreen);
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-12-10 08:00:33 +13:00
|
|
|
|
if (!Properties.Settings.Default.AppearAtTheBottomLeft &&
|
|
|
|
|
!Properties.Settings.Default.AppearAtMouseLocation &&
|
|
|
|
|
!Properties.Settings.Default.UseCustomLocation &&
|
|
|
|
|
i == 0)
|
2020-09-21 03:26:45 +12:00
|
|
|
|
{
|
2020-09-21 06:45:12 +12:00
|
|
|
|
const int overlapTolerance = 4;
|
|
|
|
|
|
2020-09-21 03:26:45 +12:00
|
|
|
|
// Remember width of the initial menu as we don't want to overlap with it
|
2020-09-21 06:45:12 +12:00
|
|
|
|
if (taskbarPosition == TaskbarPosition.Left)
|
|
|
|
|
{
|
|
|
|
|
screenBounds.X += menu.Width - overlapTolerance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
screenBounds.Width -= menu.Width - overlapTolerance;
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
menuPredecessor = menu;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-10 20:47:30 +13:00
|
|
|
|
private void Menu_SearchTextChanging()
|
|
|
|
|
{
|
|
|
|
|
searchTextChanging = true;
|
|
|
|
|
keyboardInput.SearchTextChanging();
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-27 01:54:24 +12:00
|
|
|
|
private void Menu_SearchTextChanged(object sender, EventArgs e)
|
|
|
|
|
{
|
2021-06-28 00:44:12 +12:00
|
|
|
|
Menu menu = (Menu)sender;
|
|
|
|
|
keyboardInput.SearchTextChanged(menu);
|
2020-09-27 01:54:24 +12:00
|
|
|
|
AdjustMenusSizeAndLocation();
|
2020-10-10 20:47:30 +13:00
|
|
|
|
searchTextChanging = false;
|
2021-06-28 00:44:12 +12:00
|
|
|
|
|
|
|
|
|
// if any open menu close
|
2021-10-11 04:33:54 +13:00
|
|
|
|
if (menu.Level + 1 < menus.Length)
|
2021-06-28 00:44:12 +12:00
|
|
|
|
{
|
2021-10-05 08:36:52 +13:00
|
|
|
|
Menu menuToClose = menus[menu.Level + 1];
|
|
|
|
|
if (menuToClose != null)
|
|
|
|
|
{
|
|
|
|
|
HideOldMenu(menuToClose);
|
|
|
|
|
}
|
2021-06-28 00:44:12 +12:00
|
|
|
|
}
|
2020-09-27 01:54:24 +12:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|