using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Globalization; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Threading; using C4IT.Logging; using C4IT.MultiLanguage; using FasdDesktopUi.Basics; using FasdDesktopUi.Basics.Enums; using FasdDesktopUi.Pages.DetailsPage.Models; using static C4IT.Logging.cLogManager; namespace FasdDesktopUi.Pages.DetailsPage.UserControls { public partial class DetailsPageDataHistoryCollection : UserControl { #region Properties public cSupportCaseDataProvider DataProvider { get; set; } #region DetailsGeometry DependencyProperty private static bool DidGeometryDataChanged(DependencyPropertyChangedEventArgs e) { bool didGeometryChange = false; var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { if (e.NewValue != null && e.OldValue != null) { var newValue = e.NewValue as DetailsPageDataHistoryCollectionGeometryModel; var oldValue = e.OldValue as DetailsPageDataHistoryCollectionGeometryModel; didGeometryChange = newValue.ColumnCount != oldValue.ColumnCount || didGeometryChange; var oldValueSubtitleEnumerator = oldValue.SubtitleCount.GetEnumerator(); foreach (var subtitleCount in newValue.SubtitleCount) { if (oldValueSubtitleEnumerator.MoveNext()) { didGeometryChange = subtitleCount != oldValueSubtitleEnumerator.Current || didGeometryChange; } else { didGeometryChange = true; } } } else { didGeometryChange = true; } } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } return didGeometryChange; } private static void GeometryChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (DidGeometryDataChanged(e) is false) return; var _me = d as DetailsPageDataHistoryCollection; _me.InitializeCollectionGeometry(); } public static readonly DependencyProperty DetailsGeometryProperty = DependencyProperty.Register("DetailsGeometry", typeof(DetailsPageDataHistoryCollectionGeometryModel), typeof(DetailsPageDataHistoryCollection), new PropertyMetadata(new DetailsPageDataHistoryCollectionGeometryModel(), new PropertyChangedCallback(GeometryChangedCallback))); public DetailsPageDataHistoryCollectionGeometryModel DetailsGeometry { get { return (DetailsPageDataHistoryCollectionGeometryModel)GetValue(DetailsGeometryProperty); } set { SetValue(DetailsGeometryProperty, value); } } #endregion #region HistoryDataList DependencyProperty static void RefreshDataCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is DetailsPageDataHistoryCollection _me) { _me.UpdateDetailsCollection(); _me.RefreshData(); } } public static readonly DependencyProperty HistoryDataListProperty = DependencyProperty.Register("HistoryDataList", typeof(List), typeof(DetailsPageDataHistoryCollection), new PropertyMetadata(new List(), new PropertyChangedCallback(RefreshDataCallback))); public List HistoryDataList { get { return (List)GetValue(HistoryDataListProperty); } set { SetValue(HistoryDataListProperty, value); } } #endregion #region ShownValueColumnsCount DependencyProperty public static readonly DependencyProperty ShownValueColumnsCountProperty = DependencyProperty.Register("ShownValueColumnsCount", typeof(int), typeof(DetailsPageDataHistoryCollection), new PropertyMetadata(5)); public int ShownValueColumnsCount { get { return (int)GetValue(ShownValueColumnsCountProperty); } set { SetValue(ShownValueColumnsCountProperty, value); } } #endregion #endregion public DetailsPageDataHistoryCollection() { InitializeComponent(); AddCustomEventHandlers(); } private void AddCustomEventHandlers() { AddHandler(DetailsPageDataHistoryValueColumn.StatusBorderClickedEvent, new RoutedEventHandler(ChangedVerticalCollapseEvent)); AddHandler(DetailsPageDataHistoryTitleColumn.StatusBorderClickedEvent, new RoutedEventHandler(ChangedVerticalCollapseEvent)); } #region SetUpControls #region Control Lists public readonly List HistorySectionControls = new List(); #endregion #region SetUp/Initialize Functions private delegate void DelegateFunction(); private void InitializeCollectionGeometry() { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { if (DesignerProperties.GetIsInDesignMode(this) || DetailsGeometry == null) return; Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background, new DelegateFunction(() => { DataHistoryCollectionStackPanel.Children.Clear(); HistorySectionControls.Clear(); for (int i = 0; i < DetailsGeometry.SubtitleCount.Count; i++) { DetailsPageDataHistorySection historySectionToCreate = new DetailsPageDataHistorySection() { ColumnCount = DetailsGeometry.ColumnCount, SubtitleCount = DetailsGeometry.SubtitleCount[i], Margin = new Thickness(0, 0, 0, 10) }; historySectionToCreate.HistoryValueScrollViewer.ScrollChanged += HistoryValueScrollViewer_ScrollChanged; DataHistoryCollectionStackPanel.Children.Add(historySectionToCreate); HistorySectionControls.Add(historySectionToCreate); } })); } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } } private void HistoryValueScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e) { foreach (var historyControl in HistorySectionControls) { historyControl.HistoryValueScrollViewer.ScrollToHorizontalOffset(e.HorizontalOffset); } } public void ToggleHorizontalCollapseHistory(bool isHorizontalVisible) { HistorySectionControls.ForEach(historyControl => historyControl.IsHorizontalCollapsed = !isHorizontalVisible); } #endregion #endregion #region Update Controls private void UpdateDetailsCollection() { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { if (HistoryDataList == null) return; UpdateHistorySections(); UpdateColumnWidths(); } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } } private void UpdateHistorySections() { try { int missingDataSections = HistoryDataList.Count - HistorySectionControls.Count; if (missingDataSections > 0) { for (int i = 0; i < missingDataSections; i++) { DetailsPageDataHistorySection historySectionToCreate = new DetailsPageDataHistorySection() { ColumnCount = DetailsGeometry.ColumnCount, SubtitleCount = int.MinValue, Margin = new Thickness(0, 0, 0, 10) }; historySectionToCreate.HistoryValueScrollViewer.ScrollChanged += HistoryValueScrollViewer_ScrollChanged; DataHistoryCollectionStackPanel.Children.Add(historySectionToCreate); HistorySectionControls.Add(historySectionToCreate); } } else if (missingDataSections < 0 && HistorySectionControls.Count + missingDataSections >= 0) { var categoriesToHide = HistorySectionControls.Skip(HistorySectionControls.Count + missingDataSections); foreach (var categoryToHide in categoriesToHide) { categoryToHide.Visibility = Visibility.Collapsed; } } HistorySectionControls.GetRange(0, HistoryDataList.Count).ForEach(section => section.Visibility = Visibility.Visible); } catch (Exception E) { LogException(E); } } private void ChangedVerticalCollapseEvent(object sender, RoutedEventArgs e) { try { if (!(e.OriginalSource is FrameworkElement senderFrameworkElement)) return; if (!(senderFrameworkElement.Tag is DetailsPageDataHistorySection senderHistorySection)) return; if (senderHistorySection.IsVerticalExpandLocked) return; bool tempExpandStatus = senderHistorySection.IsVerticalExpanded; foreach (var historySection in HistorySectionControls) { if (!historySection.IsVerticalExpandLocked) historySection.IsVerticalExpanded = false; } if (!tempExpandStatus) VerticalUncollapseDataHistory(senderHistorySection); else senderHistorySection.IsVerticalExpanded = !tempExpandStatus; } catch (Exception E) { LogException(E); } } private void UpdateColumnWidths() { try { const int maxValueColumnWidth = 140; double titleColumnWidth = 50; double valueColumnWidth = 50; foreach (var historyData in HistoryDataList) { double tempTitleColumnWidth = GetTitleColumnWidth(historyData); double tempValueColumnWidth = GetValueColumnWidth(historyData); titleColumnWidth = tempTitleColumnWidth > titleColumnWidth ? tempTitleColumnWidth : titleColumnWidth; valueColumnWidth = tempValueColumnWidth > valueColumnWidth ? tempValueColumnWidth : valueColumnWidth; } valueColumnWidth = Math.Min(valueColumnWidth, maxValueColumnWidth); foreach (var historyData in HistoryDataList) { historyData.TitleColumnWidth = titleColumnWidth + 15; historyData.ValueColumnWidth = valueColumnWidth + 10; } } catch (Exception E) { LogException(E); } } #endregion #region RefreshData private void RefreshData() { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { if (HistoryDataList is null || HistoryDataList.Count == 0) { Visibility = Visibility.Collapsed; return; } Visibility = Visibility.Visible; var DataEnumerator = HistoryDataList.GetEnumerator(); foreach (var Entry in HistorySectionControls) { if (DataEnumerator.MoveNext()) { var Data = DataEnumerator.Current; Entry.ShownValueColumnsCount = this.ShownValueColumnsCount; //Entry.Visibility = Visibility.Visible; //Entry.Visibility = Data?.TitleColumn.ColumnValues.Count <= 0 ? Visibility.Collapsed : Visibility.Visible; // && Data?.ValueColumns.Any(column => column.IsLoading) == false // && Data?.ValueColumns.Any(column => column.ColumnValues.Any(columnValue => columnValue.IsLoading)) == false ? Visibility.Collapsed : Visibility.Visible; Entry.HistoryData = Data; } else { //Entry.Visibility = Visibility.Collapsed; Entry.HistoryData = null; } } } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } } #endregion #region UpdateData public void UpdateHistory(List historyData) { try { if (HistoryDataList is null || HistoryDataList.Count == 0) { Visibility = Visibility.Collapsed; return; } Visibility = Visibility.Visible; var historyDataEnumerator = HistoryDataList.GetEnumerator(); for (int i = 0; i < historyData.Count; i++) { var historyCategory = historyData[i]; historyDataEnumerator.MoveNext(); var currentHistoryData = historyDataEnumerator.Current; if (DidHistoryCategoryChange(currentHistoryData, historyCategory)) HistorySectionControls[i]?.UpdateHistoryData(historyCategory); } HistoryDataList = historyData; UpdateColumnWidths(); } catch (Exception E) { LogException(E); } } private bool DidHistoryCategoryChange(cDetailsPageDataHistoryDataModel oldValue, cDetailsPageDataHistoryDataModel newValue) { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { if (oldValue is null || newValue is null) return true; if (oldValue.ValueColumns.Count != newValue.ValueColumns.Count) return true; var newValueColumnEnumeator = newValue.ValueColumns.GetEnumerator(); foreach (var oldValueColumn in oldValue.ValueColumns) { if (!newValueColumnEnumeator.MoveNext()) continue; var currentNewValueColumn = newValueColumnEnumeator.Current; var newValueColumnValueEnumerator = currentNewValueColumn.ColumnValues.GetEnumerator(); foreach (var oldCellValue in oldValueColumn.ColumnValues) { var valueRowIndex = oldValueColumn.ColumnValues.IndexOf(oldCellValue); if (!newValueColumnValueEnumerator.MoveNext()) continue; if (oldCellValue.Content.Equals(newValueColumnValueEnumerator.Current.Content) == false) return true; } } } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } return false; } #endregion #region StyleDefinitions private Style titleColumnOverViewTitleStyle; private Style titleColumnMainTitleStyle; private Style titleCoumnSubTitleStyle; private void SetStyles() { titleColumnOverViewTitleStyle = (Style)FindResource("DetailsPage.DataHistory.TitleColumn.OverviewTitle"); titleColumnMainTitleStyle = (Style)FindResource("DetailsPage.DataHistory.TitleColumn.MainTitle"); titleCoumnSubTitleStyle = (Style)FindResource("DetailsPage.DataHistory.TitleColumn.SubTitle"); } private static Size MeasureStringSize(string stringToMeasure, Control controlOfText) { var formattedText = new FormattedText( stringToMeasure, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(controlOfText.FontFamily, controlOfText.FontStyle, controlOfText.FontWeight, controlOfText.FontStretch), controlOfText.FontSize, Brushes.Black, new NumberSubstitution(), 1); return new Size(formattedText.Width, formattedText.Height); } private double GetTitleColumnWidth(cDetailsPageDataHistoryDataModel detailsData) { double maxTitleLength = MeasureStringSize(detailsData.TitleColumn.Content, new TextBox { Style = titleColumnOverViewTitleStyle }).Width + 90; foreach (var subtitle in detailsData.TitleColumn.ColumnValues) { Style subtitleStyle; switch (subtitle.PresentationStyle) { case enumHistoryTitleType.value: subtitleStyle = titleColumnMainTitleStyle; break; case enumHistoryTitleType.subValue: subtitleStyle = titleCoumnSubTitleStyle; break; default: subtitleStyle = titleColumnMainTitleStyle; break; }; double subtitleLength = MeasureStringSize(subtitle.Content, new TextBox { Style = subtitleStyle }).Width; maxTitleLength = maxTitleLength < subtitleLength ? subtitleLength + 70 : maxTitleLength; } return maxTitleLength; } private double GetValueColumnWidth(cDetailsPageDataHistoryDataModel detailsData) { double maxValueWidth = 55; //55 to set MinWidth foreach (var valueColumn in detailsData.ValueColumns) { foreach (var value in valueColumn.ColumnValues) { var valueSize = MeasureStringSize(value.Content, new Control() { Style = titleColumnOverViewTitleStyle }); maxValueWidth = valueSize.Width > maxValueWidth ? valueSize.Width : maxValueWidth; } } return maxValueWidth + 30; //+30 to include functionmarker width } #endregion #region Event Methods #region UserControl private void UserControl_Initialized(object sender, EventArgs e) { SetStyles(); } #endregion #region Collapse #region Vertical Uncollapse Specific DataHistory public void VerticalUncollapseDataHistory(DetailsPageDataHistorySection historySection) { try { var historyIndex = DataHistoryCollectionStackPanel.Children.IndexOf(historySection); VerticalUncollapseDataHistory(historyIndex); } catch (Exception E) { LogException(E); } } public void VerticalUncollapseDataHistory(int historyIndex) { try { if (historyIndex >= DataHistoryCollectionStackPanel.Children.Count) return; HistorySectionControls.ForEach(historyControl => { if (!historyControl.IsVerticalExpandLocked) historyControl.IsVerticalExpanded = false; }); (DataHistoryCollectionStackPanel.Children[historyIndex] as DetailsPageDataHistorySection).IsVerticalExpanded = true; var _h = Dispatcher.Invoke(async () => { await Task.Delay(1); var position = (DataHistoryCollectionStackPanel.Children[historyIndex] as DetailsPageDataHistorySection).TranslatePoint(new Point(0, 0), DataHistoryCollectionStackPanel); DetailsCollectionScrollViewer.ScrollToVerticalOffset(position.Y); }); } catch (Exception E) { LogException(E); } } #endregion #region Vertical Collapse Details public void ToggleVerticalCollapseDetails(bool collapse) { try { foreach (var detail in HistorySectionControls) { if (detail.IsVerticalExpandLocked) continue; detail.IsVerticalExpanded = !collapse; } } catch (Exception E) { LogException(E); } } private void CollapseButton_MouseUp(object sender, MouseButtonEventArgs e) { ToggleVerticalCollapseDetails(true); } private void CollapseButton_TouchDown(object sender, TouchEventArgs e) { ToggleVerticalCollapseDetails(true); } private void UnCollapseButton_MouseUp(object sender, MouseButtonEventArgs e) { ToggleVerticalCollapseDetails(false); } private void UnCollapseButton_TouchDown(object sender, TouchEventArgs e) { ToggleVerticalCollapseDetails(false); } #endregion #endregion private void DetailsCollectionScrollViewer_PreviewKeyDown(object sender, KeyEventArgs e) { e.Handled = true; } #endregion } }