Rework ListViewItemData and RowData members

Improve UI updates due to unnecessary color and selection changes of menus' lists
Fix selection when going back to previous menu via key
This commit is contained in:
Peter Kirmeier 2023-05-09 00:19:29 +02:00
parent 14d0896419
commit bb198a32db
6 changed files with 109 additions and 131 deletions

View file

@ -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);
}
}

View file

@ -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();
}
}

View file

@ -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;
}
}
}

View file

@ -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)

View file

@ -193,7 +193,7 @@
<EventSetter Event="MouseEnter" Handler="ListViewItem_MouseEnter" />
<EventSetter Event="MouseLeave" Handler="ListViewItem_MouseLeave" />
<EventSetter Event="PreviewMouseDown" Handler="ListViewItem_PreviewMouseDown" />
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListViewxItem_PreviewMouseLeftButtonDown" />
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListViewItem_PreviewMouseLeftButtonDown" />
</Style>
</ListView.ItemContainerStyle>
</ListView>

View file

@ -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<RowData> 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");
/// <summary>
/// Triggers an PropertyChanged event of INotifyPropertyChanged.
/// </summary>
/// <param name="propertyName">Name of the changing property.</param>
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;
}
}
}
}
}