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.IO ;
using System.Linq ;
2022-10-23 11:02:31 +13:00
using System.Windows ;
using System.Windows.Controls ;
using System.Windows.Input ;
2023-04-30 08:42:28 +12:00
using System.Windows.Media ;
2022-10-23 11:02:31 +13:00
using System.Windows.Threading ;
2022-11-26 11:31:20 +13:00
using Microsoft.Win32 ;
2020-09-27 01:54:24 +12:00
using SystemTrayMenu.DataClasses ;
2022-08-06 10:09:19 +12:00
using SystemTrayMenu.DllImports ;
2020-09-27 01:54:24 +12:00
using SystemTrayMenu.Handler ;
2022-09-27 06:02:18 +13:00
using SystemTrayMenu.Helpers ;
2022-12-06 08:06:40 +13:00
using SystemTrayMenu.Properties ;
2020-09-27 01:54:24 +12:00
using SystemTrayMenu.Utilities ;
2022-11-20 07:33:23 +13:00
using static SystemTrayMenu . UserInterface . Menu ;
2021-06-27 21:35:07 +12:00
using Menu = SystemTrayMenu . UserInterface . Menu ;
2020-09-27 01:54:24 +12:00
internal class Menus : IDisposable
{
2022-12-03 14:14:15 +13:00
private readonly Dispatcher dispatchter = Dispatcher . CurrentDispatcher ;
2023-04-17 06:17:24 +12:00
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 ( ) ;
private readonly WaitToLoadMenu waitToOpenMenu = new ( ) ;
2021-04-17 12:39:48 +12:00
private readonly KeyboardInput keyboardInput ;
2023-05-02 02:24:33 +12:00
private readonly JoystickHelper ? joystickHelper ;
2022-06-18 00:38:09 +12:00
private readonly List < FileSystemWatcher > watchers = new ( ) ;
2022-06-21 03:39:39 +12:00
private readonly List < EventArgs > watcherHistory = new ( ) ;
2022-10-23 11:02:31 +13:00
private readonly DispatcherTimer timerShowProcessStartedAsLoadingIcon = new ( ) ;
private readonly DispatcherTimer timerStillActiveCheck = new ( ) ;
2022-12-06 08:06:40 +13:00
private readonly DispatcherTimer waitLeave = new ( ) ;
2020-09-27 01:54:24 +12:00
private DateTime deactivatedTime = DateTime . MinValue ;
private OpenCloseState openCloseState = OpenCloseState . Default ;
private TaskbarPosition taskbarPosition = new WindowsTaskbar ( ) . Position ;
2021-04-17 12:39:48 +12:00
private bool searchTextChanging ;
2023-04-25 08:38:36 +12:00
#if TODO // Misc MouseEvents
2021-12-31 00:36:00 +13:00
private int lastMouseDownRowIndex = - 1 ;
2023-04-25 08:38:36 +12:00
#endif
2021-11-26 11:49:50 +13:00
private bool showMenuAfterMainPreload ;
2020-09-27 01:54:24 +12:00
public Menus ( )
{
2023-04-17 06:17:24 +12:00
keyboardInput = new ( menus ) ;
keyboardInput . RegisterHotKey ( ) ;
2023-04-30 10:06:00 +12:00
keyboardInput . HotKeyPressed + = ( ) = > SwitchOpenClose ( false , false ) ;
2023-04-17 06:17:24 +12:00
keyboardInput . ClosePressed + = MenusFadeOut ;
keyboardInput . RowDeselected + = waitToOpenMenu . RowDeselected ;
keyboardInput . EnterPressed + = waitToOpenMenu . EnterOpensInstantly ;
keyboardInput . RowSelected + = waitToOpenMenu . RowSelected ;
2020-09-27 01:54:24 +12:00
workerMainMenu . WorkerSupportsCancellation = true ;
workerMainMenu . DoWork + = LoadMenu ;
workerMainMenu . RunWorkerCompleted + = LoadMainMenuCompleted ;
waitToOpenMenu . StopLoadMenu + = WaitToOpenMenu_StopLoadMenu ;
void WaitToOpenMenu_StopLoadMenu ( )
{
foreach ( BackgroundWorker workerSubMenu in workersSubMenu .
Where ( w = > w . IsBusy ) )
{
workerSubMenu . CancelAsync ( ) ;
}
2022-12-06 09:46:53 +13:00
LoadStopped ? . Invoke ( ) ;
2020-09-27 01:54:24 +12:00
}
waitToOpenMenu . StartLoadMenu + = StartLoadMenu ;
void StartLoadMenu ( RowData rowData )
{
2023-04-30 04:57:39 +12:00
if ( IsMainUsable & &
2022-06-18 00:38:09 +12:00
( menus [ rowData . Level + 1 ] = = null | |
2023-04-17 06:17:24 +12:00
menus [ rowData . Level + 1 ] ? . RowDataParent ! = rowData ) )
2020-09-27 01:54:24 +12:00
{
2023-04-30 04:57:39 +12:00
Create ( new ( rowData ) , rowData . Path ) ; // Level 1+ Sub Menu (loading)
2021-10-04 07:24:22 +13:00
2022-12-06 09:46:53 +13:00
BackgroundWorker ? workerSubMenu = workersSubMenu .
2020-09-27 01:54:24 +12:00
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 ) ;
}
}
waitToOpenMenu . CloseMenu + = CloseMenu ;
void CloseMenu ( int level )
{
2023-04-17 06:17:24 +12:00
if ( level < menus . Length )
2020-09-27 01:54:24 +12:00
{
2023-04-17 06:17:24 +12:00
Menu ? menu = menus [ level ] ;
if ( menu ! = null )
{
HideOldMenu ( menu ) ;
}
2020-09-27 01:54:24 +12:00
}
}
waitToOpenMenu . MouseEnterOk + = MouseEnterOk ;
2022-11-30 10:48:45 +13:00
#if TODO // Misc MouseEvents
2023-04-28 06:27:16 +12:00
dgvMouseRow . RowMouseLeave + = Dgv_RowMouseLeave ; // event moved to Menu.CellMouseLeave()
2022-10-23 11:02:31 +13:00
#endif
2020-09-27 01:54:24 +12:00
2023-05-02 02:24:33 +12:00
if ( Settings . Default . SupportGamepad )
{
joystickHelper = new ( ) ;
joystickHelper . KeyPressed + = ( key , modifiers ) = >
{
if ( IsMainUsable )
{
2023-05-03 08:04:32 +12:00
Menu ? menu = AsEnumerable . FirstOrDefault ( m = > m ! = null & & ( m . IsActive | | m . IsKeyboardFocusWithin ) , MainMenu ) ;
menu ? . Dispatcher . Invoke ( keyboardInput . CmdKeyProcessed , new object [ ] { menu , key , modifiers } ) ;
2023-05-02 02:24:33 +12:00
}
} ;
}
2022-09-27 06:02:18 +13:00
2023-05-03 08:04:32 +12:00
// Timer to check after activation if the application lost focus and close/fadeout windows again
2022-12-06 08:06:40 +13:00
timerStillActiveCheck . Interval = TimeSpan . FromMilliseconds ( 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
{
2023-05-03 08:04:32 +12:00
timerStillActiveCheck . Stop ( ) ;
2020-09-27 01:54:24 +12:00
if ( ! IsActive ( ) )
{
FadeHalfOrOutIfNeeded ( ) ;
}
}
2022-12-06 08:06:40 +13:00
waitLeave . Interval = TimeSpan . FromMilliseconds ( Settings . Default . TimeUntilCloses ) ;
waitLeave . Tick + = ( _ , _ ) = >
{
waitLeave . Stop ( ) ;
FadeHalfOrOutIfNeeded ( ) ;
} ;
2022-06-18 00:38:09 +12:00
CreateWatcher ( Config . Path , false ) ;
2023-04-17 00:17:33 +12:00
foreach ( var pathAndFlags in DirectoryHelpers . GetAddionalPathsForMainMenu ( ) )
2022-06-18 00:38:09 +12:00
{
CreateWatcher ( pathAndFlags . Path , pathAndFlags . Recursive ) ;
}
void CreateWatcher ( string path , bool recursiv )
{
try
{
2022-09-27 06:02:18 +13:00
FileSystemWatcher watcher = new ( )
{
Path = path ,
NotifyFilter = NotifyFilters . Attributes |
2022-06-18 00:38:09 +12:00
NotifyFilters . DirectoryName |
NotifyFilters . FileName |
2022-09-27 06:02:18 +13:00
NotifyFilters . LastWrite ,
Filter = "*.*" ,
} ;
2022-06-18 00:38:09 +12:00
watcher . Created + = WatcherProcessItem ;
watcher . Deleted + = WatcherProcessItem ;
2022-06-21 03:39:39 +12:00
watcher . Renamed + = WatcherProcessItem ;
watcher . Changed + = WatcherProcessItem ;
2022-06-18 00:38:09 +12:00
watcher . IncludeSubdirectories = recursiv ;
watcher . EnableRaisingEvents = true ;
watchers . Add ( watcher ) ;
}
catch ( Exception ex )
{
Log . Warn ( $"Failed to {nameof(CreateWatcher)}: {path}" , ex ) ;
}
}
2022-11-26 11:31:20 +13:00
SystemEvents . DisplaySettingsChanged + = SystemEvents_DisplaySettingsChanged ;
2020-09-27 01:54:24 +12:00
}
2022-12-06 09:46:53 +13:00
internal event Action ? LoadStarted ;
2020-09-27 01:54:24 +12:00
2022-12-06 09:46:53 +13:00
internal event Action ? LoadStopped ;
2020-09-27 01:54:24 +12:00
private enum OpenCloseState
{
Default ,
Opening ,
Closing ,
}
2023-04-28 09:24:25 +12:00
private Menu ? MainMenu = > menus [ 0 ] ;
private bool IsMainUsable = > MainMenu ? . IsUsable ? ? false ;
2023-04-17 06:17:24 +12:00
2023-04-20 10:50:29 +12:00
private IEnumerable < Menu > AsEnumerable = > menus . Where ( m = > m ! = null & & ! m . IsClosed ) ! ;
2020-09-27 01:54:24 +12:00
private List < Menu > AsList = > AsEnumerable . ToList ( ) ;
public void Dispose ( )
{
2022-11-26 11:31:20 +13:00
SystemEvents . DisplaySettingsChanged - = SystemEvents_DisplaySettingsChanged ;
2020-09-27 01:54:24 +12:00
workerMainMenu . Dispose ( ) ;
foreach ( BackgroundWorker worker in workersSubMenu )
{
worker . Dispose ( ) ;
}
waitToOpenMenu . Dispose ( ) ;
keyboardInput . Dispose ( ) ;
2023-05-02 02:24:33 +12:00
joystickHelper ? . Dispose ( ) ;
2022-10-23 11:02:31 +13:00
timerShowProcessStartedAsLoadingIcon . Stop ( ) ;
timerStillActiveCheck . Stop ( ) ;
2022-12-06 08:06:40 +13:00
waitLeave . Stop ( ) ;
2023-04-28 09:24:25 +12:00
MainMenu ? . Close ( ) ;
2022-10-23 11:02:31 +13:00
2022-06-18 00:38:09 +12:00
foreach ( FileSystemWatcher watcher in watchers )
{
watcher . Created - = WatcherProcessItem ;
watcher . Deleted - = WatcherProcessItem ;
2022-06-21 03:39:39 +12:00
watcher . Renamed - = WatcherProcessItem ;
watcher . Changed - = WatcherProcessItem ;
2022-06-18 00:38:09 +12:00
watcher . Dispose ( ) ;
}
2020-09-27 01:54:24 +12:00
}
2022-12-04 13:24:30 +13:00
internal static void OpenFolder ( string? path = null )
{
if ( string . IsNullOrEmpty ( path ) )
{
path = Config . Path ;
}
Log . ProcessStart ( path ) ;
}
2021-11-10 05:41:39 +13:00
internal void SwitchOpenCloseByTaskbarItem ( )
{
2023-04-20 10:50:29 +12:00
// User started with taskbar or clicked on taskbar: remember to open menu after preload has finished
showMenuAfterMainPreload = true ;
SwitchOpenClose ( true , true ) ;
2021-11-10 05:41:39 +13:00
timerStillActiveCheck . Start ( ) ;
}
2023-04-20 10:50:29 +12:00
internal void FirstStartInBackground ( )
2021-10-26 05:55:34 +13:00
{
2023-04-20 10:50:29 +12:00
dispatchter . Invoke ( ( ) = > SwitchOpenClose ( false , true ) ) ;
2021-10-26 05:55:34 +13:00
}
2023-04-30 10:06:00 +12:00
internal void SwitchOpenClose ( bool byClick , bool allowPreloading )
2020-09-27 01:54:24 +12:00
{
2021-11-24 11:48:59 +13:00
// Ignore open close events during main preload #248
2023-04-20 10:50:29 +12:00
if ( IconReader . IsPreloading & & ! allowPreloading )
2021-11-24 11:48:59 +13:00
{
2023-04-20 10:50:29 +12:00
// User pressed hotkey or clicked on notifyicon: remember to open menu after preload has finished
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
}
2023-04-17 06:17:24 +12:00
else
2020-09-27 01:54:24 +12:00
{
2023-04-17 06:17:24 +12:00
if ( openCloseState = = OpenCloseState . Opening | |
2023-04-28 09:24:25 +12:00
( ( MainMenu ? . Visibility ? ? Visibility . Collapsed ) = = Visibility . Visible & & openCloseState = = OpenCloseState . Default ) )
2020-09-27 01:54:24 +12:00
{
2023-04-17 06:17:24 +12:00
openCloseState = OpenCloseState . Closing ;
MenusFadeOut ( ) ;
StopWorker ( ) ;
if ( ! AsEnumerable . Any ( m = > m . Visibility = = Visibility . Visible ) )
{
openCloseState = OpenCloseState . Default ;
}
}
else
{
openCloseState = OpenCloseState . Opening ;
StartWorker ( ) ;
2020-09-27 01:54:24 +12:00
}
}
deactivatedTime = DateTime . MinValue ;
}
internal void StartWorker ( )
{
2022-12-06 08:06:40 +13:00
if ( Settings . Default . GenerateShortcutsToDrives )
2022-07-10 21:40:48 +12:00
{
GenerateDriveShortcuts . Start ( ) ;
}
2020-09-27 01:54:24 +12:00
if ( ! workerMainMenu . IsBusy )
{
2022-12-06 09:46:53 +13:00
LoadStarted ? . Invoke ( ) ;
2023-04-20 10:50:29 +12:00
workerMainMenu . RunWorkerAsync ( null ) ;
2020-09-27 01:54:24 +12:00
}
}
internal void StopWorker ( )
{
if ( workerMainMenu . IsBusy )
{
workerMainMenu . CancelAsync ( ) ;
}
}
2023-04-23 07:04:34 +12:00
private static void LoadMenu ( object? sender , DoWorkEventArgs eDoWork )
2021-11-11 11:39:52 +13:00
{
2023-04-23 07:04:34 +12:00
BackgroundWorker ? workerSelf = sender as BackgroundWorker ;
2022-12-05 13:27:57 +13:00
RowData ? rowData = eDoWork . Argument as RowData ;
2023-04-30 04:57:39 +12:00
string path = rowData ? . ResolvedPath ? ? Config . Path ;
2021-12-11 03:20:24 +13:00
2023-04-30 04:57:39 +12:00
MenuData menuData = new ( rowData ) ;
2023-04-23 07:04:34 +12:00
DirectoryHelpers . DiscoverItems ( workerSelf , path , ref menuData ) ;
if ( menuData . DirectoryState ! = MenuDataDirectoryState . Undefined & &
2023-04-30 04:57:39 +12:00
workerSelf ! = null & & rowData = = null )
2023-04-23 07:04:34 +12:00
{
// After success of MainMenu loading: never run again
workerSelf . DoWork - = LoadMenu ;
}
2021-11-11 11:39:52 +13:00
eDoWork . Result = menuData ;
}
2023-04-23 07:04:34 +12:00
private void LoadMainMenuCompleted ( object? sender , RunWorkerCompletedEventArgs e )
{
keyboardInput . ResetSelectedByKey ( ) ;
LoadStopped ? . Invoke ( ) ;
if ( e . Result = = null )
{
2023-04-28 09:24:25 +12:00
Menu ? menu = MainMenu ;
2023-04-23 07:04:34 +12:00
if ( menu ! = null )
{
// The main menu gets loaded again
// Clean up menu status of previous one
ListView ? dgvMainMenu = menu . GetDataGridView ( ) ;
if ( dgvMainMenu ! = null )
{
foreach ( ListViewItemData item in dgvMainMenu . Items )
{
RowData rowDataToClear = item . data ;
rowDataToClear . IsMenuOpen = false ;
rowDataToClear . IsClicking = false ;
rowDataToClear . IsSelected = false ;
}
RefreshSelection ( dgvMainMenu ) ;
}
menu . RelocateOnNextShow = true ;
}
AsEnumerable . ToList ( ) . ForEach ( m = > { m . ShowWithFade ( ) ; } ) ;
}
else
{
// First time the main menu gets loaded
MenuData menuData = ( MenuData ) e . Result ;
switch ( menuData . DirectoryState )
{
case MenuDataDirectoryState . Valid :
if ( IconReader . IsPreloading )
{
Create ( menuData , Config . Path ) ; // Level 0 Main Menu
IconReader . IsPreloading = false ;
if ( showMenuAfterMainPreload )
{
2023-04-28 09:24:25 +12:00
MainMenu ? . ShowWithFade ( ) ;
2023-04-23 07:04:34 +12:00
}
}
else
{
AsEnumerable . ToList ( ) . ForEach ( m = > { m . ShowWithFade ( ) ; } ) ;
}
break ;
case MenuDataDirectoryState . Empty :
MessageBox . Show ( Translator . GetText ( "Your root directory for the app does not exist or is empty! Change the root directory or put some files, directories or shortcuts into the root directory." ) ) ;
OpenFolder ( ) ;
Config . SetFolderByUser ( ) ;
AppRestart . ByConfigChange ( ) ;
break ;
case MenuDataDirectoryState . NoAccess :
MessageBox . Show ( Translator . GetText ( "You have no access to the root directory of the app. Grant access to the directory or change the root directory." ) ) ;
OpenFolder ( ) ;
Config . SetFolderByUser ( ) ;
AppRestart . ByConfigChange ( ) ;
break ;
case MenuDataDirectoryState . Undefined :
Log . Info ( $"{nameof(MenuDataDirectoryState)}.{nameof(MenuDataDirectoryState.Undefined)}" ) ;
break ;
default :
break ;
}
}
openCloseState = OpenCloseState . Default ;
}
2023-04-28 08:19:02 +12:00
private void LoadSubMenuCompleted ( object? senderCompleted , RunWorkerCompletedEventArgs e )
{
if ( e . Result = = null )
{
return ;
}
MenuData menuData = ( MenuData ) e . Result ;
Menu ? menu = menus [ menuData . Level ] ;
if ( menu = = null )
{
return ;
}
if ( IsMainUsable )
{
if ( menuData . DirectoryState ! = MenuDataDirectoryState . Undefined )
{
// Sub Menu (completed)
2023-04-28 09:24:25 +12:00
menu . AddItemsToMenu ( menuData . RowDatas , menuData . DirectoryState , true ) ;
2023-04-28 08:19:02 +12:00
AdjustMenusSizeAndLocation ( menu . Level ) ;
}
else
{
menu . HideWithFade ( ) ;
menus [ menu . Level ] = null ;
ListView ? lv = menus [ menuData . Level - 1 ] ? . GetDataGridView ( ) ;
if ( lv ! = null )
{
RefreshSelection ( lv ) ;
}
}
}
}
2022-02-28 04:44:08 +13:00
private bool IsActive ( )
{
2023-05-03 08:04:32 +12:00
return menus . Where ( m = > m ! = null & & ( m . IsActive | | m . IsKeyboardFocusWithin ) ) . FirstOrDefault ( ) ! = null | | ( App . TaskbarLogo ? . IsActive ? ? false ) ;
2022-02-28 04:44:08 +13:00
}
2023-04-16 22:42:42 +12:00
private Menu Create ( MenuData menuData , string path )
2020-09-27 01:54:24 +12:00
{
2023-04-16 07:23:28 +12:00
Menu menu = new ( menuData , path ) ;
2021-06-28 00:44:12 +12:00
2023-04-17 06:17:24 +12:00
menu . MenuScrolled + = ( ) = > AdjustMenusSizeAndLocation ( menu . Level + 1 ) ; // TODO: Only update vertical location while scrolling?
2022-12-06 08:06:40 +13:00
menu . MouseLeave + = ( _ , _ ) = >
{
// Restart timer
waitLeave . Stop ( ) ;
waitLeave . Start ( ) ;
} ;
menu . MouseEnter + = ( _ , _ ) = > waitLeave . Stop ( ) ;
2020-09-27 01:54:24 +12:00
menu . CmdKeyProcessed + = keyboardInput . CmdKeyProcessed ;
2023-04-20 10:50:29 +12:00
2020-10-10 20:47:30 +13:00
menu . SearchTextChanging + = Menu_SearchTextChanging ;
2023-04-17 06:17:24 +12:00
void Menu_SearchTextChanging ( )
{
searchTextChanging = true ;
keyboardInput . SearchTextChanging ( ) ;
waitToOpenMenu . MouseActive = false ;
}
2020-09-27 01:54:24 +12:00
menu . SearchTextChanged + = Menu_SearchTextChanged ;
2023-04-28 09:24:25 +12:00
void Menu_SearchTextChanged ( Menu menu , bool isSearchStringEmpty , bool causedByWatcherUpdate )
2023-04-17 06:17:24 +12:00
{
keyboardInput . SearchTextChanged ( menu , isSearchStringEmpty ) ;
AdjustMenusSizeAndLocation ( menu . Level + 1 ) ;
searchTextChanging = false ;
// if any open menu close
2023-04-28 09:24:25 +12:00
if ( ! causedByWatcherUpdate & & menu . Level + 1 < menus . Length )
2023-04-17 06:17:24 +12:00
{
Menu ? menuToClose = menus [ menu . Level + 1 ] ;
2023-04-28 09:24:25 +12:00
if ( menuToClose ! = null )
2023-04-17 06:17:24 +12:00
{
HideOldMenu ( menuToClose ) ;
}
}
}
2021-11-25 07:01:59 +13:00
menu . UserDragsMenu + = Menu_UserDragsMenu ;
void Menu_UserDragsMenu ( )
{
2023-04-17 06:17:24 +12:00
Menu ? menu = menus [ 1 ] ;
if ( menu ! = null )
2021-11-25 07:01:59 +13:00
{
2023-04-17 06:17:24 +12:00
HideOldMenu ( menu ) ;
2021-11-25 07:01:59 +13:00
}
}
2022-10-23 11:02:31 +13:00
menu . Deactivated + = Deactivate ;
2022-12-06 09:46:53 +13:00
void Deactivate ( object? sender , EventArgs e )
2020-09-27 01:54:24 +12:00
{
2023-04-20 10:50:29 +12:00
if ( openCloseState = = OpenCloseState . Opening )
2021-11-10 03:12:52 +13:00
{
Log . Info ( "Ignored Deactivate, because openCloseState == OpenCloseState.Opening" ) ;
}
2023-04-17 06:17:24 +12:00
else if ( ! Settings . Default . StaysOpenWhenFocusLostAfterEnterPressed )
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
{
2023-05-03 08:04:32 +12:00
// Bring transparent menus back
foreach ( Menu ? menu in menus . Where ( m = > m ! = null & & m . Opacity ! = 1D ) )
2020-09-27 01:54:24 +12:00
{
2023-05-03 08:04:32 +12:00
menu ! . ActivateWithFade ( ) ;
2020-09-27 01:54:24 +12:00
}
2023-05-03 08:04:32 +12:00
timerStillActiveCheck . Stop ( ) ;
timerStillActiveCheck . Start ( ) ;
2020-09-27 01:54:24 +12:00
}
2022-12-01 12:16:30 +13:00
menu . IsVisibleChanged + = ( sender , _ ) = > MenuVisibleChanged ( ( Menu ) sender ) ;
2023-04-28 06:27:16 +12:00
menu . CellMouseEnter + = waitToOpenMenu . MouseEnter ;
menu . CellMouseLeave + = waitToOpenMenu . MouseLeave ;
2022-10-23 11:02:31 +13:00
menu . CellMouseDown + = Dgv_MouseDown ;
menu . CellMouseUp + = Dgv_MouseUp ;
2023-04-25 08:38:36 +12:00
menu . CellOpenOnClick + = Dgv_OpenItemOnClick ;
menu . ClosePressed + = MenusFadeOut ;
2022-11-30 10:48:45 +13:00
2022-12-06 09:46:53 +13:00
ListView ? dgv = menu . GetDataGridView ( ) ;
if ( dgv ! = null )
{
2022-11-30 10:48:45 +13:00
#if TODO // Misc MouseEvents
2022-12-06 09:46:53 +13:00
dgv . MouseMove + = waitToOpenMenu . MouseMove ;
2022-11-30 10:48:45 +13:00
#endif
2022-12-06 09:46:53 +13:00
dgv . SelectionChanged + = Dgv_SelectionChanged ;
}
2023-04-28 08:19:02 +12:00
if ( menu . Level = = 0 )
2023-04-16 08:47:29 +12:00
{
// Main Menu
2023-04-28 08:19:02 +12:00
menus [ menu . Level ] = menu ;
2023-04-16 08:47:29 +12:00
menu . Loaded + = ( s , e ) = > ExecuteWatcherHistory ( ) ;
}
2023-04-16 22:42:42 +12:00
else
2023-04-16 08:47:29 +12:00
{
2023-04-16 22:42:42 +12:00
// Sub Menu (loading)
2023-04-17 06:17:24 +12:00
if ( IsMainUsable )
2023-04-16 08:47:29 +12:00
{
2023-04-16 22:42:42 +12:00
HideOldMenu ( menu , true ) ;
menus [ menu . Level ] = menu ;
2023-04-24 09:53:20 +12:00
menu . ShowWithFade ( ! IsActive ( ) ) ;
2023-04-16 08:47:29 +12:00
}
}
2020-09-27 01:54:24 +12:00
return menu ;
}
2022-12-01 12:16:30 +13:00
private void MenuVisibleChanged ( Menu menu )
2020-09-27 01:54:24 +12:00
{
if ( menu . IsUsable )
{
2023-04-17 06:17:24 +12:00
AdjustMenusSizeAndLocation ( menu . Level ) ;
2022-01-08 23:39:23 +13:00
if ( menu . Level = = 0 )
{
2022-06-11 22:45:46 +12:00
menu . ResetSearchText ( ) ;
2023-04-30 10:06:00 +12:00
menu . Activate ( ) ;
2022-01-08 23:39:23 +13:00
}
2020-09-27 01:54:24 +12:00
}
2022-10-23 11:02:31 +13:00
if ( menu . Visibility ! = Visibility . Visible & & menu . Level ! = 0 )
2020-09-27 01:54:24 +12:00
{
2022-11-26 11:31:20 +13:00
menu . Close ( ) ;
2020-09-27 01:54:24 +12:00
}
2022-10-23 11:02:31 +13:00
if ( ! AsEnumerable . Any ( m = > m . Visibility = = Visibility . Visible ) )
2020-09-27 01:54:24 +12:00
{
2023-04-29 04:48:39 +12:00
IconReader . ClearCacheWhenLimitReached ( ) ;
2021-10-14 04:13:11 +13:00
openCloseState = OpenCloseState . Default ;
2020-09-27 01:54:24 +12:00
}
}
2023-04-25 10:24:48 +12:00
private void Dgv_MouseDown ( ListView dgv , ListViewItemData itemData , MouseButtonEventArgs e )
2020-09-27 01:54:24 +12:00
{
2023-04-25 10:24:48 +12:00
MouseEnterOk ( dgv , itemData , true ) ;
2022-10-23 11:02:31 +13:00
2023-04-25 08:38:36 +12:00
#if TODO // Misc MouseEvents
2022-10-23 11:02:31 +13:00
if ( e . LeftButton = = MouseButtonState . Pressed )
2021-11-24 11:08:19 +13:00
{
2022-10-23 11:02:31 +13:00
lastMouseDownRowIndex = index ;
2021-11-24 11:08:19 +13:00
}
2023-04-25 08:38:36 +12:00
#endif
2021-12-30 23:56:34 +13:00
}
2023-04-25 10:24:48 +12:00
private void Dgv_MouseUp ( object sender , ListViewItemData itemData , MouseButtonEventArgs e )
2021-11-24 11:08:19 +13:00
{
2023-04-25 08:38:36 +12:00
#if TODO // Misc MouseEvents
2021-12-31 00:36:00 +13:00
lastMouseDownRowIndex = - 1 ;
2023-04-25 08:38:36 +12:00
#endif
2021-11-24 11:08:19 +13:00
}
2023-04-25 10:24:48 +12:00
private void MouseEnterOk ( ListView dgv , ListViewItemData itemData )
2022-06-18 00:38:09 +12:00
{
2023-04-25 10:24:48 +12:00
MouseEnterOk ( dgv , itemData , false ) ;
2022-06-18 00:38:09 +12:00
}
2023-04-25 10:24:48 +12:00
private void MouseEnterOk ( ListView dgv , ListViewItemData itemData , bool refreshView )
2022-06-18 00:38:09 +12:00
{
2023-04-17 06:17:24 +12:00
if ( IsMainUsable )
2022-06-18 00:38:09 +12:00
{
if ( keyboardInput . InUse )
{
keyboardInput . ClearIsSelectedByKey ( ) ;
keyboardInput . InUse = false ;
}
2023-04-25 10:24:48 +12:00
keyboardInput . Select ( dgv , itemData , refreshView ) ;
2022-06-18 00:38:09 +12:00
}
}
2022-11-30 10:48:45 +13:00
#if TODO // Misc MouseEvents
2021-11-24 11:08:19 +13:00
private void Dgv_RowMouseLeave ( object sender , DataGridViewCellEventArgs e )
{
2022-10-23 11:02:31 +13:00
ListView dgv = ( ListView ) sender ;
2021-11-24 11:08:19 +13:00
2023-04-20 10:50:29 +12:00
if ( e . RowIndex = = lastMouseDownRowIndex & &
2021-11-24 11:08:19 +13:00
e . RowIndex > - 1 & &
2022-10-23 11:02:31 +13:00
e . RowIndex < dgv . Items . Count )
2021-11-24 11:08:19 +13:00
{
2021-12-31 00:36:00 +13:00
lastMouseDownRowIndex = - 1 ;
2022-11-30 10:48:45 +13:00
2022-10-23 11:02:31 +13:00
RowData rowData = ( RowData ) dgv . Items [ e . RowIndex ] . Cells [ 2 ] . Value ;
2022-06-18 00:38:09 +12:00
string [ ] files = new string [ ] { rowData . Path } ;
2021-11-24 11:08:19 +13:00
// 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 ) ;
}
}
2022-10-23 11:02:31 +13:00
#endif
2021-11-24 11:08:19 +13:00
2023-04-25 10:24:48 +12:00
private void Dgv_OpenItemOnClick ( ListView sender , ListViewItemData itemData )
2021-11-24 11:08:19 +13:00
{
2023-04-25 08:38:36 +12:00
#if TODO // Misc MouseEvents
2021-12-31 00:36:00 +13:00
lastMouseDownRowIndex = - 1 ;
2023-04-25 08:38:36 +12:00
#endif
2023-04-25 10:24:48 +12:00
waitToOpenMenu . ClickOpensInstantly ( sender , itemData ) ;
2020-09-27 01:54:24 +12:00
}
private void Dgv_SelectionChanged ( object sender , EventArgs e )
{
2022-10-23 11:02:31 +13:00
RefreshSelection ( ( ListView ) sender ) ;
2020-09-27 01:54:24 +12:00
}
2022-10-23 11:02:31 +13:00
private void RefreshSelection ( ListView dgv )
2020-09-27 01:54:24 +12:00
{
2020-10-10 20:47:30 +13:00
dgv . SelectionChanged - = Dgv_SelectionChanged ;
2022-10-23 11:02:31 +13:00
2023-04-25 10:24:48 +12:00
foreach ( ListViewItemData itemData in dgv . Items )
2020-09-27 01:54:24 +12:00
{
2023-04-25 10:24:48 +12:00
RowData rowData = itemData . data ;
2023-04-30 08:42:28 +12:00
if ( rowData . IsClicking )
2022-02-05 22:32:28 +13:00
{
2023-05-01 08:42:25 +12:00
itemData . BorderBrush = MenuDefines . ColorIcons ;
itemData . BackgroundBrush = MenuDefines . ColorSelectedItem ;
2023-04-25 10:24:48 +12:00
dgv . SelectedItems . Add ( itemData ) ;
2022-02-05 22:32:28 +13:00
}
2020-09-27 01:54:24 +12:00
else if ( rowData . IsMenuOpen )
{
2023-05-01 08:42:25 +12:00
itemData . BorderBrush = MenuDefines . ColorOpenFolderBorder ;
itemData . BackgroundBrush = MenuDefines . ColorOpenFolder ;
2023-04-25 10:24:48 +12:00
dgv . SelectedItems . Add ( itemData ) ;
2020-09-27 01:54:24 +12:00
}
else if ( rowData . IsSelected )
{
2023-05-01 08:42:25 +12:00
itemData . BorderBrush = MenuDefines . ColorSelectedItemBorder ;
itemData . BackgroundBrush = MenuDefines . ColorSelectedItem ;
2023-04-25 10:24:48 +12:00
dgv . SelectedItems . Add ( itemData ) ;
2020-09-27 01:54:24 +12:00
}
else
{
2023-04-30 08:42:28 +12:00
itemData . BorderBrush = Brushes . White ;
itemData . BackgroundBrush = Brushes . White ;
2023-04-25 10:24:48 +12:00
dgv . SelectedItems . Remove ( itemData ) ;
2020-09-27 01:54:24 +12:00
}
}
2020-10-10 20:47:30 +13:00
dgv . SelectionChanged + = Dgv_SelectionChanged ;
if ( ! searchTextChanging )
{
2022-11-26 11:31:20 +13:00
dgv . InvalidateVisual ( ) ;
2020-10-10 20:47:30 +13:00
}
2020-09-27 01:54:24 +12:00
}
2022-12-06 09:46:53 +13:00
private void SystemEvents_DisplaySettingsChanged ( object? sender , EventArgs e )
2022-11-26 11:31:20 +13:00
{
2022-12-03 14:14:15 +13:00
dispatchter . Invoke ( ( ) = >
2022-11-26 11:31:20 +13:00
{
2023-04-17 06:17:24 +12:00
if ( IsMainUsable )
2022-12-03 14:14:15 +13:00
{
2023-04-28 09:24:25 +12:00
Menu ? menu = MainMenu ;
2023-04-17 06:17:24 +12:00
if ( menu ! = null )
{
2023-04-23 07:04:34 +12:00
menu . RelocateOnNextShow = true ;
2023-04-17 06:17:24 +12:00
}
2022-12-03 14:14:15 +13:00
}
} ) ;
2022-11-26 11:31:20 +13:00
}
2020-09-27 01:54:24 +12:00
private void HideOldMenu ( Menu menuToShow , bool keepOrSetIsMenuOpen = false )
{
2023-04-17 06:17:24 +12:00
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
2022-12-04 13:24:30 +13:00
ListView ? dgvPrevious = menuPrevious . GetDataGridView ( ) ;
if ( dgvPrevious ! = null )
2020-09-27 01:54:24 +12:00
{
2022-12-04 13:24:30 +13:00
foreach ( ListViewItemData item in dgvPrevious . Items )
2021-05-14 01:20:40 +12:00
{
2022-12-04 13:24:30 +13:00
RowData rowDataToClear = item . data ;
2023-04-16 07:23:28 +12:00
if ( rowDataToClear = = menuToShow . RowDataParent )
2022-12-04 13:24:30 +13:00
{
rowDataToClear . IsMenuOpen = keepOrSetIsMenuOpen ;
}
else
{
rowDataToClear . IsMenuOpen = false ;
}
2021-05-14 01:20:40 +12:00
}
2020-09-27 01:54:24 +12:00
2022-12-04 13:24:30 +13:00
RefreshSelection ( dgvPrevious ) ;
}
2020-09-27 01:54:24 +12:00
2021-05-14 01:20:40 +12:00
// Hide old menu
2023-04-17 06:17:24 +12:00
foreach ( Menu ? menuToClose in menus . Where (
2021-05-14 01:20:40 +12:00
m = > m ! = null & & m . Level > menuPrevious . Level ) )
{
2023-04-17 06:17:24 +12:00
menuToClose ! . HideWithFade ( ) ;
2021-05-14 01:20:40 +12:00
menus [ menuToClose . Level ] = null ;
}
2020-09-27 01:54:24 +12:00
}
}
private void FadeHalfOrOutIfNeeded ( )
{
2023-04-17 06:17:24 +12:00
if ( IsMainUsable )
2020-09-27 01:54:24 +12:00
{
if ( ! IsActive ( ) )
{
2022-12-06 08:06:40 +13:00
if ( Settings . Default . StaysOpenWhenFocusLost & &
2022-10-23 11:02:31 +13:00
AsList . Any ( m = > m . IsMouseOn ( ) ) )
2020-09-27 01:54:24 +12:00
{
if ( ! keyboardInput . InUse )
{
2023-04-24 09:53:20 +12:00
AsList . ForEach ( menu = > menu . ShowWithFade ( true ) ) ;
2020-09-27 01:54:24 +12:00
}
}
2021-06-26 23:24:56 +12:00
else if ( Config . AlwaysOpenByPin )
{
2023-04-24 09:53:20 +12:00
AsList . ForEach ( menu = > menu . ShowWithFade ( true ) ) ;
2021-06-26 23:24:56 +12:00
}
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
}
2023-04-24 09:53:20 +12:00
private void GetScreenBounds ( out Rect screenBounds , out bool useCustomLocation , out StartLocation startLocation )
2020-09-27 01:54:24 +12:00
{
2022-12-06 08:06:40 +13:00
if ( Settings . Default . AppearAtMouseLocation )
2021-11-10 06:48:30 +13:00
{
2022-10-23 11:02:31 +13:00
screenBounds = NativeMethods . Screen . FromPoint ( NativeMethods . Screen . CursorPosition ) ;
2023-04-17 06:17:24 +12:00
useCustomLocation = false ;
2021-11-10 06:48:30 +13:00
}
2022-12-06 08:06:40 +13:00
else if ( Settings . Default . UseCustomLocation )
2021-12-10 08:00:33 +13:00
{
2023-04-17 06:17:24 +12:00
screenBounds = NativeMethods . Screen . FromPoint ( new (
2022-12-06 08:06:40 +13:00
Settings . Default . CustomLocationX ,
Settings . Default . CustomLocationY ) ) ;
2021-12-28 00:22:52 +13:00
2023-04-23 07:04:34 +12:00
useCustomLocation = screenBounds . Contains (
2022-12-06 08:06:40 +13:00
new Point ( Settings . Default . CustomLocationX , Settings . Default . CustomLocationY ) ) ;
2021-12-10 08:00:33 +13:00
}
2021-11-10 06:48:30 +13:00
else
{
2022-10-23 11:02:31 +13:00
screenBounds = NativeMethods . Screen . PrimaryScreen ;
2023-04-17 06:17:24 +12:00
useCustomLocation = false ;
2021-11-10 06:48:30 +13:00
}
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
2020-09-21 03:26:45 +12:00
switch ( taskbarPosition )
{
case TaskbarPosition . Left :
screenBounds . X + = taskbar . Size . Width ;
screenBounds . Width - = taskbar . Size . Width ;
2023-04-24 09:53:20 +12:00
startLocation = StartLocation . BottomLeft ;
2020-09-21 03:26:45 +12:00
break ;
case TaskbarPosition . Right :
screenBounds . Width - = taskbar . Size . Width ;
2023-04-24 09:53:20 +12:00
startLocation = StartLocation . BottomRight ;
2020-09-21 03:26:45 +12:00
break ;
case TaskbarPosition . Top :
screenBounds . Y + = taskbar . Size . Height ;
screenBounds . Height - = taskbar . Size . Height ;
2023-04-24 09:53:20 +12:00
startLocation = StartLocation . TopRight ;
2020-09-21 03:26:45 +12:00
break ;
case TaskbarPosition . Bottom :
default :
screenBounds . Height - = taskbar . Size . Height ;
2023-04-24 09:53:20 +12:00
startLocation = StartLocation . BottomRight ;
2020-09-21 03:26:45 +12:00
break ;
2020-09-27 01:54:24 +12:00
}
2023-04-17 06:17:24 +12:00
if ( Settings . Default . AppearAtTheBottomLeft )
2021-11-10 06:31:29 +13:00
{
2023-04-24 09:53:20 +12:00
startLocation = StartLocation . BottomLeft ;
2021-11-10 06:31:29 +13:00
}
2023-04-17 06:17:24 +12:00
}
private void AdjustMenusSizeAndLocation ( int startLevel )
{
2023-04-24 09:53:20 +12:00
GetScreenBounds ( out Rect screenBounds , out bool useCustomLocation , out StartLocation startLocation ) ;
2021-11-10 06:31:29 +13:00
2021-04-29 08:58:33 +12:00
Menu menu ;
2022-12-05 13:27:57 +13:00
Menu ? menuPredecessor = null ;
2023-04-17 06:17:24 +12:00
List < Menu > list = AsList ;
2020-09-27 01:54:24 +12:00
for ( int i = 0 ; i < list . Count ; i + + )
{
menu = list [ i ] ;
2023-04-17 06:17:24 +12:00
if ( startLevel < = i )
{
menu . AdjustSizeAndLocation ( screenBounds , menuPredecessor , startLocation , useCustomLocation ) ;
}
else
{
// Make sure further calculations of this menu access updated values (later used as predecessor)
menu . UpdateLayout ( ) ;
}
2022-11-26 11:31:20 +13:00
2022-12-06 08:06:40 +13:00
if ( ! Settings . Default . AppearAtTheBottomLeft & &
! Settings . Default . AppearAtMouseLocation & &
! Settings . Default . UseCustomLocation & &
2021-12-10 08:00:33 +13:00
i = = 0 )
2020-09-21 03:26:45 +12:00
{
2023-04-24 09:53:20 +12:00
const double overlapTolerance = 4D ;
2020-09-21 06:45:12 +12:00
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 )
{
2022-10-23 11:02:31 +13:00
screenBounds . X + = ( int ) menu . Width - overlapTolerance ;
2020-09-21 06:45:12 +12:00
}
2022-10-23 11:02:31 +13:00
screenBounds . Width - = ( int ) menu . Width - overlapTolerance ;
2020-09-27 01:54:24 +12:00
}
2022-11-26 11:31:20 +13:00
2020-09-27 01:54:24 +12:00
menuPredecessor = menu ;
}
}
2022-06-18 00:38:09 +12:00
private void ExecuteWatcherHistory ( )
{
foreach ( var fileSystemEventArgs in watcherHistory )
{
WatcherProcessItem ( watchers , fileSystemEventArgs ) ;
}
watcherHistory . Clear ( ) ;
}
2022-06-21 03:39:39 +12:00
private void WatcherProcessItem ( object sender , EventArgs e )
2022-06-18 00:38:09 +12:00
{
2023-04-28 09:24:25 +12:00
Menu ? menu = MainMenu ;
2023-04-17 01:45:47 +12:00
bool useHistory = false ;
2023-04-17 06:17:24 +12:00
if ( menu = = null )
2023-04-16 08:19:16 +12:00
{
2023-04-17 01:45:47 +12:00
useHistory = true ;
2023-04-16 08:19:16 +12:00
}
else
{
2023-04-17 06:17:24 +12:00
menu . Dispatcher . Invoke ( ( ) = > useHistory = ! menu . IsLoaded ) ;
2023-04-16 08:19:16 +12:00
}
2023-04-17 01:45:47 +12:00
if ( useHistory )
2022-06-18 00:38:09 +12:00
{
watcherHistory . Add ( e ) ;
return ;
}
2022-06-21 03:39:39 +12:00
if ( e is RenamedEventArgs renamedEventArgs )
{
2023-04-28 09:24:25 +12:00
MainMenu ? . Dispatcher . Invoke ( ( ) = > RenameItem ( renamedEventArgs ) ) ;
2022-06-21 03:39:39 +12:00
}
2022-12-05 13:27:57 +13:00
else if ( e is FileSystemEventArgs fileSystemEventArgs )
2022-06-21 03:39:39 +12:00
{
if ( fileSystemEventArgs . ChangeType = = WatcherChangeTypes . Deleted )
{
2023-04-28 09:24:25 +12:00
MainMenu ? . Dispatcher . Invoke ( ( ) = > DeleteItem ( fileSystemEventArgs ) ) ;
2022-06-21 03:39:39 +12:00
}
else if ( fileSystemEventArgs . ChangeType = = WatcherChangeTypes . Created )
{
2023-04-28 09:24:25 +12:00
MainMenu ? . Dispatcher . Invoke ( ( ) = > CreateItem ( fileSystemEventArgs ) ) ;
2022-06-21 03:39:39 +12:00
}
}
}
private void RenameItem ( RenamedEventArgs e )
{
try
2022-06-18 00:38:09 +12:00
{
2022-06-21 03:39:39 +12:00
List < RowData > rowDatas = new ( ) ;
2023-04-28 09:24:25 +12:00
ListView ? dgv = MainMenu ? . GetDataGridView ( ) ;
2022-12-05 13:27:57 +13:00
if ( dgv ! = null )
2022-06-21 03:39:39 +12:00
{
2022-12-05 13:27:57 +13:00
foreach ( ListViewItemData item in dgv . Items )
2022-06-21 03:39:39 +12:00
{
2022-12-05 13:27:57 +13:00
RowData rowData = item . data ;
2023-04-30 04:57:39 +12:00
if ( rowData . Path . StartsWith ( $"{e.OldFullPath}" ) )
2022-06-21 03:39:39 +12:00
{
2023-04-30 04:57:39 +12:00
string path = rowData . Path . Replace ( e . OldFullPath , e . FullPath ) ;
2022-12-05 13:27:57 +13:00
FileAttributes attr = File . GetAttributes ( path ) ;
bool isFolder = ( attr & FileAttributes . Directory ) = = FileAttributes . Directory ;
if ( isFolder )
{
2023-04-30 04:57:39 +12:00
string? dirpath = Path . GetDirectoryName ( path ) ;
if ( string . IsNullOrEmpty ( dirpath ) )
2023-04-17 06:17:24 +12:00
{
continue ;
}
2023-04-30 04:57:39 +12:00
path = dirpath ;
2022-12-05 13:27:57 +13:00
}
2023-04-29 04:48:39 +12:00
RowData rowDataRenamed = new ( isFolder , rowData . IsAdditionalItem , 0 , path ) ;
2023-04-28 07:11:20 +12:00
FolderOptions . ReadHiddenAttributes ( rowDataRenamed . Path , out bool hasHiddenFlag , out bool isDirectoryToHide ) ;
if ( isDirectoryToHide )
2022-12-05 13:27:57 +13:00
{
continue ;
}
2022-06-21 03:39:39 +12:00
2022-12-05 13:27:57 +13:00
IconReader . RemoveIconFromCache ( rowData . Path ) ;
2023-04-28 07:11:20 +12:00
rowDataRenamed . HiddenEntry = hasHiddenFlag ;
2022-12-05 13:27:57 +13:00
rowDataRenamed . ReadIcon ( true ) ;
rowDatas . Add ( rowDataRenamed ) ;
}
else
2022-06-21 03:39:39 +12:00
{
2022-12-05 13:27:57 +13:00
rowDatas . Add ( rowData ) ;
2022-06-21 03:39:39 +12:00
}
}
}
2023-04-17 00:17:33 +12:00
rowDatas = DirectoryHelpers . SortItems ( rowDatas ) ;
2022-06-21 03:39:39 +12:00
keyboardInput . ClearIsSelectedByKey ( ) ;
2023-04-28 09:24:25 +12:00
MainMenu ? . AddItemsToMenu ( rowDatas , null , true ) ;
MainMenu ? . OnWatcherUpdate ( ) ;
2022-06-18 00:38:09 +12:00
}
2022-06-21 03:39:39 +12:00
catch ( Exception ex )
2022-06-18 00:38:09 +12:00
{
2022-06-21 03:39:39 +12:00
Log . Warn ( $"Failed to {nameof(RenameItem)}: {e.OldFullPath} {e.FullPath}" , ex ) ;
2022-06-18 00:38:09 +12:00
}
}
private void DeleteItem ( FileSystemEventArgs e )
{
try
{
2023-04-28 09:24:25 +12:00
ListView ? dgv = MainMenu ? . GetDataGridView ( ) ;
2022-12-05 13:27:57 +13:00
if ( dgv ! = null )
2022-06-18 00:38:09 +12:00
{
2022-12-05 13:27:57 +13:00
List < ListViewItemData > rowsToRemove = new ( ) ;
2023-04-16 08:19:16 +12:00
foreach ( ListViewItemData item in dgv . ItemsSource )
2022-06-18 00:38:09 +12:00
{
2022-12-05 13:27:57 +13:00
RowData rowData = item . data ;
if ( rowData . Path = = e . FullPath | |
2023-04-30 04:57:39 +12:00
rowData . Path . StartsWith ( $"{e.FullPath}\\" ) )
2022-12-05 13:27:57 +13:00
{
IconReader . RemoveIconFromCache ( rowData . Path ) ;
rowsToRemove . Add ( item ) ;
}
2022-06-18 00:38:09 +12:00
}
2022-12-05 13:27:57 +13:00
foreach ( ListViewItemData rowToRemove in rowsToRemove )
{
2023-04-16 08:19:16 +12:00
( ( IEditableCollectionView ) dgv . Items ) . Remove ( rowToRemove ) ;
2022-12-05 13:27:57 +13:00
}
2022-06-18 00:38:09 +12:00
}
keyboardInput . ClearIsSelectedByKey ( ) ;
2023-04-28 09:24:25 +12:00
MainMenu ? . OnWatcherUpdate ( ) ;
2022-06-18 00:38:09 +12:00
}
catch ( Exception ex )
{
Log . Warn ( $"Failed to {nameof(DeleteItem)}: {e.FullPath}" , ex ) ;
}
}
private void CreateItem ( FileSystemEventArgs e )
{
try
{
FileAttributes attr = File . GetAttributes ( e . FullPath ) ;
bool isFolder = ( attr & FileAttributes . Directory ) = = FileAttributes . Directory ;
bool isAddionalItem = Path . GetDirectoryName ( e . FullPath ) ! = Config . Path ;
2023-04-29 04:48:39 +12:00
RowData rowData = new ( isFolder , isAddionalItem , 0 , e . FullPath ) ;
2023-04-28 07:11:20 +12:00
FolderOptions . ReadHiddenAttributes ( rowData . Path , out bool hasHiddenFlag , out bool isDirectoryToHide ) ;
if ( isDirectoryToHide )
2022-06-18 00:38:09 +12:00
{
return ;
}
2023-04-28 07:11:20 +12:00
rowData . HiddenEntry = hasHiddenFlag ;
2022-06-18 00:38:09 +12:00
rowData . ReadIcon ( true ) ;
2022-09-27 06:02:18 +13:00
List < RowData > rowDatas = new ( )
{
rowData ,
} ;
2022-06-18 00:38:09 +12:00
2023-04-28 09:24:25 +12:00
ListView ? dgv = MainMenu ? . GetDataGridView ( ) ;
2022-12-05 13:27:57 +13:00
if ( dgv ! = null )
2022-06-18 00:38:09 +12:00
{
2022-12-05 13:27:57 +13:00
foreach ( ListViewItemData item in dgv . Items )
{
rowDatas . Add ( item . data ) ;
}
2022-06-18 00:38:09 +12:00
}
2023-04-17 00:17:33 +12:00
rowDatas = DirectoryHelpers . SortItems ( rowDatas ) ;
2022-06-18 00:38:09 +12:00
keyboardInput . ClearIsSelectedByKey ( ) ;
2023-04-28 09:24:25 +12:00
MainMenu ? . AddItemsToMenu ( rowDatas , null , true ) ;
MainMenu ? . OnWatcherUpdate ( ) ;
2022-06-18 00:38:09 +12:00
}
catch ( Exception ex )
{
Log . Warn ( $"Failed to {nameof(CreateItem)}: {e.FullPath}" , ex ) ;
}
}
2020-09-27 01:54:24 +12:00
}
}