Improve key selections by reduced usage of Nullables types

This commit is contained in:
Peter Kirmeier 2023-05-10 00:55:18 +02:00
parent ea02181408
commit fe2ab9b4ff
4 changed files with 67 additions and 120 deletions

View file

@ -5,7 +5,6 @@
namespace SystemTrayMenu.Handler
{
using System;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Input;
using SystemTrayMenu.DataClasses;
@ -27,11 +26,11 @@ namespace SystemTrayMenu.Handler
internal event Action<Menu, ListViewItemData>? RowSelected;
internal event Action<Menu?, ListViewItemData?>? RowDeselected;
internal event Action<Menu>? RowDeselected;
internal event Action<Menu, ListViewItemData>? EnterPressed;
internal bool InUse { get; set; }
internal bool IsSelectedByKey { get; set; }
public void Dispose()
{
@ -152,7 +151,7 @@ namespace SystemTrayMenu.Handler
internal void SearchTextChanged(Menu menu, bool isSearchStringEmpty)
{
ClearIsSelectedByKey();
DeselectFoccussedRow();
if (!isSearchStringEmpty)
{
@ -164,31 +163,18 @@ namespace SystemTrayMenu.Handler
}
}
internal void ClearIsSelectedByKey()
{
ClearIsSelectedByKey(focussedMenu, focussedRow);
}
internal void DeselectFoccussedRow() => focussedMenu?.GetDataGridView().SelectedItems.Remove(focussedRow);
internal void MouseSelect(Menu menu, ListViewItemData itemData)
{
InUse = false;
IsSelectedByKey = false;
ClearIsSelectedByKey();
DeselectFoccussedRow();
focussedMenu = menu;
Select(menu.GetDataGridView(), itemData);
}
private static void ClearIsSelectedByKey(Menu? menu, ListViewItemData? itemData)
{
if (menu != null && itemData != null)
{
itemData.IsClicking = false;
menu.GetDataGridView().SelectedItems.Remove(itemData);
}
}
private void SelectByKey(Key key, ModifierKeys modifiers)
{
Menu? menuFromSelected;
@ -214,6 +200,9 @@ namespace SystemTrayMenu.Handler
case Key.Enter:
if ((modifiers == ModifierKeys.None) && rowBefore != null && menuBefore != null)
{
// When not sub menu already open, open the sub menu,
// but when already opened, open the actual folder instead.
// In case it is a single file, open it right away
RowData trigger = rowBefore.data;
if (trigger.SubMenu != null || !trigger.IsPointingToFolder)
{
@ -225,7 +214,7 @@ namespace SystemTrayMenu.Handler
}
else
{
RaiseRowSelectionChanged(menuBefore, rowBefore);
RaiseRowSelectionChanged(menuBefore);
EnterPressed?.Invoke(menuBefore, rowBefore);
}
}
@ -237,7 +226,7 @@ namespace SystemTrayMenu.Handler
(TrySelectPrevious(menuBefore, menuBefore.GetDataGridView().Items.IndexOf(rowBefore)) ||
TrySelectPrevious(menuBefore, menuBefore.GetDataGridView().Items.Count - 1)))
{
RaiseRowSelectionChanged(menuBefore, rowBefore);
RaiseRowSelectionChanged(menuBefore);
doClearOldSelection = wasSelected;
}
@ -248,7 +237,7 @@ namespace SystemTrayMenu.Handler
(TrySelectNext(menuBefore, menuBefore.GetDataGridView().Items.IndexOf(rowBefore)) ||
TrySelectNext(menuBefore, 0)))
{
RaiseRowSelectionChanged(menuBefore, rowBefore);
RaiseRowSelectionChanged(menuBefore);
doClearOldSelection = wasSelected;
}
@ -258,7 +247,7 @@ namespace SystemTrayMenu.Handler
menuBefore != null &&
TrySelectNext(menuBefore, 0))
{
RaiseRowSelectionChanged(menuBefore, rowBefore);
RaiseRowSelectionChanged(menuBefore);
doClearOldSelection = wasSelected;
}
@ -268,7 +257,7 @@ namespace SystemTrayMenu.Handler
menuBefore != null &&
TrySelectPrevious(menuBefore, menuBefore.GetDataGridView().Items.Count - 1))
{
RaiseRowSelectionChanged(menuBefore, rowBefore);
RaiseRowSelectionChanged(menuBefore);
doClearOldSelection = wasSelected;
}
@ -299,7 +288,7 @@ namespace SystemTrayMenu.Handler
focussedRow = null;
if (TrySelectNext(menuFromSelected, 0))
{
RaiseRowSelectionChanged(menuBefore, rowBefore);
RaiseRowSelectionChanged(menuBefore);
doClearOldSelection = wasSelected;
}
}
@ -315,7 +304,7 @@ namespace SystemTrayMenu.Handler
Menu? lastMenu = focussedMenu;
if (lastMenu != null && TrySelectNext(lastMenu, 0))
{
RaiseRowSelectionChanged(menuBefore, rowBefore);
RaiseRowSelectionChanged(menuBefore);
doClearOldSelection = wasSelected;
}
}
@ -329,7 +318,7 @@ namespace SystemTrayMenu.Handler
if (TrySelectNext(focussedMenu, index) ||
TrySelectNext(focussedMenu, 0))
{
RaiseRowSelectionChanged(menuBefore, rowBefore);
RaiseRowSelectionChanged(menuBefore);
doClearOldSelection = wasSelected;
}
}
@ -341,8 +330,12 @@ namespace SystemTrayMenu.Handler
if ((key == Key.Escape && modifiers == ModifierKeys.None) ||
(key == Key.F4 && modifiers == ModifierKeys.Alt))
{
RowDeselected?.Invoke(menuBefore, rowBefore);
ResetSelectedByKey();
if (menuBefore != null)
{
RaiseRowSelectionChanged(menuBefore);
}
doClearOldSelection = wasSelected;
ClosePressed?.Invoke();
}
@ -354,17 +347,17 @@ namespace SystemTrayMenu.Handler
if (doClearOldSelection)
{
ClearIsSelectedByKey(menuBefore, rowBefore);
menuBefore?.GetDataGridView().SelectedItems.Remove(rowBefore);
}
}
private void RaiseRowSelectionChanged(Menu? menuBefore, ListViewItemData? rowBefore)
private void RaiseRowSelectionChanged(Menu menuBefore)
{
RowDeselected?.Invoke(menuBefore, rowBefore);
RowDeselected?.Invoke(menuBefore);
if (focussedMenu != null && focussedRow != null)
{
InUse = true;
IsSelectedByKey = true;
RowSelected?.Invoke(focussedMenu, focussedRow);
}
}

