2020-03-17 09:05:52 +13:00
using Microsoft.Win32 ;
2019-07-15 02:46:11 +12:00
using System ;
using System.Collections.Generic ;
using System.ComponentModel ;
using System.Diagnostics ;
using System.Drawing ;
using System.IO ;
using System.Linq ;
using System.Windows.Forms ;
using SystemTrayMenu.Controls ;
2020-03-09 01:21:15 +13:00
using SystemTrayMenu.Handler ;
2019-07-15 02:46:11 +12:00
using SystemTrayMenu.Helper ;
namespace SystemTrayMenu
{
2020-03-09 01:21:15 +13:00
class SystemTrayMenu : IDisposable
2019-07-15 02:46:11 +12:00
{
2020-03-21 09:03:47 +13:00
enum OpenCloseState { Default , Opening , Closing } ;
OpenCloseState openCloseState = OpenCloseState . Default ;
2020-03-09 01:21:15 +13:00
MessageFilter messageFilter = new MessageFilter ( ) ;
2019-07-15 02:46:11 +12:00
MenuNotifyIcon menuNotifyIcon = null ;
Menu [ ] menus = new Menu [ MenuDefines . MenusMax ] ;
BackgroundWorker worker = new BackgroundWorker ( ) ;
2020-03-14 02:31:31 +13:00
Screen screen = Screen . PrimaryScreen ;
2020-03-21 09:03:47 +13:00
WaitFastLeave fastLeave = new WaitFastLeave ( ) ;
KeyboardInput keyboardInput ;
2020-03-16 04:06:18 +13:00
DataGridView dgvFromLastMouseEvent = null ;
DataGridViewCellEventArgs cellEventArgsFromLastMouseEvent = null ;
2020-03-21 23:14:16 +13:00
int clicksInQueue = 0 ;
2020-03-16 04:06:18 +13:00
2020-03-17 02:45:19 +13:00
public SystemTrayMenu ( )
2019-07-15 02:46:11 +12:00
{
2020-03-17 09:05:52 +13:00
AppRestart . BeforeRestarting + = Dispose ;
SystemEvents . DisplaySettingsChanged + = AppRestart . ByDisplaySettings ;
menus [ 0 ] = new Menu ( Menu . MenuType . DisposedFake ) ;
2020-03-09 01:21:15 +13:00
keyboardInput = new KeyboardInput ( menus ) ;
keyboardInput . RegisterHotKey ( ) ;
2020-03-21 09:03:47 +13:00
keyboardInput . HotKeyPressed + = SwitchOpenClose ;
2020-03-09 01:21:15 +13:00
keyboardInput . ClosePressed + = MenusFadeOut ;
keyboardInput . RowSelected + = KeyboardInputRowSelected ;
void KeyboardInputRowSelected ( DataGridView dgv , int rowIndex )
2019-07-15 02:46:11 +12:00
{
2020-03-16 04:06:18 +13:00
keyboardInput . InUse = true ;
2020-03-09 01:21:15 +13:00
FadeInIfNeeded ( ) ;
CheckMenuOpenerStart ( dgv , rowIndex ) ;
2019-07-15 02:46:11 +12:00
}
2020-03-09 01:21:15 +13:00
keyboardInput . RowDeselected + = CheckMenuOpenerStop ;
keyboardInput . Cleared + = FadeHalfOrOutIfNeeded ;
2019-07-15 02:46:11 +12:00
2020-03-09 01:21:15 +13:00
menuNotifyIcon = new MenuNotifyIcon ( ) ;
2020-03-17 09:05:52 +13:00
menuNotifyIcon . Exit + = Application . Exit ;
menuNotifyIcon . Restart + = AppRestart . ByMenuNotifyIcon ;
2019-07-15 02:46:11 +12:00
menuNotifyIcon . HandleClick + = SwitchOpenClose ;
void SwitchOpenClose ( )
{
if ( Config . Path = = string . Empty )
{
//Case when Folder Dialog open
}
2020-02-22 21:51:06 +13:00
else if ( openCloseState = = OpenCloseState . Opening | |
menus [ 0 ] . Visible & & openCloseState = = OpenCloseState . Default )
2019-07-15 02:46:11 +12:00
{
2020-02-22 21:51:06 +13:00
openCloseState = OpenCloseState . Closing ;
2019-07-15 02:46:11 +12:00
MenusFadeOut ( ) ;
if ( worker . IsBusy )
{
worker . CancelAsync ( ) ;
}
2020-03-12 10:29:32 +13:00
if ( ! Menus ( ) . Any ( m = > m . Visible ) )
{
openCloseState = OpenCloseState . Default ;
}
2019-07-15 02:46:11 +12:00
}
2020-03-21 23:14:16 +13:00
else if ( worker . IsBusy )
{
if ( clicksInQueue < MenuDefines . MaxClicksInQueue )
{
clicksInQueue + + ;
while ( worker . IsBusy )
{
Application . DoEvents ( ) ;
}
clicksInQueue - - ;
SwitchOpenClose ( ) ;
}
else
{
Log . Info ( "User is clicking too often => throw event away" ) ;
}
}
2019-07-15 02:46:11 +12:00
else
{
2020-03-09 01:21:15 +13:00
openCloseState = OpenCloseState . Opening ;
2020-02-22 21:51:06 +13:00
menuNotifyIcon . LoadingStart ( ) ;
worker . RunWorkerAsync ( ) ;
2019-07-15 02:46:11 +12:00
}
}
worker . WorkerSupportsCancellation = true ;
worker . DoWork + = Worker_DoWork ;
void Worker_DoWork ( object senderDoWork ,
DoWorkEventArgs eDoWork )
{
int level = 0 ;
BackgroundWorker worker = ( BackgroundWorker ) senderDoWork ;
eDoWork . Result = ReadMenu ( worker , Config . Path , level ) ;
}
worker . RunWorkerCompleted + = Worker_RunWorkerCompleted ;
void Worker_RunWorkerCompleted ( object sender ,
RunWorkerCompletedEventArgs e )
{
2020-03-09 01:21:15 +13:00
keyboardInput . ResetSelectedByKey ( ) ;
2020-02-22 21:51:06 +13:00
menuNotifyIcon . LoadingStop ( ) ;
MenuData menuData = ( MenuData ) e . Result ;
if ( menuData . Validity = = MenuDataValidity . Valid )
2019-07-15 02:46:11 +12:00
{
2020-03-12 10:29:32 +13:00
DisposeMenu ( menus [ 0 ] ) ;
2020-02-22 21:51:06 +13:00
menus [ 0 ] = CreateMenu ( menuData , Path . GetFileName ( Config . Path ) ) ;
menus [ 0 ] . AdjustLocationAndSize ( screen ) ;
ActivateMenu ( ) ;
menus [ 0 ] . AdjustLocationAndSize ( screen ) ;
2020-03-17 09:05:52 +13:00
messageFilter . StartListening ( ) ;
2019-07-15 02:46:11 +12:00
}
2020-03-12 10:29:32 +13:00
openCloseState = OpenCloseState . Default ;
2019-07-15 02:46:11 +12:00
}
void ActivateMenu ( )
{
2020-03-21 23:37:39 +13:00
Menus ( ) . ToList ( ) . ForEach ( m = > { m . FadeIn ( ) ; m . FadeHalf ( ) ; } ) ;
2019-07-15 02:46:11 +12:00
menus [ 0 ] . SetTitleColorActive ( ) ;
menus [ 0 ] . Activate ( ) ;
WindowToTop . ForceForegroundWindow ( menus [ 0 ] . Handle ) ;
}
2020-03-17 02:45:19 +13:00
menuNotifyIcon . OpenLog + = Log . OpenLogFile ;
2019-07-15 02:46:11 +12:00
menuNotifyIcon . ChangeFolder + = ChangeFolder ;
void ChangeFolder ( )
{
if ( Config . SetFolderByUser ( ) )
{
2020-03-17 09:05:52 +13:00
AppRestart . ByConfigChange ( ) ;
2019-07-15 02:46:11 +12:00
}
}
messageFilter . MouseMove + = FadeInIfNeeded ;
2020-03-16 04:06:18 +13:00
messageFilter . MouseMove + = MessageFilter_MouseMove ;
void MessageFilter_MouseMove ( )
{
if ( keyboardInput . InUse )
{
CheckMenuOpenerStop ( keyboardInput . iMenuKey ,
keyboardInput . iRowKey ) ;
keyboardInput . ClearIsSelectedByKey ( ) ;
keyboardInput . InUse = false ;
if ( dgvFromLastMouseEvent ! = null )
{
Dgv_MouseEnter ( dgvFromLastMouseEvent ,
cellEventArgsFromLastMouseEvent ) ;
}
}
}
2019-07-15 02:46:11 +12:00
messageFilter . ScrollBarMouseMove + = FadeInIfNeeded ;
messageFilter . MouseLeave + = fastLeave . Start ;
fastLeave . Leave + = FadeHalfOrOutIfNeeded ;
}
2020-03-09 01:21:15 +13:00
2019-07-15 02:46:11 +12:00
void FadeInIfNeeded ( )
{
if ( menus [ 0 ] . Visible & &
! menus [ 0 ] . IsFadingIn & &
! menus [ 0 ] . IsFadingOut )
{
if ( Menus ( ) . Any ( m = > m . Opacity < 1 ) )
{
Menus ( ) . ToList ( ) . ForEach ( menu = > menu . FadeIn ( ) ) ;
}
}
}
void FadeHalfOrOutIfNeeded ( )
{
Point mousePosition = Control . MousePosition ;
bool isMouseOnAnyMenu =
! Menus ( ) . Any ( m = > m . IsMouseOn ( mousePosition ) ) ;
bool isAnyMenuActive = IsAnyMenuActive ( ) ;
2020-03-09 01:21:15 +13:00
if ( menus [ 0 ] . Visible & &
isMouseOnAnyMenu )
2019-07-15 02:46:11 +12:00
{
2020-02-22 21:51:06 +13:00
if ( isAnyMenuActive & &
! ( openCloseState = = OpenCloseState . Closing ) )
2019-07-15 02:46:11 +12:00
{
2020-03-16 21:38:53 +13:00
if ( ! keyboardInput . InUse )
2019-07-15 02:46:11 +12:00
{
Menus ( ) . ToList ( ) . ForEach ( menu = > menu . FadeHalf ( ) ) ;
}
}
else
{
MenusFadeOut ( ) ;
}
}
}
public void Dispose ( )
{
2020-03-09 01:21:15 +13:00
keyboardInput . Dispose ( ) ;
2019-07-15 02:46:11 +12:00
menuNotifyIcon . Dispose ( ) ;
fastLeave . Dispose ( ) ;
DisposeMenu ( menus [ 0 ] ) ;
}
void DisposeMenu ( Menu menuToDispose )
{
if ( menuToDispose ! = null )
{
DataGridView dgv = menuToDispose . GetDataGridView ( ) ;
foreach ( DataGridViewRow row in dgv . Rows )
{
RowData rowData = ( RowData ) row . Tag ;
rowData . Dispose ( ) ;
DisposeMenu ( rowData . SubMenu ) ;
}
dgv . ClearSelection ( ) ;
menuToDispose . Dispose ( ) ;
}
}
void DisposeWhenHidden ( object sender , EventArgs e )
{
Menu menuToDispose = ( Menu ) sender ;
if ( ! menuToDispose . Visible )
{
DisposeMenu ( menuToDispose ) ;
}
2020-03-17 09:05:52 +13:00
if ( ! Menus ( ) . Any ( m = > m . Visible ) )
2020-03-12 10:29:32 +13:00
{
openCloseState = OpenCloseState . Default ;
}
2019-07-15 02:46:11 +12:00
}
void AdjustSubMenusLocationAndSize ( )
{
int heightMax = screen . Bounds . Height -
new Taskbar ( ) . Size . Height ;
Menu menuPredecessor = menus [ 0 ] ;
int widthPredecessors = - 1 ; // -1 padding
bool directionToRight = false ;
2020-03-17 09:05:52 +13:00
foreach ( Menu menu in Menus ( ) . Where ( m = > m . Level > 0 ) )
2019-07-15 02:46:11 +12:00
{
2020-03-21 09:03:47 +13:00
int newWith = ( menu . Width -
menu . Padding . Horizontal + menuPredecessor . Width ) ;
2019-07-15 02:46:11 +12:00
if ( directionToRight )
{
2020-03-21 09:03:47 +13:00
if ( widthPredecessors - menu . Width < =
- menu . Padding . Horizontal )
2019-07-15 02:46:11 +12:00
{
directionToRight = false ;
}
else
{
widthPredecessors - = newWith ;
}
}
2020-03-14 02:31:31 +13:00
else if ( screen . Bounds . Width <
2019-07-15 02:46:11 +12:00
widthPredecessors + menuPredecessor . Width + menu . Width )
{
directionToRight = true ;
widthPredecessors - = newWith ;
}
menu . AdjustLocationAndSize ( heightMax ,
widthPredecessors , menuPredecessor ) ;
2020-03-21 09:03:47 +13:00
widthPredecessors + = menu . Width - menu . Padding . Left ;
2019-07-15 02:46:11 +12:00
menuPredecessor = menu ;
}
}
void OpenSubMenu ( object sender , EventArgs e )
{
RowData trigger = ( RowData ) sender ;
Menu menuTriggered = trigger . SubMenu ;
Menu menuFromTrigger = menus [ menuTriggered . Level - 1 ] ;
for ( int level = menuTriggered . Level ;
level < MenuDefines . MenusMax ; level + + )
{
if ( menus [ level ] ! = null )
{
Menu menuToClose = menus [ level ] ;
RowData oldTrigger = ( RowData ) menuToClose . Tag ;
DataGridView dgv = menuFromTrigger . GetDataGridView ( ) ;
foreach ( DataGridViewRow row in dgv . Rows )
{
RowData rowData = ( RowData ) row . Tag ;
rowData . IsSelected = false ;
}
trigger . IsSelected = true ;
dgv . ClearSelection ( ) ;
dgv . Rows [ trigger . RowIndex ] . Selected = true ;
menuToClose . FadeOut ( ) ;
menuToClose . VisibleChanged + = DisposeWhenHidden ;
menus [ level ] = null ;
}
}
2020-03-12 10:41:12 +13:00
DisposeMenu ( menus [ menuTriggered . Level ] ) ;
2019-07-15 02:46:11 +12:00
menus [ menuTriggered . Level ] = menuTriggered ;
AdjustSubMenusLocationAndSize ( ) ;
menus [ menuTriggered . Level ] . FadeIn ( ) ;
AdjustSubMenusLocationAndSize ( ) ;
IsAnyMenuActive ( ) ;
}
bool IsAnyMenuActive ( )
{
2020-03-09 01:21:15 +13:00
bool isAnyMenuActive = Form . ActiveForm is Menu ;
2019-07-15 02:46:11 +12:00
if ( ! isAnyMenuActive )
{
menus [ 0 ] . SetTitleColorDeactive ( ) ;
2020-03-09 01:21:15 +13:00
CheckMenuOpenerStop ( keyboardInput . iMenuKey ,
keyboardInput . iRowKey ) ;
keyboardInput . ClearIsSelectedByKey ( ) ;
2019-07-15 02:46:11 +12:00
}
else
{
menus [ 0 ] . SetTitleColorActive ( ) ;
}
return isAnyMenuActive ;
}
MenuData ReadMenu ( BackgroundWorker worker , string path , int level )
{
MenuData menuData = new MenuData ( ) ;
menuData . RowDatas = new List < RowData > ( ) ;
menuData . Validity = MenuDataValidity . Invalid ;
menuData . Level = level ;
if ( ! worker . CancellationPending )
{
string [ ] directories = new string [ ] { } ;
try
{
directories = Directory . GetDirectories ( path ) ;
Array . Sort ( directories , new WindowsExplorerSort ( ) ) ;
}
2019-08-03 20:29:57 +12:00
catch ( UnauthorizedAccessException )
{
2020-03-17 03:57:51 +13:00
Log . Info ( $"UnauthorizedAccessException:'{path}'" ) ;
2019-08-03 20:29:57 +12:00
}
2019-07-15 02:46:11 +12:00
catch ( Exception ex )
{
2020-03-17 03:57:51 +13:00
Log . Error ( $"path:'{path}'" , ex ) ;
2019-07-15 02:46:11 +12:00
}
foreach ( string directory in directories )
{
if ( worker ! = null & & worker . CancellationPending )
{
break ;
}
2020-03-17 03:57:51 +13:00
bool hiddenEntry = false ;
if ( FolderOptions . IsHidden ( directory , ref hiddenEntry ) )
2019-07-20 04:58:16 +12:00
{
2019-08-03 19:27:33 +12:00
continue ;
2019-07-15 02:46:11 +12:00
}
RowData menuButtonData = ReadMenuButtonData ( directory , false ) ;
menuButtonData . ContainsMenu = true ;
2019-08-03 19:27:33 +12:00
menuButtonData . HiddenEntry = hiddenEntry ;
2019-07-15 02:46:11 +12:00
string resolvedLnkPath = string . Empty ;
menuButtonData . ReadIcon ( true , ref resolvedLnkPath ) ;
menuData . RowDatas . Add ( menuButtonData ) ;
}
}
if ( ! worker . CancellationPending )
{
string [ ] files = new string [ ] { } ;
try
{
2019-11-19 08:11:55 +13:00
files = Directory . GetFiles ( path ) . Where ( p = >
! Path . GetFileName ( p ) . Equals ( "desktop.ini" , StringComparison . OrdinalIgnoreCase ) & & // Windows folder settings, e.g. Win10 "desktop.ini", Win2003 "Desktop.ini"
! Path . GetFileName ( p ) . Equals ( "thumbs.db" , StringComparison . OrdinalIgnoreCase ) // Windows thumbnail cache
2019-07-15 02:46:11 +12:00
) . ToArray ( ) ;
Array . Sort ( files , new WindowsExplorerSort ( ) ) ;
}
2020-03-17 03:57:51 +13:00
catch ( UnauthorizedAccessException )
{
Log . Info ( $"UnauthorizedAccessException:'{path}'" ) ;
menuData . Validity = MenuDataValidity . NoAccess ;
}
2019-07-15 02:46:11 +12:00
catch ( Exception ex )
{
2020-03-17 03:57:51 +13:00
Log . Error ( $"path:'{path}'" , ex ) ;
2019-07-15 02:46:11 +12:00
}
foreach ( string file in files )
{
if ( worker ! = null & & worker . CancellationPending )
2019-08-03 19:27:33 +12:00
{
2019-07-15 02:46:11 +12:00
break ;
2019-08-03 19:27:33 +12:00
}
2019-07-15 02:46:11 +12:00
2020-03-17 03:57:51 +13:00
bool hiddenEntry = false ;
if ( FolderOptions . IsHidden ( file , ref hiddenEntry ) )
2019-07-20 04:58:16 +12:00
{
2019-08-03 19:27:33 +12:00
continue ;
2019-07-15 02:46:11 +12:00
}
RowData menuButtonData = ReadMenuButtonData ( file , false ) ;
string resolvedLnkPath = string . Empty ;
if ( menuButtonData . ReadIcon ( false , ref resolvedLnkPath ) )
{
menuButtonData = ReadMenuButtonData ( resolvedLnkPath , true , menuButtonData ) ;
menuButtonData . ContainsMenu = true ;
2019-08-03 19:27:33 +12:00
menuButtonData . HiddenEntry = hiddenEntry ;
2019-07-15 02:46:11 +12:00
}
menuData . RowDatas . Add ( menuButtonData ) ;
}
}
if ( ! worker . CancellationPending )
{
if ( menuData . Validity = = MenuDataValidity . Invalid )
menuData . Validity = MenuDataValidity . Valid ;
}
return menuData ;
}
RowData ReadMenuButtonData ( string fileName ,
bool isResolvedLnk , RowData menuButtonData = null )
{
if ( menuButtonData = = null )
{
menuButtonData = new RowData ( ) ;
}
menuButtonData . IsResolvedLnk = isResolvedLnk ;
try
{
menuButtonData . FileInfo = new FileInfo ( fileName ) ;
menuButtonData . TargetFilePath = menuButtonData . FileInfo . FullName ;
if ( ! isResolvedLnk )
{
menuButtonData . SetText ( menuButtonData . FileInfo . Name ) ;
menuButtonData . TargetFilePathOrig = menuButtonData . FileInfo . FullName ;
}
}
catch ( Exception ex )
{
2020-03-17 03:57:51 +13:00
Log . Error ( $"fileName:'{fileName}'" , ex ) ;
2019-07-15 02:46:11 +12:00
}
return menuButtonData ;
}
private void Dgv_MouseDoubleClick ( object sender , MouseEventArgs e )
{
DataGridView dgv = ( DataGridView ) sender ;
DataGridView . HitTestInfo hitTestInfo ;
hitTestInfo = dgv . HitTest ( e . X , e . Y ) ;
if ( hitTestInfo . RowIndex > - 1 & &
dgv . Rows . Count > hitTestInfo . RowIndex )
{
RowData trigger = ( RowData ) dgv . Rows [ hitTestInfo . RowIndex ] . Tag ;
trigger . DoubleClick ( ) ;
}
}
private void Dgv_MouseDown ( object sender , MouseEventArgs e )
{
DataGridView dgv = ( DataGridView ) sender ;
DataGridView . HitTestInfo hitTestInfo ;
hitTestInfo = dgv . HitTest ( e . X , e . Y ) ;
if ( hitTestInfo . RowIndex > - 1 & &
dgv . Rows . Count > hitTestInfo . RowIndex )
{
RowData trigger = ( RowData ) dgv . Rows [ hitTestInfo . RowIndex ] . Tag ;
trigger . MouseDown ( dgv , e ) ;
}
}
private void Dgv_MouseEnter ( object sender , DataGridViewCellEventArgs e )
{
DataGridView dgv = ( DataGridView ) sender ;
2020-03-16 04:06:18 +13:00
dgvFromLastMouseEvent = dgv ;
cellEventArgsFromLastMouseEvent = e ;
if ( ! keyboardInput . InUse )
{
keyboardInput . ClearIsSelectedByKey ( ) ;
keyboardInput . Select ( dgv , e . RowIndex ) ;
CheckMenuOpenerStart ( dgv , e . RowIndex ) ;
}
2019-07-15 02:46:11 +12:00
}
private void CheckMenuOpenerStart ( DataGridView dgv , int rowIndex )
{
if ( rowIndex > - 1 & &
dgv . Rows . Count > rowIndex )
{
RowData trigger = ( RowData ) dgv . Rows [ rowIndex ] . Tag ;
trigger . IsSelected = true ;
dgv . Rows [ rowIndex ] . Selected = true ;
Menu menuFromTrigger = ( Menu ) dgv . FindForm ( ) ;
Menu menuTriggered = trigger . SubMenu ;
int level = menuFromTrigger . Level + 1 ;
if ( trigger . ContainsMenu & &
level < MenuDefines . MenusMax & &
! menus [ 0 ] . IsFadingOut & &
! menuFromTrigger . IsFadingOut & &
( menus [ level ] = = null | |
menus [ level ] ! = menuTriggered ) )
{
trigger . StopLoadMenuAndStartWaitToOpenIt ( ) ;
trigger . StartMenuOpener ( ) ;
if ( trigger . Reading . IsBusy )
{
trigger . RestartLoading = true ;
}
else
{
menuNotifyIcon . LoadingStart ( ) ;
trigger . Reading . RunWorkerAsync ( level ) ;
}
}
}
}
private void Dgv_MouseLeave ( object sender , DataGridViewCellEventArgs e )
{
DataGridView dgv = ( DataGridView ) sender ;
2020-03-16 04:06:18 +13:00
if ( ! keyboardInput . InUse )
{
Menu menu = ( Menu ) dgv . FindForm ( ) ;
CheckMenuOpenerStop ( menu . Level , e . RowIndex , dgv ) ;
}
dgvFromLastMouseEvent = null ;
cellEventArgsFromLastMouseEvent = null ;
2019-07-15 02:46:11 +12:00
}
private void CheckMenuOpenerStop ( int menuIndex , int rowIndex , DataGridView dgv = null )
{
Menu menu = menus [ menuIndex ] ;
2019-11-19 08:11:55 +13:00
if ( menu ! = null & &
2019-07-15 02:46:11 +12:00
rowIndex > - 1 )
{
if ( dgv = = null )
{
dgv = menu . GetDataGridView ( ) ;
}
if ( dgv . Rows . Count > rowIndex )
{
RowData trigger = ( RowData ) dgv . Rows [ rowIndex ] . Tag ;
if ( trigger . Reading . IsBusy )
{
if ( ! trigger . IsContextMenuOpen )
{
trigger . IsSelected = false ;
dgv . Rows [ rowIndex ] . Selected = false ;
}
trigger . Reading . CancelAsync ( ) ;
}
else if ( trigger . ContainsMenu & & ! trigger . IsLoading )
{
trigger . IsSelected = true ;
dgv . Rows [ rowIndex ] . Selected = true ;
}
else
{
if ( ! trigger . IsContextMenuOpen )
{
trigger . IsSelected = false ;
dgv . Rows [ rowIndex ] . Selected = false ;
}
}
if ( trigger . IsLoading )
{
trigger . StopLoadMenuAndStartWaitToOpenIt ( ) ;
trigger . IsLoading = false ;
}
}
}
}
private void Dgv_SelectionChanged ( object sender , EventArgs e )
{
DataGridView dgv = ( DataGridView ) sender ;
foreach ( DataGridViewRow row in dgv . Rows )
{
RowData rowData = ( RowData ) row . Tag ;
if ( rowData . IsSelectedByKeyboard )
{
2019-11-19 08:11:55 +13:00
row . DefaultCellStyle . SelectionBackColor =
2019-07-15 02:46:11 +12:00
MenuDefines . KeyBoardSelection ;
row . Selected = true ;
}
else if ( rowData . IsSelected )
{
2019-11-19 08:11:55 +13:00
row . DefaultCellStyle . SelectionBackColor =
2019-07-15 02:46:11 +12:00
MenuDefines . FolderOpen ;
row . Selected = true ;
}
else
{
rowData . IsSelected = false ;
row . Selected = false ;
}
}
}
IEnumerable < Menu > Menus ( )
{
2020-03-17 09:05:52 +13:00
return menus . Where ( m = > m ! = null & & ! m . IsDisposed ) ;
2019-07-15 02:46:11 +12:00
}
void MenusFadeOut ( )
{
2020-03-17 09:05:52 +13:00
messageFilter . StopListening ( ) ;
2020-03-09 01:21:15 +13:00
2019-07-15 02:46:11 +12:00
Menus ( ) . ToList ( ) . ForEach ( menu = >
{
if ( menu . Level > 0 )
{
menus [ menu . Level ] = null ;
}
menu . FadeOut ( ) ;
} ) ;
}
Menu CreateMenu ( MenuData menuData , string title = null )
{
Menu menu = new Menu ( ) ;
if ( title ! = null )
{
if ( title = = string . Empty )
{
title = Path . GetPathRoot ( Config . Path ) ;
}
menu . SetTitle ( title ) ;
menu . UserClickedOpenFolder + = OpenFolder ;
void OpenFolder ( )
{
Process . Start ( "explorer.exe" , Config . Path ) ;
}
}
menu . Level = menuData . Level ;
menu . MouseWheel + = AdjustSubMenusLocationAndSize ;
DataGridView dgv = menu . GetDataGridView ( ) ;
dgv . CellMouseEnter + = Dgv_MouseEnter ;
dgv . CellMouseLeave + = Dgv_MouseLeave ;
dgv . MouseDoubleClick + = Dgv_MouseDoubleClick ;
dgv . MouseDown + = Dgv_MouseDown ;
dgv . SelectionChanged + = Dgv_SelectionChanged ;
2020-03-09 01:21:15 +13:00
menu . KeyPress + = keyboardInput . KeyPress ;
menu . CmdKeyProcessed + = keyboardInput . CmdKeyProcessed ;
menu . Activated + = Activated ;
void Activated ( object sender , EventArgs e )
{
menus [ 0 ] . SetTitleColorActive ( ) ;
}
2019-07-15 02:46:11 +12:00
menu . Deactivated + = fastLeave . Start ;
menu . VisibleChanged + = DisposeWhenHidden ;
AddItemsToMenu ( menuData . RowDatas , menu ) ;
return menu ;
}
private void AddItemsToMenu ( List < RowData > data , Menu menu )
{
foreach ( RowData rowData in data )
{
CreateMenuRow ( rowData , menu ) ;
}
}
private void CreateMenuRow ( RowData rowData , Menu menu )
{
rowData . SetData ( rowData , menu . GetDataGridView ( ) ) ;
rowData . OpenMenu + = OpenSubMenu ;
rowData . Reading . WorkerSupportsCancellation = true ;
rowData . Reading . DoWork + = ReadMenu_DoWork ;
void ReadMenu_DoWork ( object senderDoWork ,
DoWorkEventArgs eDoWork )
{
int level = ( int ) eDoWork . Argument ;
BackgroundWorker worker = ( BackgroundWorker ) senderDoWork ;
rowData . RestartLoading = false ;
eDoWork . Result = ReadMenu ( worker , rowData . TargetFilePath , level ) ;
}
rowData . Reading . RunWorkerCompleted + = ReadMenu_RunWorkerCompleted ;
void ReadMenu_RunWorkerCompleted ( object senderCompleted ,
RunWorkerCompletedEventArgs e )
{
MenuData menuData = ( MenuData ) e . Result ;
if ( rowData . RestartLoading )
{
rowData . Reading . RunWorkerAsync ( menuData . Level ) ;
}
else
{
menuNotifyIcon . LoadingStop ( ) ;
menuNotifyIcon . LoadWait ( ) ;
if ( menuData . Validity ! = MenuDataValidity . Invalid )
{
menu = CreateMenu ( menuData ) ;
if ( menuData . RowDatas . Count > 0 )
{
menu . SetTypeSub ( ) ;
}
else if ( menuData . Validity = = MenuDataValidity . NoAccess )
{
menu . SetTypeNoAccess ( ) ;
}
else
{
menu . SetTypeEmpty ( ) ;
}
menu . Tag = rowData ;
rowData . SubMenu = menu ;
rowData . MenuLoaded ( ) ;
}
menuNotifyIcon . LoadStop ( ) ;
}
}
}
}
2019-07-05 05:04:14 +12:00
}