Files
C4IT-F4SD-Client/FasdDesktopUi/Basics/UserControls/SearchResult/CustomSearchResultCollection.xaml.cs
2025-11-11 11:03:42 +01:00

497 lines
17 KiB
C#

using C4IT.FASD.Base;
using C4IT.MultiLanguage;
using F4SD_AdaptableIcon;
using F4SD_AdaptableIcon.Enums;
using FasdDesktopUi.Basics.CustomEvents;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.UiActions;
using FasdDesktopUi.Basics.UserControls.SearchResult;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class CustomSearchResultCollection : UserControl
{
private Dictionary<enumFasdInformationClass, SearchResultCategory> _searchCategories;
#region IndexOfSelectedResultItem
private int _indexOfSelectedResultItem = int.MinValue;
public int IndexOfSelectedResultItem
{
get { return _indexOfSelectedResultItem; }
set
{
if (_indexOfSelectedResultItem == value)
return;
if (value < -1)
_indexOfSelectedResultItem = int.MinValue;
else if (value == -1)
_indexOfSelectedResultItem = GetSearchResultCount() - 1;
else if (value == GetSearchResultCount())
_indexOfSelectedResultItem = 0;
else
_indexOfSelectedResultItem = value;
HandleIndexOfSelectedResultItemChanged();
}
}
#endregion
private cMenuDataBase _lastSelectedMenuData = null;
public bool ShowSearchResultDetails
{
get { return cFasdCockpitConfig.Instance.ShowSearchResultDetails; }
set
{
cFasdCockpitConfig.Instance.ShowSearchResultDetails = value;
cFasdCockpitConfig.Instance.Save("ShowSearchResultDetails");
}
}
public CustomSearchResultCollection()
{
InitializeComponent();
}
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
AddHandler(CustomEventManager.IndexChangedEvent, new CustomEventManager.IndexChangedHandlerDelegate(UpdateIndexOfSelectedResultItem));
AddHandler(CustomEventManager.MenuDataChangedEvent, new CustomEventManager.MenuDataChangedHandlerDelegate((_, args) => _lastSelectedMenuData = args.MenuData));
}
private void UpdateIndexOfSelectedResultItem(object sender, IndexEventArgs args)
{
try
{
if (!(args.OriginalSource is SearchResultCategory category))
return;
var indexOfSender = _searchCategories.Values.ToList().IndexOf(category);
int updatedIndex = args.NewValue;
for (int i = 0; i < indexOfSender; i++)
{
updatedIndex += _searchCategories.Values.ToList()[i].GetItemCount();
}
IndexOfSelectedResultItem = updatedIndex;
}
catch (Exception ex)
{
LogException(ex);
}
}
public bool IsEmpty() => MainStackPanel.Children.Count == 0;
internal int GetSearchResultCount()
{
int itemCount = 0;
foreach (var resultCategory in _searchCategories.Values)
{
itemCount += resultCategory.GetItemCount();
}
return itemCount;
}
private void HandleIndexOfSelectedResultItemChanged()
{
try
{
int totalResultItemCount = 0;
foreach (var category in _searchCategories.Values)
{
int categoryItemCount = category.GetItemCount();
if (IndexOfSelectedResultItem > totalResultItemCount)
category.HiglightItemAt(-1);
if (IndexOfSelectedResultItem < totalResultItemCount + categoryItemCount)
category.HiglightItemAt(IndexOfSelectedResultItem - totalResultItemCount);
totalResultItemCount += categoryItemCount;
}
}
catch (Exception E)
{
LogException(E);
}
}
public void SetHeaderText(string headerText, bool hideDetailsCheckbox = false)
{
try
{
HeaderTextBlock.Text = headerText;
HeaderTextBlock.Visibility = string.IsNullOrEmpty(headerText) ? Visibility.Collapsed : Visibility.Visible;
ShowDetailsCheckBox.Visibility = string.IsNullOrEmpty(headerText) || hideDetailsCheckbox ? Visibility.Collapsed : Visibility.Visible;
}
catch (Exception E)
{
LogException(E);
}
}
private void ProcessNewItems()
{
UpdateCornerRadius();
UpdateSearchResultDetailsShown(ShowSearchResultDetails);
}
public void ShowLoadingTextItem(string itemText)
{
try
{
ClearControl();
var menuItem = new CustomMenuItem(false) { MenuData = new cMenuDataLoading(itemText) };
MainStackPanel.Children.Add(menuItem);
ProcessNewItems();
}
catch (Exception E)
{
LogException(E);
}
}
public void ShowSearchResults(cFilteredResults SearchResults, string headerText, ISearchUiProvider searchUiProvider)
{
try
{
ClearControl();
SetHeaderText(headerText);
if (SearchResults?.Results is null || SearchResults.Results.Count == 0)
ProcessNoSearchResults();
else
ProcessSearchResults();
ProcessNewItems();
}
catch (Exception E)
{
LogException(E);
}
void ProcessNoSearchResults()
{
var resultItemControl = new CustomMenuItem(false)
{
MenuData = new cMenuDataBase()
{
MenuText = cMultiLanguageSupport.GetItem("SearchBar.NoResults"),
MenuIcon = new IconData(enumInternIcons.menuBar_search_noResults)
}
};
MainStackPanel.Children.Add(resultItemControl);
}
void ProcessSearchResults()
{
if (!_searchCategories.TryGetValue(enumFasdInformationClass.Main, out var mainCategory))
return;
List<cMenuDataBase> menuDataList = new List<cMenuDataBase>();
mainCategory.UpdateSearchResults(SearchResults.Results, searchUiProvider);
UpdatePendingInformationClasses(new HashSet<enumFasdInformationClass>());
}
}
public void ShowSearchHistory()
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
ClearControl();
SetHeaderText(cMultiLanguageSupport.GetItem("Searchbar.History.Title"), true);
if (cSearchManager.Instance.HistoryList.Count <= 0)
{
this.Visibility = Visibility.Collapsed;
return;
}
this.Visibility = Visibility.Visible;
foreach (var historyEntry in cSearchManager.Instance.HistoryList)
{
var menuData = new cMenuDataBase() { MenuText = historyEntry.DisplayText, UiAction = new cUiProcessSearchHistoryEntry(historyEntry) };
if (historyEntry.isSeen)
{
menuData.MenuIcon = new IconData(MaterialIcons.MaterialIconType.ic_visibility);
menuData.MenuIconSize = 0.75;
}
MainStackPanel.Children.Add(new CustomMenuItem(true) { MenuData = menuData });
}
ProcessNewItems();
}
catch (Exception E)
{
LogException(E);
}
finally
{
LogMethodEnd(CM);
}
}
public void UpdateSearchRelations(ILookup<enumFasdInformationClass, cMenuDataBase> relations)
{
try
{
if (_searchCategories is null)
return;
int indexOfMenuData = -1;
int indexOfMenuDataCategory = -1;
foreach (var relation in relations)
{
if (!_searchCategories.TryGetValue(relation.Key, out var category))
continue;
category.UpdateSearchRelations(relation);
if (indexOfMenuData != -1)
continue;
indexOfMenuData = GetIndexOf(relation.Select(value => value.Data), _lastSelectedMenuData?.Data);
if (indexOfMenuData != -1)
indexOfMenuDataCategory = GetIndexOf(_searchCategories.Values, category);
}
ProcessNewItems();
if (indexOfMenuData == -1)
return;
IndexOfSelectedResultItem = indexOfMenuData + _searchCategories.Take(indexOfMenuDataCategory).Sum(category => category.Value.GetItemCount());
}
catch (Exception ex)
{
LogException(ex);
}
// even if not ideal, seems to be the most performant solution for retrieving the index of IEnumerable
int GetIndexOf(IEnumerable<object> data, object value)
{
int index = 0;
foreach (var item in data)
{
if (item.Equals(value))
return index;
index++;
}
return -1;
}
}
private void ClearControl()
{
MainStackPanel.Children.Clear();
var mainCategory = new SearchResultCategory() { IsPending = false };
_searchCategories = new Dictionary<enumFasdInformationClass, SearchResultCategory>() { [enumFasdInformationClass.Main] = mainCategory };
MainStackPanel.Children.Add(mainCategory);
_lastSelectedMenuData = null;
IndexOfSelectedResultItem = int.MinValue;
HandleIndexOfSelectedResultItemChanged();
}
public void SelectCurrentResultItem()
{
try
{
int totalResultItemCount = 0;
foreach (var category in _searchCategories.Values)
{
int categoryItemCount = category.GetItemCount();
if (IndexOfSelectedResultItem < totalResultItemCount + categoryItemCount)
{
category.SelectItemAt(IndexOfSelectedResultItem - totalResultItemCount);
return;
}
totalResultItemCount += categoryItemCount;
}
}
catch (Exception E)
{
LogException(E);
}
}
private void UpdateCornerRadius()
{
try
{
const double cornerRadius = 10;
if (MainStackPanel.Children.Count <= 0)
return;
if (MainStackPanel.Children[0] is CustomMenuItem resultItemFirst)
{
var tempCornerRadius = resultItemFirst.MenuItemBorder.CornerRadius;
tempCornerRadius.TopLeft = cornerRadius;
tempCornerRadius.TopRight = cornerRadius;
resultItemFirst.MenuItemBorder.CornerRadius = tempCornerRadius;
}
if (MainStackPanel.Children[MainStackPanel.Children.Count - 1] is CustomMenuItem resultItemLast)
{
var tempCornerRadiusLast = resultItemLast.MenuItemBorder.CornerRadius;
tempCornerRadiusLast.BottomLeft = cornerRadius;
tempCornerRadiusLast.BottomRight = cornerRadius;
resultItemLast.MenuItemBorder.CornerRadius = tempCornerRadiusLast;
}
}
catch (Exception E)
{
LogException(E);
}
}
private void ShowDetailsCheckBox_Checked(object sender, RoutedEventArgs e)
{
if (!(sender is CheckBox checkBox))
return;
cFasdCockpitConfig.Instance.ShowSearchResultDetails = checkBox.IsChecked == true;
cFasdCockpitConfig.Instance.Save("ShowSearchResultDetails");
UpdateSearchResultDetailsShown(checkBox.IsChecked);
}
private void UpdateSearchResultDetailsShown(bool? showDetailHeadings)
{
try
{
if (showDetailHeadings is null)
return;
if (MainStackPanel?.Children is null || MainStackPanel.Children.Count <= 0)
return;
foreach (var searchResult in MainStackPanel.Children.OfType<CustomMenuItem>())
{
searchResult.ShowDetailHeadings(showDetailHeadings.Value);
}
foreach (var searchResult in MainStackPanel.Children.OfType<SearchResultCategory>())
{
searchResult.ShowDetailHeadings(showDetailHeadings.Value);
}
}
catch (Exception ex)
{
LogException(ex);
}
}
public void SetPendingInformationClasses(HashSet<enumFasdInformationClass> informationClasses)
{
try
{
MainStackPanel.Children.Clear();
_searchCategories = new Dictionary<enumFasdInformationClass, SearchResultCategory>();
foreach (var informationClass in informationClasses.Reverse())
{
var searchResultCategory = new SearchResultCategory()
{
Title = string.Format(cMultiLanguageSupport.GetItem("Searchbar.Relations.SearchFor"), informationClass),
IsPending = true,
TitleIcon = GetIconFrom(informationClass),
Margin = new Thickness(0, 7.5, 0, 0)
};
_searchCategories.Add(informationClass, searchResultCategory);
MainStackPanel.Children.Add(searchResultCategory);
}
}
catch (Exception ex)
{
LogException(ex);
}
IconData GetIconFrom(enumFasdInformationClass informationClass)
{
switch (informationClass)
{
case enumFasdInformationClass.Computer:
return new IconData(enumInternIcons.misc_computer);
case enumFasdInformationClass.User:
return new IconData(enumInternIcons.misc_user);
case enumFasdInformationClass.Ticket:
return new IconData(enumInternIcons.menuBar_mail);
case enumFasdInformationClass.VirtualSession:
return new IconData(MaterialIcons.MaterialIconType.ic_cloud_queue);
case enumFasdInformationClass.MobileDevice:
return new IconData(MaterialIcons.MaterialIconType.ic_smartphone);
default:
return new IconData(enumInternIcons.f4sd);
}
}
}
public void UpdatePendingInformationClasses(HashSet<enumFasdInformationClass> informationClasses)
{
try
{
if (_searchCategories is null)
return;
var finishedInformationClasses = _searchCategories.Where(category => !informationClasses.Contains(category.Key)).Select(category => category.Value);
foreach (var pendingCategory in finishedInformationClasses)
{
pendingCategory.IsPending = false;
if (pendingCategory.GetItemCount() == 0)
pendingCategory.Margin = new Thickness(0);
else
pendingCategory.Margin = new Thickness(0, 7.5, 0, 0);
}
if (IndexOfSelectedResultItem != int.MinValue)
return;
if (_searchCategories.Values.Any(c => c.IsPending))
return;
IndexOfSelectedResultItem = _searchCategories.Values.Sum(c => c.GetItemCount()) - 1;
}
catch (Exception ex)
{
LogException(ex);
}
}
}
}