View file

@ -13,7 +13,6 @@ namespace SystemTrayMenu.Business
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using Microsoft.Win32;
using SystemTrayMenu.DataClasses;
@ -21,7 +20,6 @@ namespace SystemTrayMenu.Business
using SystemTrayMenu.Handler;
using SystemTrayMenu.Helpers;
using SystemTrayMenu.Properties;
using SystemTrayMenu.UserInterface;
using SystemTrayMenu.Utilities;
using static SystemTrayMenu.UserInterface.Menu;
using Menu = SystemTrayMenu.UserInterface.Menu;
@ -392,14 +390,7 @@ namespace SystemTrayMenu.Business
Menu? menu = mainMenu;
if (menu != null)
{
// The main menu gets loaded again, reset list
ListView dgvMainMenu = menu.GetDataGridView();
foreach (ListViewItemData item in dgvMainMenu.Items)
{
item.IsClicking = false;
}
dgvMainMenu.SelectedItem = null;
menu.GetDataGridView().SelectedItem = null;
menu.RelocateOnNextShow = true;
@ -576,8 +567,6 @@ namespace SystemTrayMenu.Business
menu.CellOpenOnClick += waitToOpenMenu.ClickOpensInstantly;
menu.ClosePressed += MenusFadeOut;
ListView dgv = menu.GetDataGridView();
if (menu.Level == 0)
{
// Main Menu
@ -590,7 +579,6 @@ namespace SystemTrayMenu.Business
if (IsMainUsable)
{
menu.ShowWithFade(!IsActiveApp(), false);
menu.RefreshSelection();
}
}
@ -666,7 +654,7 @@ namespace SystemTrayMenu.Business
{
if (Settings.Default.StaysOpenWhenFocusLost && IsMouseOverAnyMenu(mainMenu) != null)
{
if (!keyboardInput.InUse)
if (!keyboardInput.IsSelectedByKey)
{
mainMenu?.ShowWithFade(true, true);
}
@ -872,7 +860,7 @@ namespace SystemTrayMenu.Business
}
rowDatas = DirectoryHelpers.SortItems(rowDatas);
keyboardInput.ClearIsSelectedByKey();
keyboardInput.DeselectFoccussedRow();
menu.AddItemsToMenu(rowDatas, null, true);
menu.OnWatcherUpdate();
}
@ -905,7 +893,7 @@ namespace SystemTrayMenu.Business
((IEditableCollectionView)dgv.Items).Remove(rowToRemove);
}
keyboardInput.ClearIsSelectedByKey();
keyboardInput.DeselectFoccussedRow();
menu.OnWatcherUpdate();
}
catch (Exception ex)
@ -939,7 +927,7 @@ namespace SystemTrayMenu.Business
}
rowDatas = DirectoryHelpers.SortItems(rowDatas);
keyboardInput.ClearIsSelectedByKey();
keyboardInput.DeselectFoccussedRow();
menu.AddItemsToMenu(rowDatas, null, true);
menu.OnWatcherUpdate();
}

