2020-07-07 07:15:45 +12:00
|
|
|
|
// <copyright file="KeyboardInput.cs" company="PlaceholderCompany">
|
|
|
|
|
// Copyright (c) PlaceholderCompany. All rights reserved.
|
|
|
|
|
// </copyright>
|
2020-06-21 03:38:21 +12:00
|
|
|
|
|
|
|
|
|
namespace SystemTrayMenu.Handler
|
|
|
|
|
{
|
2020-07-07 07:15:45 +12:00
|
|
|
|
using System;
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.Globalization;
|
|
|
|
|
using System.Linq;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
using System.Reflection;
|
|
|
|
|
using System.Windows.Controls;
|
|
|
|
|
using System.Windows.Input;
|
2020-07-07 07:15:45 +12:00
|
|
|
|
using SystemTrayMenu.DataClasses;
|
|
|
|
|
using SystemTrayMenu.Helper;
|
|
|
|
|
using SystemTrayMenu.Utilities;
|
2022-11-26 11:31:20 +13:00
|
|
|
|
using static System.Net.Mime.MediaTypeNames;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
using ListView = System.Windows.Controls.ListView;
|
2021-06-27 21:35:07 +12:00
|
|
|
|
using Menu = SystemTrayMenu.UserInterface.Menu;
|
2020-07-07 07:15:45 +12:00
|
|
|
|
|
2020-06-21 03:38:21 +12:00
|
|
|
|
internal class KeyboardInput : IDisposable
|
|
|
|
|
{
|
|
|
|
|
private readonly Menu[] menus;
|
2021-11-17 12:13:46 +13:00
|
|
|
|
private readonly KeyboardHook hook = new();
|
2020-06-21 03:38:21 +12:00
|
|
|
|
|
2020-07-07 09:37:55 +12:00
|
|
|
|
private int iRowKey = -1;
|
2021-04-17 12:39:48 +12:00
|
|
|
|
private int iMenuKey;
|
2020-07-07 09:37:55 +12:00
|
|
|
|
|
2020-06-21 03:38:21 +12:00
|
|
|
|
public KeyboardInput(Menu[] menus)
|
|
|
|
|
{
|
|
|
|
|
this.menus = menus;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-23 11:02:31 +13:00
|
|
|
|
internal event Action HotKeyPressed;
|
2020-07-07 09:37:55 +12:00
|
|
|
|
|
2022-10-23 11:02:31 +13:00
|
|
|
|
internal event Action ClosePressed;
|
2020-07-07 09:37:55 +12:00
|
|
|
|
|
2022-10-23 11:02:31 +13:00
|
|
|
|
internal event Action<ListView, int> RowSelected;
|
2020-07-07 09:37:55 +12:00
|
|
|
|
|
2022-10-23 11:02:31 +13:00
|
|
|
|
internal event Action<int, ListView> RowDeselected;
|
2020-07-07 09:37:55 +12:00
|
|
|
|
|
2022-10-23 11:02:31 +13:00
|
|
|
|
internal event Action<ListView, int> EnterPressed;
|
2020-07-07 09:37:55 +12:00
|
|
|
|
|
2022-10-23 11:02:31 +13:00
|
|
|
|
internal event Action Cleared;
|
2020-07-07 09:37:55 +12:00
|
|
|
|
|
2021-04-17 12:39:48 +12:00
|
|
|
|
internal bool InUse { get; set; }
|
2020-07-08 03:05:19 +12:00
|
|
|
|
|
2020-06-21 03:38:21 +12:00
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
hook.Dispose();
|
2020-05-31 05:59:33 +12:00
|
|
|
|
}
|
|
|
|
|
|
2020-06-21 03:38:21 +12:00
|
|
|
|
internal void RegisterHotKey()
|
|
|
|
|
{
|
|
|
|
|
if (!string.IsNullOrEmpty(Properties.Settings.Default.HotKey))
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2020-07-04 08:02:16 +12:00
|
|
|
|
hook.RegisterHotKey();
|
2021-10-27 09:09:40 +13:00
|
|
|
|
hook.KeyPressed += (sender, e) => HotKeyPressed?.Invoke();
|
2020-06-21 03:38:21 +12:00
|
|
|
|
}
|
|
|
|
|
catch (InvalidOperationException ex)
|
|
|
|
|
{
|
2020-06-26 06:54:27 +12:00
|
|
|
|
Log.Warn($"key:'{Properties.Settings.Default.HotKey}'", ex);
|
2020-06-21 03:38:21 +12:00
|
|
|
|
Properties.Settings.Default.HotKey = string.Empty;
|
|
|
|
|
Properties.Settings.Default.Save();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void ResetSelectedByKey()
|
|
|
|
|
{
|
|
|
|
|
iRowKey = -1;
|
|
|
|
|
iMenuKey = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-23 11:02:31 +13:00
|
|
|
|
internal void CmdKeyProcessed(object sender, Key keys)
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
2022-09-27 06:02:18 +13:00
|
|
|
|
sender ??= menus[iMenuKey];
|
|
|
|
|
|
2020-06-21 03:38:21 +12:00
|
|
|
|
switch (keys)
|
|
|
|
|
{
|
2022-10-23 11:02:31 +13:00
|
|
|
|
case Key.Enter:
|
2021-11-11 11:39:52 +13:00
|
|
|
|
SelectByKey(keys);
|
2021-11-18 12:52:24 +13:00
|
|
|
|
menus[iMenuKey]?.FocusTextBox();
|
2021-11-11 11:39:52 +13:00
|
|
|
|
break;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
case Key.Left:
|
2021-12-12 08:43:33 +13:00
|
|
|
|
SelectByKey(keys);
|
2021-11-11 11:39:52 +13:00
|
|
|
|
break;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
case Key.Right:
|
2021-12-12 08:43:33 +13:00
|
|
|
|
SelectByKey(keys);
|
2021-11-11 11:39:52 +13:00
|
|
|
|
break;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
case Key.Home:
|
|
|
|
|
case Key.End:
|
|
|
|
|
case Key.Up:
|
|
|
|
|
case Key.Down:
|
|
|
|
|
case Key.Escape:
|
|
|
|
|
#if TODO // WPF Key Modifier!
|
|
|
|
|
case Key.Alt | Key.F4:
|
2020-06-21 03:38:21 +12:00
|
|
|
|
SelectByKey(keys);
|
|
|
|
|
break;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
case Key.Control | Key.F:
|
2021-11-18 12:52:24 +13:00
|
|
|
|
menus[iMenuKey]?.FocusTextBox();
|
2020-05-31 05:59:33 +12:00
|
|
|
|
break;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
case Key.Tab:
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
|
|
|
|
Menu currentMenu = (Menu)sender;
|
|
|
|
|
int indexOfTheCurrentMenu = GetMenuIndex(currentMenu);
|
|
|
|
|
int indexMax = menus.Where(m => m != null).Count() - 1;
|
|
|
|
|
int indexNew = 0;
|
|
|
|
|
if (indexOfTheCurrentMenu > 0)
|
|
|
|
|
{
|
|
|
|
|
indexNew = indexOfTheCurrentMenu - 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
indexNew = indexMax;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-18 12:52:24 +13:00
|
|
|
|
menus[indexNew]?.FocusTextBox();
|
2020-06-21 03:38:21 +12:00
|
|
|
|
}
|
2020-07-07 07:15:45 +12:00
|
|
|
|
|
2020-06-21 03:38:21 +12:00
|
|
|
|
break;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
case Key.Tab | Key.LeftShift:
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
|
|
|
|
Menu currentMenu = (Menu)sender;
|
|
|
|
|
int indexOfTheCurrentMenu = GetMenuIndex(currentMenu);
|
|
|
|
|
int indexMax = menus.Where(m => m != null).Count() - 1;
|
|
|
|
|
int indexNew = 0;
|
|
|
|
|
if (indexOfTheCurrentMenu < indexMax)
|
|
|
|
|
{
|
|
|
|
|
indexNew = indexOfTheCurrentMenu + 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
indexNew = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-18 12:52:24 +13:00
|
|
|
|
menus[indexNew]?.FocusTextBox();
|
2020-06-21 03:38:21 +12:00
|
|
|
|
}
|
2020-07-07 07:15:45 +12:00
|
|
|
|
|
2020-06-21 03:38:21 +12:00
|
|
|
|
break;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
#endif
|
|
|
|
|
case Key.Apps:
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
2022-10-23 11:02:31 +13:00
|
|
|
|
ListView dgv = menus[iMenuKey]?.GetDataGridView();
|
2020-06-21 03:38:21 +12:00
|
|
|
|
|
|
|
|
|
if (iRowKey > -1 &&
|
2022-10-23 11:02:31 +13:00
|
|
|
|
dgv.Items.Count > iRowKey)
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
2022-10-23 11:02:31 +13:00
|
|
|
|
#if TODO
|
2021-11-24 12:22:38 +13:00
|
|
|
|
Point point = dgv.GetCellDisplayRectangle(2, iRowKey, false).Location;
|
2020-05-31 05:59:33 +12:00
|
|
|
|
RowData trigger = (RowData)dgv.Rows[iRowKey].Cells[2].Value;
|
2021-11-24 12:22:38 +13:00
|
|
|
|
MouseEventArgs mouseEventArgs = new(MouseButtons.Right, 1, point.X, point.Y, 0);
|
|
|
|
|
trigger.MouseDown(dgv, mouseEventArgs);
|
2022-10-23 11:02:31 +13:00
|
|
|
|
#endif
|
2020-06-21 03:38:21 +12:00
|
|
|
|
}
|
|
|
|
|
}
|
2020-07-07 07:15:45 +12:00
|
|
|
|
|
2020-06-21 03:38:21 +12:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-07-07 07:15:45 +12:00
|
|
|
|
|
|
|
|
|
int GetMenuIndex(in Menu currentMenu)
|
|
|
|
|
{
|
|
|
|
|
int index = 0;
|
|
|
|
|
foreach (Menu menuFindIndex in menus.Where(m => m != null))
|
|
|
|
|
{
|
|
|
|
|
if (currentMenu == menuFindIndex)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
index++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return index;
|
|
|
|
|
}
|
2020-06-21 03:38:21 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void SearchTextChanging()
|
|
|
|
|
{
|
|
|
|
|
ClearIsSelectedByKey();
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-11 23:04:21 +12:00
|
|
|
|
internal void SearchTextChanged(Menu menu, bool isSearchStringEmpty)
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
2022-10-23 11:02:31 +13:00
|
|
|
|
ListView dgv = menu.GetDataGridView();
|
2022-06-11 23:04:21 +12:00
|
|
|
|
if (isSearchStringEmpty)
|
|
|
|
|
{
|
|
|
|
|
ClearIsSelectedByKey();
|
|
|
|
|
}
|
2022-10-23 11:02:31 +13:00
|
|
|
|
else if (dgv.Items.Count > 0)
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
2020-06-23 03:52:19 +12:00
|
|
|
|
Select(dgv, 0, true);
|
2020-06-21 03:38:21 +12:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 07:15:45 +12:00
|
|
|
|
internal void ClearIsSelectedByKey()
|
|
|
|
|
{
|
|
|
|
|
ClearIsSelectedByKey(iMenuKey, iRowKey);
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-23 11:02:31 +13:00
|
|
|
|
internal void Select(ListView dgv, int index, bool refreshview)
|
2020-07-08 03:05:19 +12:00
|
|
|
|
{
|
2022-10-23 11:02:31 +13:00
|
|
|
|
int newiMenuKey = ((Menu)dgv.GetParentWindow()).Level;
|
|
|
|
|
if (index != iRowKey || newiMenuKey != iMenuKey)
|
2020-07-08 03:05:19 +12:00
|
|
|
|
{
|
|
|
|
|
ClearIsSelectedByKey();
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-23 11:02:31 +13:00
|
|
|
|
iRowKey = index;
|
2020-07-08 03:05:19 +12:00
|
|
|
|
iMenuKey = newiMenuKey;
|
2020-08-04 20:58:20 +12:00
|
|
|
|
|
2022-10-23 11:02:31 +13:00
|
|
|
|
if (dgv.Items.Count > index)
|
2020-07-08 03:05:19 +12:00
|
|
|
|
{
|
2022-11-26 11:31:20 +13:00
|
|
|
|
Menu.ListViewItemData itemData = (Menu.ListViewItemData)dgv.Items[index];
|
|
|
|
|
RowData rowData = itemData.data;
|
2021-11-11 11:39:52 +13:00
|
|
|
|
if (rowData != null)
|
|
|
|
|
{
|
|
|
|
|
rowData.IsSelected = true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-04 20:58:20 +12:00
|
|
|
|
if (refreshview)
|
|
|
|
|
{
|
2022-11-26 11:31:20 +13:00
|
|
|
|
if (dgv.SelectedItems.Contains(itemData))
|
|
|
|
|
{
|
|
|
|
|
dgv.SelectedItems.Remove(itemData);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dgv.SelectedItems.Add(itemData);
|
2020-08-04 20:58:20 +12:00
|
|
|
|
}
|
2020-07-08 03:05:19 +12:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-21 03:38:21 +12:00
|
|
|
|
private bool IsAnyMenuSelectedByKey(
|
2022-10-23 11:02:31 +13:00
|
|
|
|
ref ListView dgv,
|
2020-06-21 03:38:21 +12:00
|
|
|
|
ref Menu menuFromSelected,
|
|
|
|
|
ref string textselected)
|
|
|
|
|
{
|
|
|
|
|
Menu menu = menus[iMenuKey];
|
|
|
|
|
bool isStillSelected = false;
|
|
|
|
|
if (menu != null &&
|
|
|
|
|
iRowKey > -1)
|
|
|
|
|
{
|
|
|
|
|
dgv = menu.GetDataGridView();
|
2022-10-23 11:02:31 +13:00
|
|
|
|
if (dgv.Items.Count > iRowKey)
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
2022-11-26 11:31:20 +13:00
|
|
|
|
Menu.ListViewItemData itemData = (Menu.ListViewItemData)dgv.Items[iRowKey];
|
|
|
|
|
RowData rowData = itemData.data;
|
2020-06-21 03:38:21 +12:00
|
|
|
|
if (rowData.IsSelected)
|
|
|
|
|
{
|
|
|
|
|
isStillSelected = true;
|
|
|
|
|
menuFromSelected = rowData.SubMenu;
|
2022-11-26 11:31:20 +13:00
|
|
|
|
textselected = itemData.ColumnText;
|
2020-06-21 03:38:21 +12:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return isStillSelected;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-23 11:02:31 +13:00
|
|
|
|
private void SelectByKey(Key keys, string keyInput = "", bool keepSelection = false)
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
|
|
|
|
int iRowBefore = iRowKey;
|
|
|
|
|
int iMenuBefore = iMenuKey;
|
|
|
|
|
|
|
|
|
|
Menu menu = menus[iMenuKey];
|
2022-10-23 11:02:31 +13:00
|
|
|
|
ListView dgv = null;
|
|
|
|
|
ListView dgvBefore = null;
|
2020-06-21 03:38:21 +12:00
|
|
|
|
Menu menuFromSelected = null;
|
|
|
|
|
string textselected = string.Empty;
|
|
|
|
|
bool isStillSelected = IsAnyMenuSelectedByKey(ref dgv, ref menuFromSelected, ref textselected);
|
|
|
|
|
if (isStillSelected)
|
|
|
|
|
{
|
2020-07-07 09:37:55 +12:00
|
|
|
|
if (keepSelection)
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
|
|
|
|
// If current selection is still valid for this search then skip selecting different item
|
|
|
|
|
if (textselected.StartsWith(keyInput, true, CultureInfo.InvariantCulture))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dgvBefore = dgv;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ResetSelectedByKey();
|
|
|
|
|
menu = menus[iMenuKey];
|
|
|
|
|
dgv = menu.GetDataGridView();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool toClear = false;
|
|
|
|
|
switch (keys)
|
|
|
|
|
{
|
2022-10-23 11:02:31 +13:00
|
|
|
|
case Key.Enter:
|
|
|
|
|
if (iRowKey > -1 && dgv.Items.Count > iRowKey)
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
2022-10-23 11:02:31 +13:00
|
|
|
|
RowData trigger = ((Menu.ListViewItemData)dgv.Items[iRowKey]).data;
|
2020-06-21 03:38:21 +12:00
|
|
|
|
if (trigger.IsMenuOpen || !trigger.ContainsMenu)
|
|
|
|
|
{
|
2021-11-24 12:22:38 +13:00
|
|
|
|
trigger.MouseClick(null, out bool toCloseByMouseClick);
|
2022-10-23 11:02:31 +13:00
|
|
|
|
#if TODO
|
2020-06-21 03:38:21 +12:00
|
|
|
|
trigger.DoubleClick(
|
2022-10-23 11:02:31 +13:00
|
|
|
|
new MouseButtonEventArgs(MouseButtons.Left, 0, 0, 0, 0),
|
2021-05-02 23:12:18 +12:00
|
|
|
|
out bool toCloseByDoubleClick);
|
2022-10-23 11:02:31 +13:00
|
|
|
|
#else
|
|
|
|
|
bool toCloseByDoubleClick = false;
|
|
|
|
|
#endif
|
2021-11-24 11:08:19 +13:00
|
|
|
|
if (toCloseByMouseClick || toCloseByDoubleClick)
|
2021-05-02 23:12:18 +12:00
|
|
|
|
{
|
|
|
|
|
ClosePressed?.Invoke();
|
|
|
|
|
}
|
2022-10-23 11:02:31 +13:00
|
|
|
|
#if TODO
|
2021-12-30 23:56:34 +13:00
|
|
|
|
if (iRowKey > -1 && dgv.Rows.Count > iRowKey)
|
2021-11-18 12:52:24 +13:00
|
|
|
|
{
|
|
|
|
|
// Raise Dgv_RowPostPaint to show ProcessStarted
|
|
|
|
|
dgv.InvalidateRow(iRowKey);
|
|
|
|
|
}
|
2022-10-23 11:02:31 +13:00
|
|
|
|
#endif
|
2020-06-21 03:38:21 +12:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-07-04 08:02:16 +12:00
|
|
|
|
RowDeselected(iRowBefore, dgvBefore);
|
2020-06-21 03:38:21 +12:00
|
|
|
|
SelectRow(dgv, iRowKey);
|
|
|
|
|
EnterPressed.Invoke(dgv, iRowKey);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-07-07 07:15:45 +12:00
|
|
|
|
|
2020-06-21 03:38:21 +12:00
|
|
|
|
break;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
case Key.Up:
|
2020-06-21 03:38:21 +12:00
|
|
|
|
if (SelectMatchedReverse(dgv, iRowKey) ||
|
2022-10-23 11:02:31 +13:00
|
|
|
|
SelectMatchedReverse(dgv, dgv.Items.Count - 1))
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
2020-07-04 08:02:16 +12:00
|
|
|
|
RowDeselected(iRowBefore, dgvBefore);
|
2020-06-21 03:38:21 +12:00
|
|
|
|
SelectRow(dgv, iRowKey);
|
|
|
|
|
toClear = true;
|
|
|
|
|
}
|
2020-07-07 07:15:45 +12:00
|
|
|
|
|
2020-06-21 03:38:21 +12:00
|
|
|
|
break;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
case Key.Down:
|
2020-06-21 03:38:21 +12:00
|
|
|
|
if (SelectMatched(dgv, iRowKey) ||
|
|
|
|
|
SelectMatched(dgv, 0))
|
|
|
|
|
{
|
2020-07-04 08:02:16 +12:00
|
|
|
|
RowDeselected(iRowBefore, dgvBefore);
|
2020-06-21 03:38:21 +12:00
|
|
|
|
SelectRow(dgv, iRowKey);
|
|
|
|
|
toClear = true;
|
|
|
|
|
}
|
2020-07-07 07:15:45 +12:00
|
|
|
|
|
2022-02-05 02:37:37 +13:00
|
|
|
|
break;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
case Key.Home:
|
2022-02-05 02:37:37 +13:00
|
|
|
|
if (SelectMatched(dgv, 0))
|
|
|
|
|
{
|
|
|
|
|
RowDeselected(iRowBefore, dgvBefore);
|
|
|
|
|
SelectRow(dgv, iRowKey);
|
|
|
|
|
toClear = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
case Key.End:
|
|
|
|
|
if (SelectMatchedReverse(dgv, dgv.Items.Count - 1))
|
2022-02-05 02:37:37 +13:00
|
|
|
|
{
|
|
|
|
|
RowDeselected(iRowBefore, dgvBefore);
|
|
|
|
|
SelectRow(dgv, iRowKey);
|
|
|
|
|
toClear = true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-21 03:38:21 +12:00
|
|
|
|
break;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
case Key.Left:
|
2021-12-10 08:00:33 +13:00
|
|
|
|
bool nextMenuLocationIsLeft = menus[iMenuKey + 1] != null && menus[iMenuKey + 1].Location.X < menus[iMenuKey].Location.X;
|
2022-09-27 06:02:18 +13:00
|
|
|
|
bool previousMenuLocationIsRight = iMenuKey > 0 && menus[iMenuKey]?.Location.X < menus[iMenuKey - 1]?.Location.X;
|
|
|
|
|
if (nextMenuLocationIsLeft || previousMenuLocationIsRight)
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
2021-12-10 08:00:33 +13:00
|
|
|
|
SelectNextMenu(iRowBefore, ref dgv, dgvBefore, menuFromSelected, isStillSelected, ref toClear);
|
2020-06-21 03:38:21 +12:00
|
|
|
|
}
|
2022-09-27 06:02:18 +13:00
|
|
|
|
else if (iMenuKey > 0)
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
2021-12-10 08:00:33 +13:00
|
|
|
|
SelectPreviousMenu(iRowBefore, ref menu, ref dgv, dgvBefore, ref toClear);
|
2020-06-21 03:38:21 +12:00
|
|
|
|
}
|
2020-07-07 07:15:45 +12:00
|
|
|
|
|
2020-06-21 03:38:21 +12:00
|
|
|
|
break;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
case Key.Right:
|
2022-09-27 06:02:18 +13:00
|
|
|
|
bool nextMenuLocationIsRight = menus[iMenuKey + 1]?.Location.X > menus[iMenuKey]?.Location.X;
|
|
|
|
|
bool previousMenuLocationIsLeft = iMenuKey > 0 && menus[iMenuKey]?.Location.X > menus[iMenuKey - 1]?.Location.X;
|
|
|
|
|
if (nextMenuLocationIsRight || previousMenuLocationIsLeft)
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
2021-12-10 08:00:33 +13:00
|
|
|
|
SelectNextMenu(iRowBefore, ref dgv, dgvBefore, menuFromSelected, isStillSelected, ref toClear);
|
2020-06-21 03:38:21 +12:00
|
|
|
|
}
|
2022-09-27 06:02:18 +13:00
|
|
|
|
else if (iMenuKey > 0)
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
2021-12-10 08:00:33 +13:00
|
|
|
|
SelectPreviousMenu(iRowBefore, ref menu, ref dgv, dgvBefore, ref toClear);
|
2020-06-21 03:38:21 +12:00
|
|
|
|
}
|
2020-07-07 07:15:45 +12:00
|
|
|
|
|
2020-06-21 03:38:21 +12:00
|
|
|
|
break;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
case Key.Escape:
|
|
|
|
|
#if TODO // WPF Key Modifier!
|
|
|
|
|
case Key.Alt | Key.F4:
|
|
|
|
|
#endif
|
2020-07-04 08:02:16 +12:00
|
|
|
|
RowDeselected(iRowBefore, dgvBefore);
|
2020-06-21 03:38:21 +12:00
|
|
|
|
iMenuKey = 0;
|
|
|
|
|
iRowKey = -1;
|
|
|
|
|
toClear = true;
|
|
|
|
|
ClosePressed?.Invoke();
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
if (!string.IsNullOrEmpty(keyInput))
|
|
|
|
|
{
|
|
|
|
|
if (SelectMatched(dgv, iRowKey, keyInput) ||
|
|
|
|
|
SelectMatched(dgv, 0, keyInput))
|
|
|
|
|
{
|
2020-07-04 08:02:16 +12:00
|
|
|
|
RowDeselected(iRowBefore, null);
|
2020-06-21 03:38:21 +12:00
|
|
|
|
SelectRow(dgv, iRowKey);
|
|
|
|
|
toClear = true;
|
|
|
|
|
}
|
|
|
|
|
else if (isStillSelected)
|
|
|
|
|
{
|
|
|
|
|
iRowKey = iRowBefore - 1;
|
|
|
|
|
if (SelectMatched(dgv, iRowKey, keyInput) ||
|
|
|
|
|
SelectMatched(dgv, 0, keyInput))
|
|
|
|
|
{
|
2020-07-04 08:02:16 +12:00
|
|
|
|
RowDeselected(iRowBefore, null);
|
2020-06-21 03:38:21 +12:00
|
|
|
|
SelectRow(dgv, iRowKey);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
iRowKey = iRowBefore;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-07-07 07:15:45 +12:00
|
|
|
|
|
2020-06-21 03:38:21 +12:00
|
|
|
|
break;
|
|
|
|
|
}
|
2020-07-07 07:15:45 +12:00
|
|
|
|
|
2020-06-21 03:38:21 +12:00
|
|
|
|
if (isStillSelected && toClear)
|
|
|
|
|
{
|
|
|
|
|
ClearIsSelectedByKey(iMenuBefore, iRowBefore);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-23 11:02:31 +13:00
|
|
|
|
private void SelectPreviousMenu(int iRowBefore, ref Menu menu, ref ListView dgv, ListView dgvBefore, ref bool toClear)
|
2021-12-10 08:00:33 +13:00
|
|
|
|
{
|
|
|
|
|
if (iMenuKey > 0)
|
|
|
|
|
{
|
|
|
|
|
if (menus[iMenuKey - 1] != null)
|
|
|
|
|
{
|
|
|
|
|
iMenuKey -= 1;
|
|
|
|
|
iRowKey = -1;
|
|
|
|
|
menu = menus[iMenuKey];
|
|
|
|
|
dgv = menu.GetDataGridView();
|
2022-10-23 11:02:31 +13:00
|
|
|
|
#if TODO
|
2021-12-10 08:00:33 +13:00
|
|
|
|
if (SelectMatched(dgv, dgv.SelectedRows[0].Index) ||
|
|
|
|
|
SelectMatched(dgv, 0))
|
|
|
|
|
{
|
|
|
|
|
RowDeselected(iRowBefore, dgvBefore);
|
|
|
|
|
SelectRow(dgv, iRowKey);
|
|
|
|
|
toClear = true;
|
|
|
|
|
}
|
2022-10-23 11:02:31 +13:00
|
|
|
|
#endif
|
2021-12-10 08:00:33 +13:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
RowDeselected(iRowBefore, dgvBefore);
|
|
|
|
|
iMenuKey = 0;
|
|
|
|
|
iRowKey = -1;
|
|
|
|
|
toClear = true;
|
|
|
|
|
Cleared?.Invoke();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-23 11:02:31 +13:00
|
|
|
|
private void SelectNextMenu(int iRowBefore, ref ListView dgv, ListView dgvBefore, Menu menuFromSelected, bool isStillSelected, ref bool toClear)
|
2021-12-10 08:00:33 +13:00
|
|
|
|
{
|
|
|
|
|
int iMenuKeyNext = iMenuKey + 1;
|
|
|
|
|
if (isStillSelected)
|
|
|
|
|
{
|
|
|
|
|
if (menuFromSelected != null &&
|
|
|
|
|
menuFromSelected == menus[iMenuKeyNext])
|
|
|
|
|
{
|
|
|
|
|
dgv = menuFromSelected.GetDataGridView();
|
2022-10-23 11:02:31 +13:00
|
|
|
|
if (dgv.Items.Count > 0)
|
2021-12-10 08:00:33 +13:00
|
|
|
|
{
|
|
|
|
|
iMenuKey += 1;
|
|
|
|
|
iRowKey = -1;
|
|
|
|
|
if (SelectMatched(dgv, iRowKey) ||
|
|
|
|
|
SelectMatched(dgv, 0))
|
|
|
|
|
{
|
|
|
|
|
RowDeselected(iRowBefore, dgvBefore);
|
|
|
|
|
SelectRow(dgv, iRowKey);
|
|
|
|
|
toClear = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
iRowKey = -1;
|
|
|
|
|
iMenuKey = menus.Where(m => m != null).Count() - 1;
|
|
|
|
|
if (menus[iMenuKey] != null)
|
|
|
|
|
{
|
|
|
|
|
dgv = menus[iMenuKey].GetDataGridView();
|
|
|
|
|
if (SelectMatched(dgv, iRowKey) ||
|
|
|
|
|
SelectMatched(dgv, 0))
|
|
|
|
|
{
|
|
|
|
|
RowDeselected(iRowBefore, dgvBefore);
|
|
|
|
|
SelectRow(dgv, iRowKey);
|
|
|
|
|
toClear = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-23 11:02:31 +13:00
|
|
|
|
private void SelectRow(ListView dgv, int iRowKey)
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
|
|
|
|
InUse = true;
|
|
|
|
|
RowSelected(dgv, iRowKey);
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-23 11:02:31 +13:00
|
|
|
|
private bool SelectMatched(ListView dgv, int indexStart, string keyInput = "")
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
|
|
|
|
bool found = false;
|
2022-10-23 11:02:31 +13:00
|
|
|
|
for (int i = indexStart; i < dgv.Items.Count; i++)
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
|
|
|
|
if (Select(dgv, i, keyInput))
|
|
|
|
|
{
|
|
|
|
|
found = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-07-07 07:15:45 +12:00
|
|
|
|
|
2020-06-21 03:38:21 +12:00
|
|
|
|
return found;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-23 11:02:31 +13:00
|
|
|
|
private bool SelectMatchedReverse(ListView dgv, int indexStart, string keyInput = "")
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
|
|
|
|
bool found = false;
|
|
|
|
|
for (int i = indexStart; i > -1; i--)
|
|
|
|
|
{
|
|
|
|
|
if (Select(dgv, i, keyInput))
|
|
|
|
|
{
|
|
|
|
|
found = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-07-07 07:15:45 +12:00
|
|
|
|
|
2020-06-21 03:38:21 +12:00
|
|
|
|
return found;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-23 11:02:31 +13:00
|
|
|
|
private bool Select(ListView dgv, int i, string keyInput = "")
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
|
|
|
|
bool found = false;
|
|
|
|
|
if (i > -1 &&
|
|
|
|
|
i != iRowKey &&
|
2022-10-23 11:02:31 +13:00
|
|
|
|
dgv.Items.Count > i)
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
2022-11-26 11:31:20 +13:00
|
|
|
|
Menu.ListViewItemData itemData = (Menu.ListViewItemData)dgv.Items[i];
|
|
|
|
|
RowData rowData = itemData.data;
|
|
|
|
|
if (itemData.ColumnText.StartsWith(keyInput, true, CultureInfo.InvariantCulture))
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
|
|
|
|
iRowKey = rowData.RowIndex;
|
|
|
|
|
rowData.IsSelected = true;
|
2022-11-26 11:31:20 +13:00
|
|
|
|
if (dgv.SelectedItems.Contains(itemData))
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
2022-11-26 11:31:20 +13:00
|
|
|
|
dgv.SelectedItems.Remove(itemData);
|
2020-06-21 03:38:21 +12:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-26 11:31:20 +13:00
|
|
|
|
dgv.SelectedItems.Add(itemData);
|
|
|
|
|
dgv.ScrollIntoView(itemData);
|
|
|
|
|
|
2020-06-21 03:38:21 +12:00
|
|
|
|
found = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 07:15:45 +12:00
|
|
|
|
return found;
|
2020-06-21 03:38:21 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ClearIsSelectedByKey(int menuIndex, int rowIndex)
|
|
|
|
|
{
|
|
|
|
|
Menu menu = menus[menuIndex];
|
|
|
|
|
if (menu != null && rowIndex > -1)
|
|
|
|
|
{
|
2022-10-23 11:02:31 +13:00
|
|
|
|
ListView dgv = menu.GetDataGridView();
|
|
|
|
|
if (dgv.Items.Count > rowIndex)
|
2020-06-21 03:38:21 +12:00
|
|
|
|
{
|
2022-11-26 11:31:20 +13:00
|
|
|
|
Menu.ListViewItemData itemData = (Menu.ListViewItemData)dgv.Items[rowIndex];
|
|
|
|
|
RowData rowData = itemData.data;
|
|
|
|
|
if (dgv.SelectedItems.Contains(itemData))
|
|
|
|
|
{
|
|
|
|
|
dgv.SelectedItems.Remove(itemData);
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-22 05:25:31 +13:00
|
|
|
|
if (rowData != null)
|
|
|
|
|
{
|
|
|
|
|
rowData.IsSelected = false;
|
|
|
|
|
rowData.IsClicking = false;
|
|
|
|
|
}
|
2020-06-21 03:38:21 +12:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-03-09 01:21:15 +13:00
|
|
|
|
}
|