2022-10-23 11:02:31 +13:00
// <copyright file="Menu.xaml.cs" company="PlaceholderCompany">
2020-07-07 09:37:55 +12:00
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace SystemTrayMenu.UserInterface
2020-06-08 00:28:59 +12:00
{
2020-07-07 07:15:45 +12:00
using System ;
2022-10-23 11:02:31 +13:00
using System.Collections.Generic ;
2020-07-07 07:15:45 +12:00
using System.Globalization ;
2023-04-16 07:23:28 +12:00
using System.IO ;
2022-10-23 11:02:31 +13:00
using System.Windows ;
using System.Windows.Controls ;
using System.Windows.Data ;
using System.Windows.Input ;
using System.Windows.Media ;
using System.Windows.Threading ;
2022-12-04 10:41:03 +13:00
using SystemTrayMenu.Business ;
2020-07-07 07:15:45 +12:00
using SystemTrayMenu.DataClasses ;
using SystemTrayMenu.DllImports ;
2022-12-04 10:41:03 +13:00
using SystemTrayMenu.Properties ;
2020-07-07 07:15:45 +12:00
using SystemTrayMenu.Utilities ;
2022-11-29 08:27:52 +13:00
using KeyEventArgs = System . Windows . Input . KeyEventArgs ;
2022-10-23 11:02:31 +13:00
/// <summary>
/// Logic of Menu window.
/// </summary>
public partial class Menu : Window
2020-06-08 00:28:59 +12:00
{
2022-12-04 13:24:30 +13:00
private const int CornerRadius = 10 ;
private static readonly RoutedEvent FadeInEvent = EventManager . RegisterRoutedEvent (
nameof ( FadeIn ) , RoutingStrategy . Bubble , typeof ( RoutedEventHandler ) , typeof ( Menu ) ) ;
private static readonly RoutedEvent FadeOutEvent = EventManager . RegisterRoutedEvent (
nameof ( FadeOut ) , RoutingStrategy . Bubble , typeof ( RoutedEventHandler ) , typeof ( Menu ) ) ;
2023-04-16 07:23:28 +12:00
private readonly string folderPath ;
2022-11-30 10:48:45 +13:00
#if TODO // SEARCH
2022-06-18 23:03:28 +12:00
public const string RowFilterShowAll = "[SortIndex] LIKE '%0%'" ;
2022-10-23 11:02:31 +13:00
#endif
2022-12-04 13:24:30 +13:00
private bool isFading ;
2021-04-17 12:39:48 +12:00
private bool directionToRight ;
2021-11-25 07:01:59 +13:00
private bool mouseDown ;
private Point lastLocation ;
2022-11-30 10:48:45 +13:00
#if TODO // SEARCH
2022-02-21 06:00:04 +13:00
private bool isSetSearchText ;
2022-08-02 10:49:56 +12:00
private bool dgvHeightSet ;
2022-10-23 11:02:31 +13:00
#endif
private bool isClosed = false ; // TODO WPF Replace Forms wrapper
private DispatcherTimer timerUpdateIcons = new DispatcherTimer ( DispatcherPriority . Render , Dispatcher . CurrentDispatcher ) ;
2020-06-06 21:47:19 +12:00
2023-04-16 07:23:28 +12:00
internal Menu ( MenuData menuData , string path )
2020-06-08 00:28:59 +12:00
{
2022-10-23 11:02:31 +13:00
timerUpdateIcons . Tick + = TimerUpdateIcons_Tick ;
Closed + = ( _ , _ ) = >
{
timerUpdateIcons . Stop ( ) ;
isClosed = true ; // TODO WPF Replace Forms wrapper
} ;
2020-06-08 00:28:59 +12:00
InitializeComponent ( ) ;
2020-07-07 07:15:45 +12:00
2023-04-16 07:23:28 +12:00
folderPath = path ;
RowDataParent = menuData . RowDataParent ;
Level = menuData . Level ;
2022-12-04 09:23:19 +13:00
if ( Level = = 0 )
{
// Use Main Menu DPI for all further calculations
Scaling . CalculateFactorByDpi ( this ) ;
}
2023-04-16 07:23:28 +12:00
else
{
// This will be a submenu
if ( RowDataParent ! = null )
{
RowDataParent . SubMenu = this ;
}
}
2022-07-10 11:53:36 +12:00
2023-04-16 07:23:28 +12:00
string title = new DirectoryInfo ( path ) . Name ;
2022-12-04 09:23:19 +13:00
if ( title . Length > MenuDefines . LengthMax )
{
title = $"{title[..MenuDefines.LengthMax]}..." ;
}
txtTitle . Text = title ;
2021-06-26 23:24:56 +12:00
2022-10-23 11:02:31 +13:00
foreach ( FrameworkElement control in
new List < FrameworkElement > ( )
{
buttonMenuAlwaysOpen ,
buttonOpenFolder ,
buttonSettings ,
buttonRestart ,
pictureBoxSearch ,
pictureBoxMenuAlwaysOpen ,
pictureBoxOpenFolder ,
pictureBoxSettings ,
pictureBoxRestart ,
2022-11-14 07:12:49 +13:00
pictureBoxLoading ,
2022-10-23 11:02:31 +13:00
} )
{
control . Width = Scaling . Scale ( control . Width ) ;
control . Height = Scaling . Scale ( control . Height ) ;
}
labelTitle . FontSize = Scaling . ScaleFontByPoints ( 8.25F ) ;
textBoxSearch . FontSize = Scaling . ScaleFontByPoints ( 8.25F ) ;
2022-12-04 09:23:19 +13:00
labelStatus . FontSize = Scaling . ScaleFontByPoints ( 7F ) ;
2022-10-23 11:02:31 +13:00
dgv . FontSize = Scaling . ScaleFontByPoints ( 9F ) ;
MouseDown + = Menu_MouseDown ;
MouseUp + = Menu_MouseUp ;
MouseMove + = Menu_MouseMove ;
2022-12-01 12:16:30 +13:00
2023-04-16 04:48:53 +12:00
textBoxSearch . ContextMenu = new ( )
{
Background = SystemColors . ControlBrush ,
} ;
textBoxSearch . ContextMenu . Items . Add ( new MenuItem ( )
{
Header = Translator . GetText ( "Cut" ) ,
Command = new ActionCommand ( ( _ ) = > textBoxSearch . Cut ( ) ) ,
} ) ;
textBoxSearch . ContextMenu . Items . Add ( new MenuItem ( )
{
Header = Translator . GetText ( "Copy" ) ,
Command = new ActionCommand ( ( _ ) = > Clipboard . SetData ( DataFormats . Text , textBoxSearch . SelectedText ) ) ,
} ) ;
textBoxSearch . ContextMenu . Items . Add ( new MenuItem ( )
{
Header = Translator . GetText ( "Paste" ) ,
Command = new ActionCommand ( ( _ ) = >
{
if ( Clipboard . ContainsText ( TextDataFormat . Text ) )
{
textBoxSearch . SelectedText = Clipboard . GetData ( DataFormats . Text ) . ToString ( ) ;
}
} ) ,
} ) ;
textBoxSearch . ContextMenu . Items . Add ( new MenuItem ( )
{
Header = Translator . GetText ( "Undo" ) ,
Command = new ActionCommand ( ( _ ) = > textBoxSearch . Undo ( ) ) ,
} ) ;
textBoxSearch . ContextMenu . Items . Add ( new MenuItem ( )
{
Header = Translator . GetText ( "Select All" ) ,
Command = new ActionCommand ( ( _ ) = > textBoxSearch . SelectAll ( ) ) ,
} ) ;
2022-11-14 07:58:54 +13:00
SolidColorBrush foreColor = new ( Colors . Black ) ;
2022-10-23 11:02:31 +13:00
SolidColorBrush backColor = AppColors . Background . ToSolidColorBrush ( ) ;
SolidColorBrush backColorSearch = AppColors . SearchField . ToSolidColorBrush ( ) ;
SolidColorBrush backgroundBorder = AppColors . BackgroundBorder . ToSolidColorBrush ( ) ;
2021-06-06 23:15:01 +12:00
2022-10-23 11:02:31 +13:00
if ( Config . IsDarkMode ( ) )
2020-06-08 00:28:59 +12:00
{
2022-11-14 07:58:54 +13:00
foreColor = new ( Colors . White ) ;
2022-10-23 11:02:31 +13:00
backColor = AppColors . DarkModeBackground . ToSolidColorBrush ( ) ;
backColorSearch = AppColors . DarkModeSearchField . ToSolidColorBrush ( ) ;
backgroundBorder = AppColors . DarkModeBackgroundBorder . ToSolidColorBrush ( ) ;
2022-12-05 11:56:21 +13:00
Resources [ "ic_fluent_svgColor" ] = WPFExtensions . SolidColorBrushFromString ( Settings . Default . ColorDarkModeIcons ) ;
2022-12-04 10:41:03 +13:00
}
else
{
2022-12-05 11:56:21 +13:00
Resources [ "ic_fluent_svgColor" ] = WPFExtensions . SolidColorBrushFromString ( Settings . Default . ColorIcons ) ;
2022-10-23 11:02:31 +13:00
}
2020-06-08 00:28:59 +12:00
2022-10-23 11:02:31 +13:00
labelTitle . Foreground = foreColor ;
textBoxSearch . Foreground = foreColor ;
dgv . Foreground = foreColor ;
2022-12-04 09:23:19 +13:00
labelStatus . Foreground = MenuDefines . ColorIcons . ToSolidColorBrush ( ) ;
2022-10-23 11:02:31 +13:00
windowFrame . BorderBrush = backgroundBorder ;
windowFrame . Background = backColor ;
searchPanel . Background = backColorSearch ;
panelLine . Background = AppColors . Icons . ToSolidColorBrush ( ) ;
dgv . GotFocus + = ( _ , _ ) = > FocusTextBox ( ) ;
2022-11-30 10:48:45 +13:00
#if TODO // Misc MouseEvents
2020-06-08 00:28:59 +12:00
dgv . MouseEnter + = ControlsMouseEnter ;
labelTitle . MouseEnter + = ControlsMouseEnter ;
2021-10-29 03:29:04 +13:00
textBoxSearch . MouseEnter + = ControlsMouseEnter ;
pictureBoxOpenFolder . MouseEnter + = ControlsMouseEnter ;
2021-11-22 05:24:01 +13:00
pictureBoxMenuAlwaysOpen . MouseEnter + = ControlsMouseEnter ;
pictureBoxSettings . MouseEnter + = ControlsMouseEnter ;
pictureBoxRestart . MouseEnter + = ControlsMouseEnter ;
2021-10-29 03:29:04 +13:00
pictureBoxSearch . MouseEnter + = ControlsMouseEnter ;
2021-12-10 08:00:33 +13:00
tableLayoutPanelMenu . MouseEnter + = ControlsMouseEnter ;
tableLayoutPanelDgvAndScrollbar . MouseEnter + = ControlsMouseEnter ;
tableLayoutPanelBottom . MouseEnter + = ControlsMouseEnter ;
2022-12-04 09:23:19 +13:00
labelStatus . MouseEnter + = ControlsMouseEnter ;
2020-06-08 00:28:59 +12:00
void ControlsMouseEnter ( object sender , EventArgs e )
{
2020-06-29 06:57:03 +12:00
MouseEnter ? . Invoke ( ) ;
2020-06-08 00:28:59 +12:00
}
2020-07-07 07:15:45 +12:00
2020-06-08 00:28:59 +12:00
dgv . MouseLeave + = ControlsMouseLeave ;
labelTitle . MouseLeave + = ControlsMouseLeave ;
2021-10-29 03:29:04 +13:00
textBoxSearch . MouseLeave + = ControlsMouseLeave ;
pictureBoxMenuAlwaysOpen . MouseLeave + = ControlsMouseLeave ;
pictureBoxOpenFolder . MouseLeave + = ControlsMouseLeave ;
2021-11-22 05:24:01 +13:00
pictureBoxSettings . MouseLeave + = ControlsMouseLeave ;
pictureBoxRestart . MouseLeave + = ControlsMouseLeave ;
2021-10-29 03:29:04 +13:00
pictureBoxSearch . MouseLeave + = ControlsMouseLeave ;
2021-12-10 08:00:33 +13:00
tableLayoutPanelMenu . MouseLeave + = ControlsMouseLeave ;
tableLayoutPanelDgvAndScrollbar . MouseLeave + = ControlsMouseLeave ;
tableLayoutPanelBottom . MouseLeave + = ControlsMouseLeave ;
2022-12-04 09:23:19 +13:00
labelStatus . MouseLeave + = ControlsMouseLeave ;
2020-06-08 00:28:59 +12:00
void ControlsMouseLeave ( object sender , EventArgs e )
{
2020-06-29 06:57:03 +12:00
MouseLeave ? . Invoke ( ) ;
2020-06-08 00:28:59 +12:00
}
2022-11-30 10:48:45 +13:00
#endif
#if TODO // TOUCH
2022-05-03 05:55:15 +12:00
bool isTouchEnabled = NativeMethods . IsTouchEnabled ( ) ;
2022-12-05 13:27:57 +13:00
if ( ( isTouchEnabled & & Settings . Default . DragDropItemsEnabledTouch ) | |
( ! isTouchEnabled & & Settings . Default . DragDropItemsEnabled ) )
2022-05-03 05:55:15 +12:00
{
AllowDrop = true ;
DragEnter + = DragDropHelper . DragEnter ;
DragDrop + = DragDropHelper . DragDrop ;
}
2022-10-23 11:02:31 +13:00
#endif
Loaded + = ( sender , e ) = >
{
NativeMethods . HideFromAltTab ( this ) ;
2022-12-04 13:24:30 +13:00
RaiseEvent ( new ( routedEvent : FadeInEvent ) ) ;
2022-10-23 11:02:31 +13:00
} ;
2022-11-26 11:31:20 +13:00
Closed + = ( sender , e ) = >
{
foreach ( ListViewItemData item in dgv . Items )
{
item . data . SubMenu ? . Close ( ) ;
}
} ;
2023-04-16 07:23:28 +12:00
// This will be a submenu..
if ( Level > 0 )
{
SetBehavior ( menuData . DirectoryState ) ;
}
2020-06-08 00:28:59 +12:00
}
2022-12-04 10:41:03 +13:00
internal event Action ? MenuScrolled ;
2020-07-07 09:37:55 +12:00
2022-12-01 12:16:30 +13:00
#if TODO // Misc MouseEvents
2022-10-23 11:02:31 +13:00
internal new event Action MouseEnter ;
2020-07-07 09:37:55 +12:00
2022-10-23 11:02:31 +13:00
internal new event Action MouseLeave ;
#endif
2020-07-07 09:37:55 +12:00
2022-12-04 10:41:03 +13:00
internal event Action < Menu , Key , ModifierKeys > ? CmdKeyProcessed ;
2020-07-07 09:37:55 +12:00
2022-12-04 07:30:40 +13:00
#if TODO // Misc MouseEvents and TOUCH
2022-02-21 09:35:38 +13:00
internal event EventHandler < KeyPressEventArgs > KeyPressCheck ;
2022-12-04 07:30:40 +13:00
#endif
2022-02-21 09:35:38 +13:00
2022-12-04 10:41:03 +13:00
internal event Action ? SearchTextChanging ;
2020-07-07 09:37:55 +12:00
2022-12-04 07:30:40 +13:00
#if TODO // SEARCH
2022-06-11 23:04:21 +12:00
internal event EventHandler < bool > SearchTextChanged ;
2022-10-23 11:02:31 +13:00
#endif
2020-07-07 09:37:55 +12:00
2022-10-23 11:02:31 +13:00
internal event Action ? UserDragsMenu ;
internal event Action < ListView , int > ? CellMouseEnter ;
internal event Action < ListView , int > ? CellMouseLeave ;
internal event Action < ListView , int , MouseButtonEventArgs > ? CellMouseDown ;
internal event Action < ListView , int , MouseButtonEventArgs > ? CellMouseUp ;
internal event Action < ListView , int , MouseButtonEventArgs > ? CellMouseClick ;
2022-12-05 10:03:57 +13:00
internal event RoutedEventHandler FadeIn
2022-12-04 13:24:30 +13:00
{
add { AddHandler ( FadeInEvent , value ) ; }
remove { RemoveHandler ( FadeInEvent , value ) ; }
}
2022-12-05 10:03:57 +13:00
internal event RoutedEventHandler FadeOut
2022-12-04 13:24:30 +13:00
{
add { AddHandler ( FadeOutEvent , value ) ; }
remove { RemoveHandler ( FadeOutEvent , value ) ; }
}
2020-09-21 05:19:21 +12:00
internal enum StartLocation
{
Predecessor ,
BottomLeft ,
BottomRight ,
TopRight ,
}
2022-10-23 11:02:31 +13:00
public bool IsLoadingMenu { get ; internal set ; } // TODO State out of window
2020-07-07 09:37:55 +12:00
2022-10-23 11:02:31 +13:00
public bool IsDisposed = > isClosed ; // TODO WPF Replace Forms wrapper
2022-01-09 01:39:19 +13:00
2022-10-23 11:02:31 +13:00
public bool Disposing = > isClosed ; // TODO WPF Replace Forms wrapper
2021-12-06 05:04:48 +13:00
2022-10-23 11:02:31 +13:00
public System . Drawing . Point Location = > new System . Drawing . Point ( ( int ) Left , ( int ) Top ) ; // TODO WPF Replace Forms wrapper)
internal int Level { get ; set ; }
2023-04-16 07:23:28 +12:00
internal RowData ? RowDataParent { get ; set ; }
2022-12-04 10:41:03 +13:00
2022-12-04 13:24:30 +13:00
internal bool IsUsable = > Visibility = = Visibility . Visible & & ! isFading & & ! IsDisposed & & ! Disposing ;
2022-10-23 11:02:31 +13:00
2022-11-30 10:48:45 +13:00
#if TODO // TOUCH
2022-10-23 11:02:31 +13:00
internal bool ScrollbarVisible { get ; private set ; }
2020-06-08 00:28:59 +12:00
2022-11-04 11:35:58 +13:00
private ListView tableLayoutPanelDgvAndScrollbar = > dgv ; // TODO WPF Remove and replace with dgv
#endif
2022-12-04 13:24:30 +13:00
2021-11-11 11:39:52 +13:00
internal void ResetSearchText ( )
{
textBoxSearch . Text = string . Empty ;
2022-11-04 11:35:58 +13:00
if ( dgv . Items . Count > 0 )
2022-06-18 00:38:09 +12:00
{
2022-11-04 11:35:58 +13:00
dgv . ScrollIntoView ( dgv . Items [ 0 ] ) ;
2022-06-18 00:38:09 +12:00
}
}
internal void RefreshSearchText ( )
{
2022-11-04 11:35:58 +13:00
TextBoxSearch_TextChanged ( ) ;
if ( dgv . Items . Count > 0 )
2022-06-18 00:38:09 +12:00
{
2022-11-04 11:35:58 +13:00
dgv . ScrollIntoView ( dgv . Items [ 0 ] ) ;
2022-06-18 00:38:09 +12:00
}
2021-11-11 11:39:52 +13:00
}
2020-07-08 03:05:19 +12:00
internal void FocusTextBox ( )
2020-06-08 00:28:59 +12:00
{
2022-11-30 10:48:45 +13:00
#if TODO // SEARCH
2022-02-21 06:00:04 +13:00
if ( isSetSearchText )
{
isSetSearchText = false ;
textBoxSearch . SelectAll ( ) ;
textBoxSearch . Focus ( ) ;
textBoxSearch . SelectionStart = textBoxSearch . Text . Length ;
textBoxSearch . SelectionLength = 0 ;
}
else
{
textBoxSearch . SelectAll ( ) ;
textBoxSearch . Focus ( ) ;
}
2022-10-23 11:02:31 +13:00
#endif
2020-06-08 00:28:59 +12:00
}
2022-12-04 09:23:19 +13:00
internal void SetBehavior ( MenuDataDirectoryState state )
2020-06-08 00:28:59 +12:00
{
2022-12-04 09:23:19 +13:00
if ( ! Config . ShowDirectoryTitleAtTop )
{
txtTitle . Visibility = Visibility . Hidden ;
}
2020-06-08 00:28:59 +12:00
2022-12-04 09:23:19 +13:00
if ( ! Config . ShowSearchBar )
{
searchPanel . Visibility = Visibility . Collapsed ;
}
2020-06-08 00:28:59 +12:00
2022-12-04 09:23:19 +13:00
if ( ! ( Config . ShowCountOfElementsBelow | | state ! = MenuDataDirectoryState . Valid ) )
{
// Hide status when neither config is set nor an error message must be shown
labelStatus . Visibility = Visibility . Collapsed ;
}
2020-06-08 00:28:59 +12:00
2022-12-04 09:23:19 +13:00
if ( ! Config . ShowFunctionKeyOpenFolder )
{
buttonOpenFolder . Visibility = Visibility . Collapsed ;
}
2021-10-04 07:24:22 +13:00
2022-12-04 09:23:19 +13:00
if ( ! Config . ShowFunctionKeyPinMenu )
{
buttonMenuAlwaysOpen . Visibility = Visibility . Collapsed ;
}
if ( ! Config . ShowFunctionKeySettings )
2021-06-26 23:24:56 +12:00
{
2022-10-23 11:02:31 +13:00
buttonSettings . Visibility = Visibility . Collapsed ;
2022-12-04 09:23:19 +13:00
}
if ( ! Config . ShowFunctionKeyRestart )
{
2022-10-23 11:02:31 +13:00
buttonRestart . Visibility = Visibility . Collapsed ;
2021-06-26 23:24:56 +12:00
}
2022-12-04 09:23:19 +13:00
if ( Level = = 0 )
2020-06-08 00:28:59 +12:00
{
2022-12-04 09:23:19 +13:00
// Main Menu
textBoxSearch . TextChanged + = ( _ , _ ) = > TextBoxSearch_TextChanged ( ) ;
}
else
{
// SubMenu
buttonSettings . Visibility = Visibility . Collapsed ;
buttonRestart . Visibility = Visibility . Collapsed ;
switch ( state )
{
case MenuDataDirectoryState . Valid :
textBoxSearch . TextChanged + = ( _ , _ ) = > TextBoxSearch_TextChanged ( ) ;
buttonMenuAlwaysOpen . Visibility = Visibility . Collapsed ;
break ;
case MenuDataDirectoryState . Empty :
searchPanel . Visibility = Visibility . Collapsed ;
labelStatus . Content = Translator . GetText ( "Directory empty" ) ;
buttonMenuAlwaysOpen . Visibility = Visibility . Collapsed ;
break ;
case MenuDataDirectoryState . NoAccess :
searchPanel . Visibility = Visibility . Collapsed ;
labelStatus . Content = Translator . GetText ( "Directory inaccessible" ) ;
buttonMenuAlwaysOpen . Visibility = Visibility . Collapsed ;
break ;
case MenuDataDirectoryState . Undefined :
IsLoadingMenu = true ;
labelStatus . Content = Translator . GetText ( "loading" ) ;
buttonMenuAlwaysOpen . Visibility = Visibility . Visible ;
buttonOpenFolder . Visibility = Visibility . Collapsed ;
// Todo: use embedded resources that we can assign image in XAML already
pictureBoxLoading . Source = SystemTrayMenu . Resources . StaticResources . LoadingIcon . ToImageSource ( ) ;
pictureBoxLoading . Visibility = Visibility . Visible ;
break ;
default :
break ;
}
2020-06-08 00:28:59 +12:00
}
}
2021-12-10 08:00:33 +13:00
internal string GetSearchText ( )
{
return textBoxSearch . Text ;
}
internal void SetSearchText ( string userSearchText )
{
2022-02-21 06:00:04 +13:00
if ( ! string . IsNullOrEmpty ( userSearchText ) )
{
textBoxSearch . Text = userSearchText + "*" ;
2022-11-30 10:48:45 +13:00
#if TODO // SEARCH
2022-02-21 06:00:04 +13:00
isSetSearchText = true ;
2022-10-23 11:02:31 +13:00
#endif
2022-02-21 06:00:04 +13:00
}
2021-12-10 08:00:33 +13:00
}
2022-10-23 11:02:31 +13:00
internal bool IsMouseOn ( )
2020-06-08 00:28:59 +12:00
{
2022-10-23 11:02:31 +13:00
Point mousePos = NativeMethods . Screen . CursorPosition ;
bool isMouseOn = Visibility = = Visibility . Visible & &
mousePos . X > = 0 & & mousePos . X < Width & &
mousePos . Y > = 0 & & mousePos . Y < Height ;
2020-06-08 00:28:59 +12:00
return isMouseOn ;
}
2022-10-23 11:02:31 +13:00
internal ListView ? GetDataGridView ( ) // TODO WPF Replace Forms wrapper
2020-06-08 00:28:59 +12:00
{
return dgv ;
}
internal void ShowWithFadeOrTransparent ( bool formActiveFormIsMenu )
{
if ( formActiveFormIsMenu )
{
ShowWithFade ( ) ;
}
else
{
ShowTransparent ( ) ;
}
}
2022-12-04 13:24:30 +13:00
internal void ShowWithFade ( ) = > Fading_Show ( false ) ;
2020-06-08 00:28:59 +12:00
2022-12-04 13:24:30 +13:00
internal void ShowTransparent ( ) = > Fading_Show ( true ) ;
internal void Fading_Show ( bool transparency )
2020-06-08 00:28:59 +12:00
{
2022-12-04 13:24:30 +13:00
timerUpdateIcons . Start ( ) ;
if ( Level = = 0 )
{
Activate ( ) ;
}
else
{
ShowActivated = false ;
}
Opacity = 0D ;
Show ( ) ;
if ( Settings . Default . UseFading )
{
isFading = true ;
if ( transparency )
{
// TODO: FADING: Instead setting of opacity 100% only go up to 80% (Temporarily go to 100% as well)
RaiseEvent ( new ( routedEvent : FadeInEvent ) ) ;
}
else
{
RaiseEvent ( new ( routedEvent : FadeInEvent ) ) ;
}
}
else
{
Opacity = transparency ? 0.80D : 1D ;
FadeIn_Completed ( this , new ( ) ) ;
}
2020-06-08 00:28:59 +12:00
}
internal void HideWithFade ( )
{
2022-12-04 13:24:30 +13:00
if ( Settings . Default . UseFading )
2020-06-08 00:28:59 +12:00
{
2022-12-04 13:24:30 +13:00
isFading = true ;
// TODO: FADING: Instead starting at opacity 100% it should start with 80% due to transparency setting
RaiseEvent ( new ( routedEvent : FadeOutEvent ) ) ;
}
else
{
FadeOut_Completed ( this , new ( ) ) ;
2020-06-08 00:28:59 +12:00
}
}
2022-06-18 00:38:09 +12:00
internal void TimerUpdateIconsStart ( )
{
timerUpdateIcons . Start ( ) ;
}
2020-09-21 07:47:46 +12:00
/// <summary>
/// Update the position and size of the menu.
/// </summary>
/// <param name="bounds">Screen coordinates where the menu is allowed to be drawn in.</param>
/// <param name="menuPredecessor">Predecessor menu (when available).</param>
/// <param name="startLocation">Defines where the first menu is drawn (when no predecessor is set).</param>
2021-12-28 00:22:52 +13:00
/// <param name="isCustomLocationOutsideOfScreen">isCustomLocationOutsideOfScreen.</param>
2020-07-07 07:15:45 +12:00
internal void AdjustSizeAndLocation (
2022-11-14 07:58:54 +13:00
Rect bounds ,
2022-12-05 13:27:57 +13:00
Menu ? menuPredecessor ,
2021-12-28 00:22:52 +13:00
StartLocation startLocation ,
bool isCustomLocationOutsideOfScreen )
2020-06-08 00:28:59 +12:00
{
2021-05-29 09:23:05 +12:00
// Update the height and width
AdjustDataGridViewHeight ( menuPredecessor , bounds . Height ) ;
AdjustDataGridViewWidth ( ) ;
2022-12-05 13:27:57 +13:00
bool useCustomLocation = Settings . Default . UseCustomLocation | | lastLocation . X > 0 ;
2021-12-28 00:22:52 +13:00
bool changeDirectionWhenOutOfBounds = true ;
2021-11-25 07:01:59 +13:00
2020-09-21 05:19:21 +12:00
if ( menuPredecessor ! = null )
{
2020-09-21 06:45:12 +12:00
// Ignore start as we use predecessor
2020-09-21 05:19:21 +12:00
startLocation = StartLocation . Predecessor ;
}
2021-12-28 00:22:52 +13:00
else if ( useCustomLocation & & ! isCustomLocationOutsideOfScreen )
2021-11-25 07:01:59 +13:00
{
// Do not adjust location again because Cursor.Postion changed
2023-04-16 07:23:28 +12:00
if ( RowDataParent ! = null )
2021-11-25 07:01:59 +13:00
{
return ;
}
// Use this menu as predecessor and overwrite location with CustomLocation
menuPredecessor = this ;
2023-04-16 07:23:28 +12:00
RowDataParent = new RowData ( ) ;
2022-12-05 13:27:57 +13:00
Left = Settings . Default . CustomLocationX ;
Top = Settings . Default . CustomLocationY ;
2021-11-25 07:01:59 +13:00
directionToRight = true ;
startLocation = StartLocation . Predecessor ;
2021-12-28 00:22:52 +13:00
changeDirectionWhenOutOfBounds = false ;
2021-11-25 07:01:59 +13:00
}
2022-12-05 13:27:57 +13:00
else if ( Settings . Default . AppearAtMouseLocation )
2021-04-29 08:58:33 +12:00
{
2021-06-27 22:24:05 +12:00
// Do not adjust location again because Cursor.Postion changed
2023-04-16 07:23:28 +12:00
if ( RowDataParent ! = null )
2021-06-27 22:24:05 +12:00
{
return ;
}
// Use this menu as predecessor and overwrite location with Cursor.Postion
2021-04-29 08:58:33 +12:00
menuPredecessor = this ;
2023-04-16 07:23:28 +12:00
RowDataParent = new RowData ( ) ;
2022-10-23 11:02:31 +13:00
var position = Mouse . GetPosition ( this ) ;
Left = position . X ;
Top = position . Y - labelTitle . Height ;
2021-04-29 08:58:33 +12:00
directionToRight = true ;
startLocation = StartLocation . Predecessor ;
2021-12-28 00:22:52 +13:00
changeDirectionWhenOutOfBounds = false ;
2021-04-29 08:58:33 +12:00
}
2020-09-21 05:19:21 +12:00
2022-12-01 12:16:30 +13:00
if ( IsLoaded )
{
AdjustSizeAndLocationInternal ( ) ;
}
else
{
// Layout cannot be calculated during loading, postpone this event
// TODO: Make sure lampa capture is registered only once
Loaded + = ( _ , _ ) = > AdjustSizeAndLocationInternal ( ) ;
}
void AdjustSizeAndLocationInternal ( )
2020-06-08 00:28:59 +12:00
{
2022-10-23 11:02:31 +13:00
// Calculate X position
double x ;
switch ( startLocation )
{
case StartLocation . Predecessor :
double scaling = Math . Round ( Scaling . Factor , 0 , MidpointRounding . AwayFromZero ) ;
directionToRight = menuPredecessor ! . directionToRight ; // try keeping same direction
if ( directionToRight )
2020-09-21 06:45:12 +12:00
{
2022-10-23 11:02:31 +13:00
x = menuPredecessor . Location . X + menuPredecessor . Width - scaling ;
if ( changeDirectionWhenOutOfBounds & &
bounds . X + bounds . Width < = x + Width - scaling )
2022-02-23 04:52:02 +13:00
{
2022-10-23 11:02:31 +13:00
x = menuPredecessor . Location . X - Width + scaling ;
if ( x < bounds . X & &
menuPredecessor . Location . X + menuPredecessor . Width < bounds . X + bounds . Width & &
bounds . X + ( bounds . Width / 2 ) > menuPredecessor . Location . X + ( Width / 2 ) )
2022-02-23 04:52:02 +13:00
{
2022-10-23 11:02:31 +13:00
x = bounds . X + bounds . Width - Width + scaling ;
2022-02-23 04:52:02 +13:00
}
2022-10-23 11:02:31 +13:00
else
{
if ( x < bounds . X )
{
x = bounds . X ;
}
2022-02-23 04:52:02 +13:00
2022-10-23 11:02:31 +13:00
directionToRight = ! directionToRight ;
}
2022-02-23 04:52:02 +13:00
}
2020-09-21 06:45:12 +12:00
}
2022-10-23 11:02:31 +13:00
else
2020-09-21 06:45:12 +12:00
{
2022-10-23 11:02:31 +13:00
x = menuPredecessor . Location . X - Width + scaling ;
if ( changeDirectionWhenOutOfBounds & &
x < bounds . X )
2022-02-23 04:52:02 +13:00
{
2022-10-23 11:02:31 +13:00
x = menuPredecessor . Location . X + menuPredecessor . Width - scaling ;
if ( x + Width > bounds . X + bounds . Width & &
menuPredecessor . Location . X > bounds . X & &
bounds . X + ( bounds . Width / 2 ) < menuPredecessor . Location . X + ( Width / 2 ) )
2022-02-23 04:52:02 +13:00
{
2022-10-23 11:02:31 +13:00
x = bounds . X ;
2022-02-23 04:52:02 +13:00
}
2022-10-23 11:02:31 +13:00
else
{
if ( x + Width > bounds . X + bounds . Width )
{
x = bounds . X + bounds . Width - Width + scaling ;
}
2022-02-23 04:52:02 +13:00
2022-10-23 11:02:31 +13:00
directionToRight = ! directionToRight ;
}
2022-02-23 04:52:02 +13:00
}
2020-09-21 06:45:12 +12:00
}
2020-06-08 00:28:59 +12:00
2022-10-23 11:02:31 +13:00
break ;
case StartLocation . BottomLeft :
x = bounds . X ;
directionToRight = true ;
break ;
case StartLocation . TopRight :
case StartLocation . BottomRight :
default :
x = bounds . Width - Width ;
directionToRight = false ;
break ;
2022-01-16 02:44:56 +13:00
}
2022-10-23 11:02:31 +13:00
// X position for click, remove width of this menu as it is used as predecessor
if ( menuPredecessor = = this & & directionToRight )
2022-01-16 02:44:56 +13:00
{
2022-10-23 11:02:31 +13:00
x - = Width ;
2022-01-16 02:44:56 +13:00
}
2022-10-23 11:02:31 +13:00
if ( Level ! = 0 & &
2022-12-05 13:27:57 +13:00
! Settings . Default . AppearNextToPreviousMenu & &
menuPredecessor ! = null & & menuPredecessor . Width > Settings . Default . OverlappingOffsetPixels )
2022-10-23 11:02:31 +13:00
{
if ( directionToRight )
2020-09-21 05:19:21 +12:00
{
2022-12-05 13:27:57 +13:00
x = x - menuPredecessor . Width + Settings . Default . OverlappingOffsetPixels ;
2020-09-21 05:19:21 +12:00
}
2022-10-23 11:02:31 +13:00
else
2021-06-26 23:24:56 +12:00
{
2022-12-05 13:27:57 +13:00
x = x + menuPredecessor . Width - Settings . Default . OverlappingOffsetPixels ;
2021-06-26 23:24:56 +12:00
}
2022-10-23 11:02:31 +13:00
}
2021-06-26 23:24:56 +12:00
2022-10-23 11:02:31 +13:00
// Calculate Y position
double y ;
switch ( startLocation )
{
case StartLocation . Predecessor :
2020-09-21 05:19:21 +12:00
2023-04-16 07:23:28 +12:00
RowData trigger = RowDataParent ;
2022-12-04 13:24:30 +13:00
ListView dgv = menuPredecessor ! . GetDataGridView ( ) ! ;
2020-06-08 00:28:59 +12:00
2022-10-23 11:02:31 +13:00
// Set position on same height as the selected row from predecessor
y = menuPredecessor . Location . Y ;
if ( dgv . Items . Count > trigger . RowIndex )
{
2022-12-01 12:16:30 +13:00
// When item is not found, it might be invalidated due to resizing or moving
// After updating the layout the location should be available again.
2022-12-03 07:34:24 +13:00
// It also makes sure all height and location information is up to date
2022-12-01 12:16:30 +13:00
menuPredecessor . UpdateLayout ( ) ;
2022-12-03 07:34:24 +13:00
// When scrolled, we have to reduce the index number as we calculate based on visual tree
int startIndex = 0 ;
double offset = 0D ;
ScrollViewer ? scrollViewer = ( VisualTreeHelper . GetChild ( dgv , 0 ) as Decorator ) ? . Child as ScrollViewer ;
if ( scrollViewer ! = null )
{
startIndex = ( int ) scrollViewer . VerticalOffset ;
if ( trigger . RowIndex < startIndex )
2022-12-01 12:16:30 +13:00
{
2022-12-03 07:34:24 +13:00
// calculate position above starting point
for ( int i = trigger . RowIndex ; i < startIndex ; i + + )
2022-12-01 12:16:30 +13:00
{
2022-12-03 07:34:24 +13:00
ListViewItem ? item = dgv . FindVisualChildOfType < ListViewItem > ( i ) ;
if ( item ! = null )
2022-12-01 12:16:30 +13:00
{
2022-12-03 07:34:24 +13:00
offset - = item . ActualHeight ;
2022-12-01 12:16:30 +13:00
}
}
}
2022-12-03 07:34:24 +13:00
}
2022-12-01 12:16:30 +13:00
2022-12-03 07:34:24 +13:00
if ( startIndex < trigger . RowIndex )
{
// calculate position below starting point
for ( int i = startIndex ; i < trigger . RowIndex ; i + + )
2022-12-01 12:16:30 +13:00
{
ListViewItem ? item = dgv . FindVisualChildOfType < ListViewItem > ( i ) ;
if ( item ! = null )
{
offset + = item . ActualHeight ;
}
}
2022-10-23 11:02:31 +13:00
}
2022-12-03 07:34:24 +13:00
2022-12-03 14:14:15 +13:00
if ( offset < 0 )
{
// Do not allow to show window higher than previous window
offset = 0 ;
}
else
{
double offsetList = menuPredecessor . GetRelativeChildPositionTo ( dgv ) . Y ;
offsetList + = dgv . ActualHeight ;
if ( offsetList < offset )
{
// Do not allow to show window below last entry position of list
offset = offsetList ;
}
}
y + = ( int ) offset ;
2022-10-23 11:02:31 +13:00
}
2021-11-14 07:44:32 +13:00
2022-12-03 14:14:15 +13:00
if ( searchPanel . Visibility = = Visibility . Collapsed )
2022-10-23 11:02:31 +13:00
{
2022-12-03 14:14:15 +13:00
y + = menuPredecessor . searchPanel . ActualHeight ;
2022-10-23 11:02:31 +13:00
}
// Move vertically when out of bounds
if ( bounds . Y + bounds . Height < y + Height )
{
y = bounds . Y + bounds . Height - Height ;
}
2022-12-03 07:34:24 +13:00
else if ( y < bounds . Y )
{
y = bounds . Y ;
}
2022-10-23 11:02:31 +13:00
break ;
case StartLocation . TopRight :
y = bounds . Y ;
break ;
case StartLocation . BottomLeft :
case StartLocation . BottomRight :
default :
y = bounds . Height - Height ;
break ;
2021-11-19 09:12:03 +13:00
}
2021-12-11 08:35:00 +13:00
2022-10-23 11:02:31 +13:00
// Update position
Left = x ;
Top = y ;
2022-12-05 13:27:57 +13:00
if ( Settings . Default . RoundCorners )
2021-12-11 08:35:00 +13:00
{
2022-10-23 11:02:31 +13:00
windowFrame . CornerRadius = new CornerRadius ( CornerRadius ) ;
2021-12-11 08:35:00 +13:00
}
2022-11-30 10:48:45 +13:00
// Keep its size when once created.
SizeToContent = SizeToContent . Manual ;
2022-12-01 12:16:30 +13:00
}
2020-06-08 00:28:59 +12:00
}
2022-08-02 10:49:56 +12:00
internal void ResetHeight ( )
{
2022-12-01 12:16:30 +13:00
if ( IsLoaded )
{
// TODO: WPF Check if this "reset" works
SizeToContent = SizeToContent . WidthAndHeight ;
UpdateLayout ( ) ;
SizeToContent = SizeToContent . Manual ;
2022-11-30 10:48:45 +13:00
#if TODO // SEARCH
2022-12-04 13:24:30 +13:00
dgvHeightSet = false ;
2022-10-23 11:02:31 +13:00
#endif
2022-12-01 12:16:30 +13:00
}
2022-08-02 10:49:56 +12:00
}
2021-06-28 01:42:34 +12:00
internal void SetCounts ( int foldersCount , int filesCount )
{
2021-12-10 08:00:33 +13:00
int filesAndFoldersCount = foldersCount + filesCount ;
2021-12-11 08:35:00 +13:00
string elements = filesAndFoldersCount = = 1 ? "element" : "elements" ;
2022-12-04 09:23:19 +13:00
labelStatus . Content = $"{filesAndFoldersCount} {Translator.GetText(elements)}" ;
2021-06-28 01:42:34 +12:00
}
2022-12-04 13:24:30 +13:00
private void FadeIn_Completed ( object sender , EventArgs e )
{
isFading = false ;
}
private void FadeOut_Completed ( object sender , EventArgs e )
{
isFading = false ;
Hide ( ) ;
}
2022-11-29 08:27:52 +13:00
private void HandlePreviewKeyDown ( object sender , KeyEventArgs e )
2020-07-08 03:05:19 +12:00
{
2022-12-04 13:24:30 +13:00
searchPanel . Visibility = Visibility . Visible ;
2022-12-03 14:14:15 +13:00
2022-11-29 08:27:52 +13:00
ModifierKeys modifiers = Keyboard . Modifiers ;
switch ( e . Key )
2020-07-08 03:05:19 +12:00
{
2022-11-29 08:27:52 +13:00
case Key . F4 :
if ( modifiers ! = ModifierKeys . Alt )
{
return ;
}
break ;
case Key . F :
if ( modifiers ! = ModifierKeys . Control )
{
return ;
}
break ;
case Key . Tab :
if ( ( modifiers ! = ModifierKeys . Shift ) & & ( modifiers ! = ModifierKeys . None ) )
{
return ;
}
break ;
2022-10-23 11:02:31 +13:00
case Key . Enter :
case Key . Home :
case Key . End :
case Key . Up :
case Key . Down :
case Key . Left :
case Key . Right :
case Key . Escape :
case Key . Apps :
2022-11-29 08:27:52 +13:00
if ( modifiers ! = ModifierKeys . None )
{
return ;
}
2020-07-08 03:05:19 +12:00
break ;
2022-11-29 08:27:52 +13:00
default :
return ;
2020-07-08 03:05:19 +12:00
}
2022-11-29 08:27:52 +13:00
CmdKeyProcessed ? . Invoke ( this , e . Key , modifiers ) ;
e . Handled = true ;
2020-07-08 03:05:19 +12:00
}
2022-11-29 08:27:52 +13:00
2022-12-05 13:27:57 +13:00
private void AdjustDataGridViewHeight ( Menu ? menuPredecessor , double screenHeightMax )
2020-09-21 07:47:46 +12:00
{
2022-12-05 13:27:57 +13:00
double factor = Settings . Default . RowHeighteInPercentage / 100f ;
2020-09-21 07:47:46 +12:00
if ( NativeMethods . IsTouchEnabled ( ) )
{
2022-12-05 13:27:57 +13:00
factor = Settings . Default . RowHeighteInPercentageTouch / 100f ;
2020-09-21 07:47:46 +12:00
}
if ( menuPredecessor = = null )
{
2022-10-23 11:02:31 +13:00
if ( dgv . Tag = = null & & dgv . Items . Count > 0 )
2020-09-21 07:47:46 +12:00
{
2022-07-28 07:35:09 +12:00
// dgv.AutoResizeRows(); slightly incorrect depending on dpi
// 100% = 20 instead 21
// 125% = 23 instead 27, 150% = 28 instead 32
// 175% = 33 instead 37, 200% = 35 instead 42
// #418 use 21 as default and scale it manually
2022-10-23 11:02:31 +13:00
double rowHeightDefault = 21.24f * Scaling . FactorByDpi ;
2022-11-10 11:34:27 +13:00
Resources [ "RowHeight" ] = ( double ) ( int ) ( ( rowHeightDefault * factor * Scaling . Factor ) + 0.5 ) ;
2020-09-21 07:47:46 +12:00
dgv . Tag = true ;
}
}
else
{
// Take over the height from predecessor menu
2022-11-10 12:18:21 +13:00
Resources [ "RowHeight" ] = menuPredecessor . Resources [ "RowHeight" ] ;
2020-09-21 07:47:46 +12:00
dgv . Tag = true ;
}
2022-11-30 10:48:45 +13:00
#if TODO // SEARCH
2022-10-08 23:50:47 +13:00
if ( ! dgvHeightSet & & dgvHeightByItems > 0 & & dgvHeightMax > 0 )
2020-09-21 07:47:46 +12:00
{
2022-10-23 11:02:31 +13:00
#endif
double heightMaxByOptions = Scaling . Factor * Scaling . FactorByDpi *
2022-12-05 13:27:57 +13:00
450f * ( Settings . Default . HeightMaxInPercent / 100f ) ;
2022-10-23 11:02:31 +13:00
MaxHeight = Math . Min ( screenHeightMax , heightMaxByOptions ) ;
2022-11-30 10:48:45 +13:00
#if TODO // SEARCH
2022-08-02 10:49:56 +12:00
dgvHeightSet = true ;
2021-06-03 22:52:47 +12:00
}
2022-10-23 11:02:31 +13:00
#endif
2022-11-30 10:48:45 +13:00
#if TODO // SEARCH and TOUCH
2022-08-02 10:49:56 +12:00
if ( dgvHeightByItems > dgvHeightMax )
2021-06-03 22:52:47 +12:00
{
2022-08-02 10:49:56 +12:00
ScrollbarVisible = true ;
2021-06-03 22:52:47 +12:00
}
else
{
2021-12-31 00:36:00 +13:00
ScrollbarVisible = false ;
2021-06-03 22:52:47 +12:00
}
2022-10-23 11:02:31 +13:00
#endif
2020-09-21 07:47:46 +12:00
}
2020-06-08 00:28:59 +12:00
private void AdjustDataGridViewWidth ( )
{
2022-06-18 00:38:09 +12:00
if ( ! string . IsNullOrEmpty ( textBoxSearch . Text ) )
2020-06-08 00:28:59 +12:00
{
2022-06-18 00:38:09 +12:00
return ;
2020-06-08 00:28:59 +12:00
}
2022-12-05 13:27:57 +13:00
double factorIconSizeInPercent = Settings . Default . IconSizeInPercent / 100f ;
2022-12-04 13:24:30 +13:00
2022-10-23 11:02:31 +13:00
// IcoWidth 100% = 21px, 175% is 33, +3+2 is padding from ColumnIcon
double icoWidth = ( 16 * Scaling . FactorByDpi ) + 5 ;
2022-11-10 11:34:27 +13:00
Resources [ "ColumnIconWidth" ] = ( double ) ( int ) ( ( icoWidth * factorIconSizeInPercent * Scaling . Factor ) + 0.5 ) ;
2022-06-18 00:38:09 +12:00
2022-10-23 11:02:31 +13:00
double renderedMaxWidth = 0D ;
foreach ( ListViewItemData item in dgv . Items )
{
double renderedWidth = new FormattedText (
item . ColumnText ,
CultureInfo . CurrentCulture ,
FlowDirection . LeftToRight ,
new Typeface ( dgv . FontFamily , dgv . FontStyle , dgv . FontWeight , dgv . FontStretch ) ,
dgv . FontSize ,
dgv . Foreground ,
VisualTreeHelper . GetDpi ( this ) . PixelsPerDip ) . Width ;
if ( renderedWidth > renderedMaxWidth )
{
renderedMaxWidth = renderedWidth ;
}
}
Resources [ "ColumnTextWidth" ] = Math . Min (
renderedMaxWidth ,
2022-12-05 13:27:57 +13:00
( double ) ( Scaling . Factor * Scaling . FactorByDpi * 400f * ( Settings . Default . WidthMaxInPercent / 100f ) ) ) ;
2020-06-08 00:28:59 +12:00
}
2022-12-01 12:16:30 +13:00
private void HandleScrollChanged ( object sender , ScrollChangedEventArgs e )
2020-06-08 00:28:59 +12:00
{
2022-12-01 12:16:30 +13:00
if ( IsLoaded )
{
2022-12-03 14:14:15 +13:00
MenuScrolled ? . Invoke ( ) ;
2022-12-01 12:16:30 +13:00
}
2020-06-08 00:28:59 +12:00
}
2022-12-01 12:16:30 +13:00
2022-12-04 07:30:40 +13:00
#if TODO // Misc MouseEvents and TOUCH
2022-02-21 09:35:38 +13:00
private void TextBoxSearch_KeyPress ( object sender , KeyPressEventArgs e )
{
KeyPressCheck ? . Invoke ( sender , e ) ;
}
2022-10-23 11:02:31 +13:00
#endif
2022-11-04 11:35:58 +13:00
private void TextBoxSearch_TextChanged ( )
2020-06-08 00:28:59 +12:00
{
2020-06-29 06:56:03 +12:00
SearchTextChanging ? . Invoke ( ) ;
2020-06-08 00:28:59 +12:00
2022-12-04 07:30:40 +13:00
string? userPattern = textBoxSearch . Text ? . Replace ( "%" , " " ) . Replace ( "*" , " " ) . ToLower ( ) ;
2022-01-31 04:52:42 +13:00
2022-11-04 11:35:58 +13:00
CollectionView view = ( CollectionView ) CollectionViewSource . GetDefaultView ( dgv . ItemsSource ) ;
2022-12-04 07:30:40 +13:00
if ( string . IsNullOrEmpty ( userPattern ) )
2022-11-04 11:35:58 +13:00
{
view . Filter = null ;
}
else
{
2022-12-04 07:30:40 +13:00
// Instead implementing in-string wildcards, simply split into multiple search patters
view . Filter = ( object item ) = >
2022-11-04 11:35:58 +13:00
{
2022-12-04 07:30:40 +13:00
// Look for each space separated string if it is part of an entries text (case insensitive)
2022-11-04 11:35:58 +13:00
ListViewItemData row = ( ListViewItemData ) item ;
2022-12-04 07:30:40 +13:00
foreach ( string pattern in userPattern . Split ( ' ' , StringSplitOptions . TrimEntries | StringSplitOptions . RemoveEmptyEntries ) )
{
if ( ! row . ColumnText . ToLower ( ) . Contains ( pattern ) )
{
return false ;
}
}
return true ;
} ;
2021-04-15 09:12:14 +12:00
}
2021-04-15 07:06:54 +12:00
2022-12-04 07:30:40 +13:00
#if TODO // SEARCH
DataTable data = ( DataTable ) dgv . DataSource ;
2022-01-08 23:39:23 +13:00
string columnSortIndex = "SortIndex" ;
2022-12-04 07:30:40 +13:00
if ( string . IsNullOrEmpty ( userPattern ) )
2020-06-08 00:28:59 +12:00
{
2022-01-31 01:51:23 +13:00
foreach ( DataRow row in data . Rows )
2022-01-08 23:39:23 +13:00
{
2022-01-31 01:51:23 +13:00
RowData rowData = ( RowData ) row [ 2 ] ;
2022-12-05 13:27:57 +13:00
if ( rowData . IsAddionalItem & & Settings . Default . ShowOnlyAsSearchResult )
2022-01-08 23:39:23 +13:00
{
2022-01-31 01:51:23 +13:00
row [ columnSortIndex ] = 99 ;
}
else
{
row [ columnSortIndex ] = 0 ;
2022-01-08 23:39:23 +13:00
}
}
2022-01-31 01:51:23 +13:00
data . DefaultView . Sort = string . Empty ;
data . AcceptChanges ( ) ;
2021-04-15 07:06:54 +12:00
}
else
{
foreach ( DataRow row in data . Rows )
{
if ( row [ 1 ] . ToString ( ) . StartsWith (
2021-04-15 09:12:14 +12:00
searchString ,
2021-04-15 07:06:54 +12:00
StringComparison . InvariantCultureIgnoreCase ) )
{
row [ columnSortIndex ] = 0 ;
}
else
{
row [ columnSortIndex ] = 1 ;
}
}
data . DefaultView . Sort = columnSortIndex ;
2020-06-08 00:28:59 +12:00
}
2021-06-28 00:44:12 +12:00
int foldersCount = 0 ;
int filesCount = 0 ;
2021-10-22 08:28:58 +13:00
bool anyIconNotUpdated = false ;
2021-06-28 00:44:12 +12:00
2021-04-17 09:14:39 +12:00
foreach ( DataGridViewRow row in dgv . Rows )
{
RowData rowData = ( RowData ) row . Cells [ 2 ] . Value ;
2021-06-28 00:44:12 +12:00
2022-12-04 07:30:40 +13:00
if ( ! string . IsNullOrEmpty ( userPattern ) | |
2022-12-05 13:27:57 +13:00
! ( rowData . IsAddionalItem & & Settings . Default . ShowOnlyAsSearchResult ) )
2021-06-28 00:44:12 +12:00
{
2022-01-08 23:39:23 +13:00
rowData . RowIndex = row . Index ;
2021-10-22 08:28:58 +13:00
2022-01-08 23:39:23 +13:00
if ( rowData . ContainsMenu )
{
foldersCount + + ;
}
else
{
filesCount + + ;
}
if ( rowData . IconLoading )
{
anyIconNotUpdated = true ;
}
2021-10-22 08:28:58 +13:00
}
2021-04-17 09:14:39 +12:00
}
2021-06-28 00:44:12 +12:00
SetCounts ( foldersCount , filesCount ) ;
2022-12-04 07:30:40 +13:00
SearchTextChanged . Invoke ( this , string . IsNullOrEmpty ( userPattern ) ) ;
2021-10-22 08:28:58 +13:00
if ( anyIconNotUpdated )
{
timerUpdateIcons . Start ( ) ;
}
2022-01-31 04:52:42 +13:00
2022-06-11 21:26:47 +12:00
if ( dgv . Rows . Count > 0 )
2022-01-31 04:52:42 +13:00
{
dgv . FirstDisplayedScrollingRowIndex = 0 ;
}
2022-10-23 11:02:31 +13:00
#endif
2020-06-08 00:28:59 +12:00
}
2021-06-26 23:24:56 +12:00
2022-12-04 10:41:03 +13:00
#if TODO // Misc MouseEvents and BorderColors
2021-11-22 05:24:01 +13:00
private void PictureBoxOpenFolder_Paint ( object sender , PaintEventArgs e )
2021-06-26 23:24:56 +12:00
{
2021-06-27 21:35:07 +12:00
PictureBox pictureBox = ( PictureBox ) sender ;
2021-06-26 23:24:56 +12:00
2021-11-22 05:24:01 +13:00
if ( pictureBox . Tag ! = null & & ( bool ) pictureBox . Tag )
{
Rectangle rowBounds = new ( 0 , 0 , pictureBox . Width , pictureBox . Height ) ;
ControlPaint . DrawBorder ( e . Graphics , rowBounds , MenuDefines . ColorSelectedItemBorder , ButtonBorderStyle . Solid ) ;
}
2021-06-28 00:44:12 +12:00
}
2022-10-23 11:02:31 +13:00
#endif
2021-06-28 00:44:12 +12:00
2022-10-23 11:02:31 +13:00
private void PictureBoxOpenFolder_Click ( object sender , RoutedEventArgs e )
2021-06-28 00:44:12 +12:00
{
2023-04-16 07:23:28 +12:00
Menus . OpenFolder ( folderPath ) ;
2021-06-28 00:44:12 +12:00
}
2022-11-30 10:48:45 +13:00
#if TODO // BorderColors
2021-06-26 23:24:56 +12:00
private void PictureBoxMenuAlwaysOpen_Paint ( object sender , PaintEventArgs e )
{
PictureBox pictureBox = ( PictureBox ) sender ;
if ( pictureBox . Tag ! = null & & ( bool ) pictureBox . Tag )
{
2021-11-17 12:13:46 +13:00
Rectangle rowBounds = new ( 0 , 0 , pictureBox . Width , pictureBox . Height ) ;
2021-06-26 23:24:56 +12:00
ControlPaint . DrawBorder ( e . Graphics , rowBounds , MenuDefines . ColorSelectedItemBorder , ButtonBorderStyle . Solid ) ;
}
}
2022-10-23 11:02:31 +13:00
#endif
private void PictureBoxMenuAlwaysOpen_Click ( object sender , RoutedEventArgs e )
2021-10-04 07:24:22 +13:00
{
2022-10-23 11:02:31 +13:00
if ( Config . AlwaysOpenByPin = ! Config . AlwaysOpenByPin )
{
pictureBoxMenuAlwaysOpen . Source = ( DrawingImage ) Resources [ "ic_fluent_pin_48_filledDrawingImage" ] ;
}
else
{
pictureBoxMenuAlwaysOpen . Source = ( DrawingImage ) Resources [ "ic_fluent_pin_48_regularDrawingImage" ] ;
}
2021-10-04 07:24:22 +13:00
}
2022-11-30 10:48:45 +13:00
#if TODO // BorderColors
2021-11-22 05:24:01 +13:00
private void PictureBoxSettings_Paint ( object sender , PaintEventArgs e )
2021-06-26 23:24:56 +12:00
{
PictureBox pictureBox = ( PictureBox ) sender ;
if ( pictureBox . Tag ! = null & & ( bool ) pictureBox . Tag )
{
2021-11-17 12:13:46 +13:00
Rectangle rowBounds = new ( 0 , 0 , pictureBox . Width , pictureBox . Height ) ;
2021-06-26 23:24:56 +12:00
ControlPaint . DrawBorder ( e . Graphics , rowBounds , MenuDefines . ColorSelectedItemBorder , ButtonBorderStyle . Solid ) ;
}
}
2022-10-23 11:02:31 +13:00
#endif
private void PictureBoxSettings_MouseClick ( object sender , RoutedEventArgs e )
2021-11-22 05:24:01 +13:00
{
2022-10-23 11:02:31 +13:00
SettingsWindow . ShowSingleInstance ( ) ;
2021-11-22 05:24:01 +13:00
}
2022-11-30 10:48:45 +13:00
#if TODO // BorderColors
2021-11-22 05:24:01 +13:00
private void PictureBoxRestart_Paint ( object sender , PaintEventArgs e )
2021-06-26 23:24:56 +12:00
{
PictureBox pictureBox = ( PictureBox ) sender ;
2021-11-22 05:24:01 +13:00
if ( pictureBox . Tag ! = null & & ( bool ) pictureBox . Tag )
{
Rectangle rowBounds = new ( 0 , 0 , pictureBox . Width , pictureBox . Height ) ;
ControlPaint . DrawBorder ( e . Graphics , rowBounds , MenuDefines . ColorSelectedItemBorder , ButtonBorderStyle . Solid ) ;
}
2021-06-26 23:24:56 +12:00
}
2022-10-23 11:02:31 +13:00
#endif
private void PictureBoxRestart_MouseClick ( object sender , RoutedEventArgs e )
2021-06-26 23:24:56 +12:00
{
2022-10-23 11:02:31 +13:00
AppRestart . ByMenuButton ( ) ;
2021-06-26 23:24:56 +12:00
}
2021-09-24 08:53:46 +12:00
2022-10-23 11:02:31 +13:00
private void TimerUpdateIcons_Tick ( object? sender , EventArgs e )
2021-09-24 08:53:46 +12:00
{
int iconsToUpdate = 0 ;
2022-10-23 11:02:31 +13:00
foreach ( Menu . ListViewItemData row in dgv . Items )
2021-09-24 08:53:46 +12:00
{
2022-10-23 11:02:31 +13:00
RowData rowData = row . data ;
rowData . RowIndex = dgv . Items . IndexOf ( row ) ;
2021-09-24 08:53:46 +12:00
if ( rowData . IconLoading )
{
iconsToUpdate + + ;
2022-12-05 13:27:57 +13:00
rowData . ReadIcon ( false ) ;
if ( rowData . Icon ! = null )
{
row . ColumnIcon = rowData . Icon . ToImageSource ( ) ;
}
2021-09-24 08:53:46 +12:00
}
}
if ( iconsToUpdate < 1 )
{
timerUpdateIcons . Stop ( ) ;
}
2022-11-10 11:34:27 +13:00
else
{
( ( CollectionView ) CollectionViewSource . GetDefaultView ( dgv . ItemsSource ) ) . Refresh ( ) ;
}
2021-09-24 08:53:46 +12:00
}
2021-11-25 07:01:59 +13:00
2022-10-23 11:02:31 +13:00
private void Menu_MouseDown ( object sender , MouseButtonEventArgs e )
2021-11-25 07:01:59 +13:00
{
2021-12-10 08:00:33 +13:00
if ( Level = = 0 )
{
mouseDown = true ;
2022-10-23 11:02:31 +13:00
lastLocation = NativeMethods . Screen . CursorPosition ;
UserDragsMenu ? . Invoke ( ) ;
2021-12-10 08:00:33 +13:00
}
2021-11-25 07:01:59 +13:00
}
private void Menu_MouseMove ( object sender , MouseEventArgs e )
{
if ( mouseDown )
{
2022-10-23 11:02:31 +13:00
Point mousePos = NativeMethods . Screen . CursorPosition ;
Left = Left + mousePos . X - lastLocation . X ;
Top = Top + mousePos . Y - lastLocation . Y ;
lastLocation = mousePos ;
2021-11-25 07:01:59 +13:00
2022-12-05 13:27:57 +13:00
Settings . Default . CustomLocationX = ( int ) Left ;
Settings . Default . CustomLocationY = ( int ) Top ;
2021-11-25 07:01:59 +13:00
}
}
2022-10-23 11:02:31 +13:00
private void Menu_MouseUp ( object sender , MouseButtonEventArgs e )
2021-11-25 07:01:59 +13:00
{
mouseDown = false ;
2022-12-05 13:27:57 +13:00
if ( Settings . Default . UseCustomLocation )
2021-12-27 18:31:23 +13:00
{
2022-10-23 11:02:31 +13:00
if ( ! SettingsWindow . IsOpen ( ) )
2021-12-27 18:31:23 +13:00
{
2022-12-05 13:27:57 +13:00
Settings . Default . Save ( ) ;
2021-12-27 18:31:23 +13:00
}
}
2021-11-25 07:01:59 +13:00
}
2022-10-23 11:02:31 +13:00
private void ListViewItem_MouseEnter ( object sender , MouseEventArgs e )
{
2022-11-30 10:48:45 +13:00
CellMouseEnter ? . Invoke ( dgv , dgv . IndexOfSenderItem ( ( ListViewItem ) sender ) ) ;
2022-10-23 11:02:31 +13:00
}
private void ListViewItem_MouseLeave ( object sender , MouseEventArgs e )
{
2022-11-30 10:48:45 +13:00
CellMouseLeave ? . Invoke ( dgv , dgv . IndexOfSenderItem ( ( ListViewItem ) sender ) ) ;
2022-10-23 11:02:31 +13:00
}
2022-11-26 11:31:20 +13:00
private void ListViewItem_PreviewMouseDown ( object sender , MouseButtonEventArgs e )
2022-10-23 11:02:31 +13:00
{
2022-11-30 10:48:45 +13:00
CellMouseDown ? . Invoke ( dgv , dgv . IndexOfSenderItem ( ( ListViewItem ) sender ) , e ) ;
2022-10-23 11:02:31 +13:00
}
private void ListViewItem_MouseUp ( object sender , MouseButtonEventArgs e )
{
2022-11-30 10:48:45 +13:00
CellMouseUp ? . Invoke ( dgv , dgv . IndexOfSenderItem ( ( ListViewItem ) sender ) , e ) ;
2022-10-23 11:02:31 +13:00
}
private void ListViewxItem_PreviewMouseLeftButtonDown ( object sender , MouseButtonEventArgs e )
{
2022-11-30 10:48:45 +13:00
CellMouseClick ? . Invoke ( dgv , dgv . IndexOfSenderItem ( ( ListViewItem ) sender ) , e ) ;
2022-10-23 11:02:31 +13:00
}
/// <summary>
/// Type for ListView items.
/// </summary>
internal class ListViewItemData
{
2022-11-14 07:58:54 +13:00
public ListViewItemData ( ImageSource columnIcon , string columnText , RowData rowData , int sortIndex )
2022-10-23 11:02:31 +13:00
{
ColumnIcon = columnIcon ;
ColumnText = columnText ;
data = rowData ;
SortIndex = sortIndex ;
}
2022-11-14 07:58:54 +13:00
public ImageSource ColumnIcon { get ; set ; }
2022-10-23 11:02:31 +13:00
public string ColumnText { get ; set ; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Benennungsstile", Justification = "Temporarily retained for compatibility reasons")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "Temporarily retained for compatibility reasons")]
public RowData data { get ; set ; }
public int SortIndex { get ; set ; }
}
private void textBoxSearch_TextInput ( object sender , TextCompositionEventArgs e )
{
// TODO WPF
}
2020-06-08 00:28:59 +12:00
}
2022-10-23 11:02:31 +13:00
}