View file

@ -15,8 +15,8 @@ namespace SystemTrayMenu.Handler
internal class WaitToLoadMenu : IDisposable
{
private readonly DispatcherTimer timerStartLoad = new();
private ListView? dgv;
private ListViewItemData? dgvItemData;
private Menu? currentMenu;
private ListViewItemData? currentItemData;
private bool alreadyOpened;
private bool checkForMouseActive = true;
@ -49,7 +49,7 @@ namespace SystemTrayMenu.Handler
timerStartLoad.Stop();
StopLoadMenu?.Invoke();
checkForMouseActive = true;
SetData(menu.GetDataGridView(), itemData);
SetData(menu, itemData);
timerStartLoad.Start();
}
}
@ -58,38 +58,34 @@ namespace SystemTrayMenu.Handler
{
timerStartLoad.Stop();
StopLoadMenu?.Invoke();
SetData(menu.GetDataGridView(), itemData);
SetData(menu, itemData);
MouseActive = false;
checkForMouseActive = false;
timerStartLoad.Start();
}
internal void MouseLeave(ListView dgv, ListViewItemData itemData)
internal void MouseLeave(ListView dgv)
{
if (MouseActive)
{
timerStartLoad.Stop();
StopLoadMenu?.Invoke();
ResetData(dgv, itemData);
ResetData(dgv);
}
}
internal void RowDeselected(Menu? menu, ListViewItemData? itemData)
internal void RowDeselected(Menu menu)
{
timerStartLoad.Stop();
StopLoadMenu?.Invoke();
if (menu != null && itemData != null)
{
ResetData(menu.GetDataGridView(), itemData);
}
ResetData(menu.GetDataGridView());
MouseActive = false;
}
internal void ClickOpensInstantly(ListView dgv, ListViewItemData itemData)
internal void ClickOpensInstantly(Menu menu, ListViewItemData itemData)
{
timerStartLoad.Stop();
SetData(dgv, itemData);
SetData(menu, itemData);
MouseActive = true;
checkForMouseActive = false;
CallOpenMenuNow();
@ -99,7 +95,7 @@ namespace SystemTrayMenu.Handler
{
timerStartLoad.Stop();
StopLoadMenu?.Invoke();
SetData(menu.GetDataGridView(), itemData);
SetData(menu, itemData);
MouseActive = false;
checkForMouseActive = false;
CallOpenMenuNow();
@ -116,25 +112,22 @@ namespace SystemTrayMenu.Handler
private void CallOpenMenuNow()
{
if (!alreadyOpened && dgv != null && dgvItemData != null && dgv.Items.Contains(dgvItemData))
if (!alreadyOpened && (currentMenu?.GetDataGridView().Items.Contains(currentItemData) ?? false))
{
alreadyOpened = true;
RowData rowData = dgvItemData.data;
Menu menu = (Menu)dgv.GetParentWindow();
rowData.Level = menu.Level;
// Give the opening window focus
// if closing window lose focus no window would have focus any more
menu?.Activate();
menu?.FocusTextBox();
currentMenu?.Activate();
currentMenu?.FocusTextBox();
Menu? menuToClose = menu?.SubMenu;
Menu? menuToClose = currentMenu?.SubMenu;
if (menuToClose != null)
{
CloseMenu?.Invoke(menuToClose);
}
RowData rowData = currentItemData!.data;
if (rowData.IsPointingToFolder)
{
StartLoadMenu?.Invoke(rowData);
@ -142,25 +135,24 @@ namespace SystemTrayMenu.Handler
}
}
private void SetData(ListView dgv, ListViewItemData itemData)
private void SetData(Menu menu, ListViewItemData itemData)
{
if (this.dgv == dgv && dgvItemData == itemData)
if (currentMenu != menu || currentItemData != itemData)
{
return;
alreadyOpened = false;
menu.GetDataGridView().SelectedItem = currentItemData = itemData;
currentMenu = menu;
}
alreadyOpened = false;
this.dgv = dgv;
dgv.SelectedItem = dgvItemData = itemData;
}
private void ResetData(ListView dgv, ListViewItemData itemData)
private void ResetData(ListView dgv)
{
itemData.IsClicking = false;
this.dgv = null;
dgv.SelectedItem = dgvItemData = null;
if (currentMenu != null)
{
dgv.SelectedItem = currentItemData = null;
currentMenu = null;
}
}
}
}

View file

@ -237,11 +237,11 @@ namespace SystemTrayMenu.UserInterface
internal event Action<Menu, ListViewItemData>? CellMouseEnter;
internal event Action<ListView, ListViewItemData>? CellMouseLeave;
internal event Action<ListView>? CellMouseLeave;
internal event Action<Menu, ListViewItemData>? CellMouseDown;
internal event Action<ListView, ListViewItemData>? CellOpenOnClick;
internal event Action<Menu, ListViewItemData>? CellOpenOnClick;
internal event Action? ClosePressed;
@ -1206,22 +1206,10 @@ namespace SystemTrayMenu.UserInterface
}
}
private void ListViewItem_MouseEnter(object sender, MouseEventArgs e)
{
private void ListViewItem_MouseEnter(object sender, MouseEventArgs e) =>
CellMouseEnter?.Invoke(this, (ListViewItemData)((ListViewItem)sender).Content);
}
private void ListViewItem_MouseLeave(object sender, MouseEventArgs e)
{
object content = ((ListViewItem)sender).Content;
if (content == BindingOperations.DisconnectedSource)
{
// Item may disappear while mouse is hovering over it, eg. search filter hides item
return;
}
CellMouseLeave?.Invoke(dgv, (ListViewItemData)content);
}
private void ListViewItem_MouseLeave(object sender, MouseEventArgs e) => CellMouseLeave?.Invoke(dgv);
private void ListViewItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
@ -1229,11 +1217,6 @@ namespace SystemTrayMenu.UserInterface
CellMouseDown?.Invoke(this, itemData);
if (e.LeftButton == MouseButtonState.Pressed)
{
itemData.IsClicking = true;
}
if (e.RightButton == MouseButtonState.Pressed)
{
var position = Mouse.GetPosition(this);
@ -1250,7 +1233,7 @@ namespace SystemTrayMenu.UserInterface
if (e.ClickCount == 1)
{
CellOpenOnClick?.Invoke(dgv, itemData);
CellOpenOnClick?.Invoke(this, itemData);
}
if (doClose)
@ -1325,7 +1308,7 @@ namespace SystemTrayMenu.UserInterface
internal int SortIndex { get; set; }
internal bool IsClicking { get; set; }
internal bool IsPendingOpenItem { get; set; }
internal bool IsSelected { get; set; }
@ -1337,11 +1320,7 @@ namespace SystemTrayMenu.UserInterface
/// <param name="propertyName">Name of the changing property.</param>
public void CallPropertyChanged([CallerMemberName] string? propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
internal void OpenItem(out bool doCloseAfterOpen, int clickCount = -1)
{
IsClicking = false;
data.OpenItem(out doCloseAfterOpen, clickCount);
}
internal void OpenItem(out bool doCloseAfterOpen, int clickCount = -1) => data.OpenItem(out doCloseAfterOpen, clickCount);
internal void OpenShellContextMenu(Point position)
{
@ -1357,12 +1336,7 @@ namespace SystemTrayMenu.UserInterface
internal void UpdateColors()
{
if (IsClicking)
{
BorderBrush = MenuDefines.ColorIcons;
BackgroundBrush = MenuDefines.ColorSelectedItem;
}
else if (data.SubMenu != null)
if (data.SubMenu != null)
{
BorderBrush = MenuDefines.ColorOpenFolderBorder;
BackgroundBrush = MenuDefines.ColorOpenFolder;