diff --git a/Business/KeyboardInput.cs b/Business/KeyboardInput.cs index dcd4978..2b78074 100644 --- a/Business/KeyboardInput.cs +++ b/Business/KeyboardInput.cs @@ -183,14 +183,9 @@ namespace SystemTrayMenu.Handler { if (menu != null && itemData != null) { - ListView dgv = menu.GetDataGridView(); - if (dgv.SelectedItems.Contains(itemData)) - { - dgv.SelectedItems.Remove(itemData); - } + itemData.IsClicking = false; - itemData.data.IsSelected = false; - itemData.data.IsClicking = false; + menu.GetDataGridView().SelectedItems.Remove(itemData); } } @@ -200,7 +195,7 @@ namespace SystemTrayMenu.Handler Menu? menuBefore; ListViewItemData? rowBefore = focussedRow; bool doClearOldSelection = false; - bool wasSelected = focussedRow?.data.IsSelected ?? false; + bool wasSelected = focussedRow?.IsSelected ?? false; if (wasSelected) { @@ -220,9 +215,9 @@ namespace SystemTrayMenu.Handler if ((modifiers == ModifierKeys.None) && rowBefore != null && menuBefore != null) { RowData trigger = rowBefore.data; - if (trigger.IsMenuOpen || !trigger.IsPointingToFolder) + if (trigger.SubMenu != null || !trigger.IsPointingToFolder) { - trigger.OpenItem(out bool doCloseAfterOpen); + rowBefore.OpenItem(out bool doCloseAfterOpen); if (doCloseAfterOpen) { ClosePressed?.Invoke(); @@ -328,10 +323,10 @@ namespace SystemTrayMenu.Handler else if (focussedMenu?.ParentMenu != null) { // Next is in opposite key direction and prev is in key direction ==> Select parent/prev menu + int index = focussedMenu.RowDataParent?.RowIndex ?? -1; focussedMenu = focussedMenu.ParentMenu; focussedRow = null; - ListView dgv = focussedMenu.GetDataGridView(); - if (TrySelectNext(focussedMenu, dgv.Items.IndexOf(dgv.SelectedItems.Count > 0 ? dgv.SelectedItems[0] : null)) || + if (TrySelectNext(focussedMenu, index) || TrySelectNext(focussedMenu, 0)) { RaiseRowSelectionChanged(menuBefore, rowBefore); @@ -426,15 +421,6 @@ namespace SystemTrayMenu.Handler private void Select(ListView dgv, ListViewItemData itemData) { focussedRow = itemData; - itemData.data.IsSelected = true; - - // TODO: Refresh ListViewItems - optimize out - // ([remove and] add item to procove selection changed handler) - if (dgv.SelectedItems.Contains(itemData)) - { - dgv.SelectedItems.Remove(itemData); - } - dgv.SelectedItems.Add(itemData); } } diff --git a/Business/Menus.cs b/Business/Menus.cs index 6de2c5d..e994825 100644 --- a/Business/Menus.cs +++ b/Business/Menus.cs @@ -42,7 +42,6 @@ namespace SystemTrayMenu.Business private DateTime deactivatedTime = DateTime.MinValue; private OpenCloseState openCloseState = OpenCloseState.Default; private TaskbarPosition taskbarPosition = new WindowsTaskbar().Position; - private bool searchTextChanging; private bool showMenuAfterMainPreload; private Menu? mainMenu; @@ -393,18 +392,14 @@ namespace SystemTrayMenu.Business Menu? menu = mainMenu; if (menu != null) { - // The main menu gets loaded again - // Clean up menu status of previous one + // The main menu gets loaded again, reset list ListView dgvMainMenu = menu.GetDataGridView(); foreach (ListViewItemData item in dgvMainMenu.Items) { - RowData rowDataToClear = item.data; - rowDataToClear.IsMenuOpen = false; - rowDataToClear.IsClicking = false; - rowDataToClear.IsSelected = false; + item.IsClicking = false; } - RefreshSelection(dgvMainMenu); + dgvMainMenu.SelectedItem = null; menu.RelocateOnNextShow = true; @@ -492,11 +487,8 @@ namespace SystemTrayMenu.Business // TODO: Main menu should destroy sub menu(s?) when it becomes unusable menu.HideWithFade(false); - ListView? lv = menu.ParentMenu?.GetDataGridView(); - if (lv != null) - { - RefreshSelection(lv); - } + // TODO: Remove when setting SubMenu of RowData notifies about value change + menu.ParentMenu?.RefreshSelection(); } } @@ -519,7 +511,6 @@ namespace SystemTrayMenu.Business menu.SearchTextChanging += Menu_SearchTextChanging; void Menu_SearchTextChanging() { - searchTextChanging = true; waitToOpenMenu.MouseActive = false; } @@ -528,7 +519,6 @@ namespace SystemTrayMenu.Business { keyboardInput.SearchTextChanged(menu, isSearchStringEmpty); AdjustMenusSizeAndLocation(menu.Level + 1); - searchTextChanging = false; // if any open menu close if (!causedByWatcherUpdate) @@ -587,7 +577,6 @@ namespace SystemTrayMenu.Business menu.ClosePressed += MenusFadeOut; ListView dgv = menu.GetDataGridView(); - dgv.SelectionChanged += Dgv_SelectionChanged; if (menu.Level == 0) { @@ -600,10 +589,9 @@ namespace SystemTrayMenu.Business // Sub Menu (loading) if (IsMainUsable) { - RefreshSelection(menu.GetDataGridView()); - - // TODO: Re-enable again? HideOldMenu(menu, true); menu.ShowWithFade(!IsActiveApp(), false); + + menu.RefreshSelection(); } } @@ -644,49 +632,6 @@ namespace SystemTrayMenu.Business } } - private void Dgv_SelectionChanged(object sender, EventArgs e) => RefreshSelection((ListView)sender); - - private void RefreshSelection(ListView dgv) - { - dgv.SelectionChanged -= Dgv_SelectionChanged; - - foreach (ListViewItemData itemData in dgv.Items) - { - RowData rowData = itemData.data; - if (rowData.IsClicking) - { - itemData.BorderBrush = MenuDefines.ColorIcons; - itemData.BackgroundBrush = MenuDefines.ColorSelectedItem; - dgv.SelectedItems.Add(itemData); - } - else if (rowData.IsMenuOpen) - { - itemData.BorderBrush = MenuDefines.ColorOpenFolderBorder; - itemData.BackgroundBrush = MenuDefines.ColorOpenFolder; - dgv.SelectedItems.Add(itemData); - } - else if (rowData.IsSelected) - { - itemData.BorderBrush = MenuDefines.ColorSelectedItemBorder; - itemData.BackgroundBrush = MenuDefines.ColorSelectedItem; - dgv.SelectedItems.Add(itemData); - } - else - { - itemData.BorderBrush = Brushes.White; - itemData.BackgroundBrush = Brushes.White; - dgv.SelectedItems.Remove(itemData); - } - } - - dgv.SelectionChanged += Dgv_SelectionChanged; - - if (!searchTextChanging) - { - dgv.InvalidateVisual(); - } - } - private void SystemEvents_DisplaySettingsChanged(object? sender, EventArgs e) { dispatchter.Invoke(() => @@ -702,29 +647,14 @@ namespace SystemTrayMenu.Business }); } - private void HideOldMenu(Menu menuToShow, bool keepOrSetIsMenuOpen = false) + private void HideOldMenu(Menu menuToShow) { Menu? menuPrevious = menuToShow.ParentMenu; if (menuPrevious != null) { - // Clean up menu status IsMenuOpen for previous one - ListView dgvPrevious = menuPrevious.GetDataGridView(); - foreach (ListViewItemData item in dgvPrevious.Items) - { - RowData rowDataToClear = item.data; - if (rowDataToClear == menuToShow.RowDataParent) - { - rowDataToClear.IsMenuOpen = keepOrSetIsMenuOpen; - } - else - { - rowDataToClear.IsMenuOpen = false; - } - } - - RefreshSelection(dgvPrevious); - menuPrevious.SubMenu?.HideWithFade(true); + + menuPrevious.RefreshSelection(); } } diff --git a/Business/WaitToLoadMenu.cs b/Business/WaitToLoadMenu.cs index 185e1bb..09a3e66 100644 --- a/Business/WaitToLoadMenu.cs +++ b/Business/WaitToLoadMenu.cs @@ -152,19 +152,15 @@ namespace SystemTrayMenu.Handler alreadyOpened = false; this.dgv = dgv; - dgvItemData = itemData; - dgvItemData.data.IsSelected = true; - dgv.SelectedItem = dgvItemData; + dgv.SelectedItem = dgvItemData = itemData; } private void ResetData(ListView dgv, ListViewItemData itemData) { - RowData rowData = itemData.data; - rowData.IsSelected = false; - rowData.IsClicking = false; - dgv.SelectedItem = null; + itemData.IsClicking = false; + this.dgv = null; - dgvItemData = null; + dgv.SelectedItem = dgvItemData = null; } } } diff --git a/DataClasses/RowData.cs b/DataClasses/RowData.cs index 2321a12..bd2717e 100644 --- a/DataClasses/RowData.cs +++ b/DataClasses/RowData.cs @@ -110,12 +110,6 @@ namespace SystemTrayMenu.DataClasses internal Menu? SubMenu { get; set; } - internal bool IsMenuOpen { get; set; } // TODO: Implicitly set when SubMenu != null? - - internal bool IsClicking { get; set; } - - internal bool IsSelected { get; set; } - internal bool HiddenEntry { get; set; } internal int RowIndex { get; set; } @@ -167,7 +161,6 @@ namespace SystemTrayMenu.DataClasses internal void OpenItem(out bool doCloseAfterOpen, int clickCount = -1) { - IsClicking = false; doCloseAfterOpen = false; if (!IsPointingToFolder) diff --git a/UserInterface/Menu.xaml b/UserInterface/Menu.xaml index c33849a..d0c1a0e 100644 --- a/UserInterface/Menu.xaml +++ b/UserInterface/Menu.xaml @@ -193,7 +193,7 @@ - + diff --git a/UserInterface/Menu.xaml.cs b/UserInterface/Menu.xaml.cs index 3c7c5fb..ac71735 100644 --- a/UserInterface/Menu.xaml.cs +++ b/UserInterface/Menu.xaml.cs @@ -109,7 +109,6 @@ namespace SystemTrayMenu.UserInterface Level = RowDataParent.Level + 1; MainMenu = ParentMenu.MainMenu; RowDataParent.SubMenu = this; - RowDataParent.IsMenuOpen = true; buttonOpenFolder.Visibility = Visibility.Collapsed; buttonSettings.Visibility = Visibility.Collapsed; @@ -196,6 +195,7 @@ namespace SystemTrayMenu.UserInterface }); dgv.GotFocus += (_, _) => FocusTextBox(); + dgv.SelectionChanged += ListView_SelectionChanged; Loaded += (_, _) => { @@ -212,7 +212,6 @@ namespace SystemTrayMenu.UserInterface if (RowDataParent?.SubMenu == this) { RowDataParent.SubMenu = null; - RowDataParent.IsMenuOpen = false; } foreach (ListViewItemData item in dgv.Items) @@ -395,6 +394,9 @@ namespace SystemTrayMenu.UserInterface ((CollectionView)CollectionViewSource.GetDefaultView(dgv.ItemsSource)).Refresh(); } + // TODO: Check if it is implicitly already running due to SelectionChanged event + internal void RefreshSelection() => ListView_SelectionChanged(GetDataGridView(), null); + internal void AddItemsToMenu(List data, MenuDataDirectoryState? state, bool startIconLoading) { int foldersCount = 0; @@ -1176,6 +1178,34 @@ namespace SystemTrayMenu.UserInterface } } + private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs? e) + { + if (e != null) + { + foreach (ListViewItemData itemData in e.AddedItems) + { + itemData.IsSelected = true; + itemData.UpdateColors(); + } + + foreach (ListViewItemData itemData in e.RemovedItems) + { + itemData.IsSelected = false; + itemData.UpdateColors(); + } + } + else + { + // TODO: Refactor item selection to prevent running this loop + ListView lv = (ListView)sender; + foreach (ListViewItemData itemData in lv.Items) + { + itemData.IsSelected = lv.SelectedItems.Contains(itemData); + itemData.UpdateColors(); + } + } + } + private void ListViewItem_MouseEnter(object sender, MouseEventArgs e) { CellMouseEnter?.Invoke(this, (ListViewItemData)((ListViewItem)sender).Content); @@ -1201,7 +1231,7 @@ namespace SystemTrayMenu.UserInterface if (e.LeftButton == MouseButtonState.Pressed) { - itemData.data.IsClicking = true; + itemData.IsClicking = true; } if (e.RightButton == MouseButtonState.Pressed) @@ -1212,11 +1242,11 @@ namespace SystemTrayMenu.UserInterface } } - private void ListViewxItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) + private void ListViewItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { ListViewItemData itemData = (ListViewItemData)((ListViewItem)sender).Content; - itemData.data.OpenItem(out bool doClose, e.ClickCount); + itemData.OpenItem(out bool doClose, e.ClickCount); if (e.ClickCount == 1) { @@ -1251,20 +1281,26 @@ namespace SystemTrayMenu.UserInterface public Brush? BackgroundBrush { get => backgroundBrush; - set + private set { - backgroundBrush = value; - CallPropertyChanged(); + if (value != backgroundBrush) + { + backgroundBrush = value; + CallPropertyChanged(); + } } } public Brush? BorderBrush { get => borderBrush; - set + private set { - borderBrush = value; - CallPropertyChanged(); + if (value != borderBrush) + { + borderBrush = value; + CallPropertyChanged(); + } } } @@ -1273,8 +1309,11 @@ namespace SystemTrayMenu.UserInterface get => columnIcon; set { - columnIcon = value; - CallPropertyChanged(); + if (value != columnIcon) + { + columnIcon = value; + CallPropertyChanged(); + } } } @@ -1286,13 +1325,47 @@ namespace SystemTrayMenu.UserInterface internal int SortIndex { get; set; } + internal bool IsClicking { get; set; } + + internal bool IsSelected { get; set; } + + public override string ToString() => nameof(ListViewItemData) + ": " + ColumnText + ", Owner: " + (data.Owner?.ToString() ?? "null"); + /// /// Triggers an PropertyChanged event of INotifyPropertyChanged. /// /// Name of the changing property. public void CallPropertyChanged([CallerMemberName] string? propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - public override string ToString() => nameof(ListViewItemData) + ": " + ColumnText + ", Owner: " + (data.Owner?.ToString() ?? "null"); + internal void OpenItem(out bool doCloseAfterOpen, int clickCount = -1) + { + IsClicking = false; + data.OpenItem(out doCloseAfterOpen, clickCount); + } + + internal void UpdateColors() + { + if (IsClicking) + { + BorderBrush = MenuDefines.ColorIcons; + BackgroundBrush = MenuDefines.ColorSelectedItem; + } + else if (data.SubMenu != null) + { + BorderBrush = MenuDefines.ColorOpenFolderBorder; + BackgroundBrush = MenuDefines.ColorOpenFolder; + } + else if (IsSelected) + { + BorderBrush = MenuDefines.ColorSelectedItemBorder; + BackgroundBrush = MenuDefines.ColorSelectedItem; + } + else + { + BorderBrush = Brushes.White; + BackgroundBrush = Brushes.White; + } + } } } }