using System; using System.Collections.Generic; using System.Linq; 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.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Globalization; using System.Reflection; using FasdDesktopUi.Basics.UiActions; using FasdDesktopUi.Basics.Enums; using FasdDesktopUi.Basics.Models; using FasdDesktopUi.Basics.UserControls; using FasdDesktopUi.Pages.DetailsPage.Models; using FasdDesktopUi.Basics.UserControls.AdaptableIcon; using C4IT.MultiLanguage; using C4IT.FASD.Base; using static C4IT.Logging.cLogManager; using F4SD_AdaptableIcon.Enums; using C4IT.Logging; using static C4IT.FASD.Base.cHealthCardTranslator; using FasdDesktopUi.Basics; namespace FasdDesktopUi.Pages.DetailsPage.UserControls { public partial class DetailsPageDataHistoryValueColumn : UserControl { #region Properties public List AggregateRowIndexes { get; set; } public double ColumnWidth { get; set; } = 50; #region SubtitleCount DependencyProperty private static void SubtitleCountChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (!(d is DetailsPageDataHistoryValueColumn _me)) return; _me.ClearControls(); _me.InitializeValueControls((int)e.NewValue); } public static readonly DependencyProperty SubtitleCountProperty = DependencyProperty.Register("SubtitleCount", typeof(int), typeof(DetailsPageDataHistoryValueColumn), new PropertyMetadata(1, new PropertyChangedCallback(SubtitleCountChangedCallback))); public int SubtitleCount { get { return (int)GetValue(SubtitleCountProperty); } set { SetValue(SubtitleCountProperty, value); } } #endregion #region ColumnValues DependencyProperty private static void ColumnValuesChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (!(d is DetailsPageDataHistoryValueColumn _me)) return; var updatedColumnValues = (DetailsPageDataHistoryColumnModel)e.NewValue; _me.UpdateColumnSize(updatedColumnValues.ColumnValues.Count - _me.MainGrid.RowDefinitions.Count); _me.RefreshColumnHeader(updatedColumnValues.Content); _me.RefreshColumnStatusIcon(updatedColumnValues.HighlightColor); _me.RefreshValueSection(updatedColumnValues); } public static readonly DependencyProperty ColumnValuesProperty = DependencyProperty.Register("ColumnValues", typeof(DetailsPageDataHistoryColumnModel), typeof(DetailsPageDataHistoryValueColumn), new PropertyMetadata(new DetailsPageDataHistoryColumnModel(), new PropertyChangedCallback(ColumnValuesChangedCallback))); public DetailsPageDataHistoryColumnModel ColumnValues { get { return (DetailsPageDataHistoryColumnModel)GetValue(ColumnValuesProperty); } set { SetValue(ColumnValuesProperty, value); } } #endregion #region ValueRecommendations DependencyProperty public static readonly DependencyProperty ValueRecommendationsProperty = DependencyProperty.Register("ValueRecommendations", typeof(List), typeof(DetailsPageDataHistoryValueColumn), new PropertyMetadata(new List())); public List ValueRecommendations { get { return (List)GetValue(ValueRecommendationsProperty); } set { SetValue(ValueRecommendationsProperty, value); } } #endregion #endregion #region Controls private readonly List ValueControls = new List(); private readonly List FunctionMarkers = new List(); #endregion private void ClearControls() { try { foreach (var functionMarker in FunctionMarkers) { if (functionMarker.Parent is FrameworkElement functionMarkerParent) MainGrid.Children.Remove(functionMarkerParent); } ValueControls.Clear(); FunctionMarkers.Clear(); } catch (Exception E) { LogException(E); } } private void UpdateBorderThresholdValues(Border border, cDataHistoryValueModel valueInfo) { try { switch (valueInfo?.HighlightColor) { case enumHighlightColor.none: border.ClearValue(TagProperty); border.SetResourceReference(StyleProperty, "DetailsPage.DataHistory.ValueBorder"); break; case enumHighlightColor.blue: border.SetResourceReference(StyleProperty, "DetailsPage.DataHistory.ValueBorder.Blue"); break; case enumHighlightColor.green: border.SetResourceReference(StyleProperty, "DetailsPage.DataHistory.ValueBorder.Green"); break; case enumHighlightColor.orange: border.SetResourceReference(StyleProperty, "DetailsPage.DataHistory.ValueBorder.Orange"); break; case enumHighlightColor.red: border.SetResourceReference(StyleProperty, "DetailsPage.DataHistory.ValueBorder.Red"); break; default: border.ClearValue(TagProperty); border.SetResourceReference(StyleProperty, "DetailsPage.DataHistory.ValueBorder"); break; }; border.Tag = valueInfo?.ThresholdValues; } catch (Exception E) { LogException(E); } } #region Initialize Controls private void InitializeValueRow(int rowIndex) { MainGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(35) }); DockPanel valueDockPanel = new DockPanel() { Margin = new Thickness(-19, 0, 0, 0) }; Border valueBorder = new Border() { Style = dataHistoryValueBorderStyle }; #if isNewFeature valueBorder.ToolTip = (ToolTip)FindResource("Tooltip.Treshold"); valueBorder.ToolTipOpening += TresholdToolTipEventHandler; #endif TextBlock valueTextBlock = new TextBlock(); valueBorder.Child = valueTextBlock; ValueControls.Add(valueTextBlock); valueDockPanel.Children.Add(valueBorder); var valueFunctionMarker = FunctionMarker.SetUpFunctionMarker(valueDockPanel, new FunctionMarker.FunctionMarkerClick(FunctionMarker_Click)); FunctionMarkers.Add(valueFunctionMarker); DockPanel.SetDock(valueBorder, Dock.Left); Grid.SetRow(valueDockPanel, rowIndex); MainGrid.Children.Add(valueDockPanel); } public void TresholdToolTipEventHandler(object sender, ToolTipEventArgs e) { #if isNewFeature try { if (!(sender is Border _b) || !(_b.Tag is cStateThresholdValues _v) || !(_b.ToolTip is StatusTreshholdTooltip _t)) { e.Handled = true; return; } cUtility.FillTresholdToolTip(_v, _t); } catch (Exception E) { LogException(E); } #endif } private void InitializeValueControls(int valueCount) { for (int i = 0; i < valueCount; i++) { try { InitializeValueRow(i); } catch (Exception E) { LogException(E); } } } private void FunctionMarker_Click(object sender) { if (!(sender is FrameworkElement FE)) return; if (!(FE.Tag is cDataHistoryValueModel HistoryValue)) return; if (HistoryValue.UiAction == null) return; cUiActionBase.RaiseEvent(HistoryValue.UiAction, this, this); } #endregion #region Update Controls private void UpdateColumnSize(int rowsToAdd) { if (rowsToAdd > 0) { int rowIndex = MainGrid.RowDefinitions.Count; for (int i = rowIndex; i < rowsToAdd + rowIndex; i++) { InitializeValueRow(i); } } else { MainGrid.RowDefinitions.ToList().ForEach(rowDefinitions => rowDefinitions.Height = new GridLength(35)); var reversedRowList = MainGrid.RowDefinitions.Reverse().ToList(); for (int i = 0; i < Math.Abs(rowsToAdd); i++) { reversedRowList[i].Height = new GridLength(0); } } } #endregion #region Refresh Values private void RefreshColumnHeader(string columnHeader) { string headerContent; if (int.TryParse(columnHeader, out int dayIndex)) { CultureInfo culture = new CultureInfo(cMultiLanguageSupport.CurrentLanguage); string customDateFormat = cMultiLanguageSupport.GetItem("Global.Date.Format.ShortDateWithDay", "ddd. dd.MM."); headerContent = dayIndex == 0 ? cMultiLanguageSupport.GetItem("Global.Date.Today", DateTime.Now.ToString(customDateFormat, culture)) : DateTime.Today.AddDays(-dayIndex).ToString(customDateFormat, culture); } else headerContent = columnHeader; ColumnHeaderTextBlock.Text = headerContent; } private void RefreshColumnStatusIcon(enumHighlightColor? statusColor) { ColumnStatusIcon.IconWidth = 25; if (ColumnValues.ColumnValues.Any(value => value.IsLoading && value.Content == "-") && statusColor != enumHighlightColor.red) { //todo: replace loading icon ColumnStatusIcon.SelectedInternIcon = enumInternIcons.menuBar_more; ColumnStatusIcon.PrimaryIconColor = iconColor; return; } switch (statusColor) { case enumHighlightColor.blue: ColumnStatusIcon.SelectedInternIcon = enumInternIcons.status_info; ColumnStatusIcon.PrimaryIconColor = blueBrush; ColumnStatusIcon.SecondaryIconColor = Brushes.White; break; case enumHighlightColor.green: ColumnStatusIcon.SelectedInternIcon = enumInternIcons.status_good; ColumnStatusIcon.PrimaryIconColor = greenBrush; ColumnStatusIcon.SecondaryIconColor = Brushes.White; break; case enumHighlightColor.orange: ColumnStatusIcon.SelectedInternIcon = enumInternIcons.status_danger; ColumnStatusIcon.PrimaryIconColor = orangeBrush; ColumnStatusIcon.SecondaryIconColor = Brushes.White; break; case enumHighlightColor.red: ColumnStatusIcon.SelectedInternIcon = enumInternIcons.status_bad; ColumnStatusIcon.PrimaryIconColor = redBrush; ColumnStatusIcon.SecondaryIconColor = Brushes.White; break; default: ColumnStatusIcon.SelectedInternIcon = enumInternIcons.status_empty; ColumnStatusIcon.SetResourceReference(AdaptableIcon.PrimaryIconColorProperty, "Color.SoftContrast"); ColumnStatusIcon.IconWidth = 15; break; } } private void RefreshColumnValues(DetailsPageDataHistoryColumnModel columnData) { try { var valueRowEnumerator = columnData.ColumnValues.GetEnumerator(); int tempTitleRowIndex = 0; foreach (var valueRow in ValueControls) { if (!valueRowEnumerator.MoveNext()) continue; if (AggregateRowIndexes != null && AggregateRowIndexes.Contains(tempTitleRowIndex)) { var valueRowData = valueRowEnumerator.Current; if (!(valueRow is TextBlock valueRowTextBlock)) continue; valueRowTextBlock.Style = dataHistoryValueAggregateStyle; valueRowTextBlock.Text = valueRowData.Content; #if !isNewFeature valueRowTextBlock.ToolTip = valueRowData.ContentDescription; #endif if (valueRow.Parent is FrameworkElement valueRowParent) { valueRowParent.ClearValue(TagProperty); valueRowParent.SetResourceReference(StyleProperty, "DetailsPage.DataHistory.ValueBorder"); } switch (valueRowData.HighlightColor) { case enumHighlightColor.none: valueRowTextBlock.SetResourceReference(ForegroundProperty, "FontColor.DetailsPage.DataHistory.Value"); break; case enumHighlightColor.blue: valueRowTextBlock.SetResourceReference(ForegroundProperty, "Color.Blue"); break; case enumHighlightColor.green: valueRowTextBlock.SetResourceReference(ForegroundProperty, "Color.Green"); break; case enumHighlightColor.orange: valueRowTextBlock.SetResourceReference(ForegroundProperty, "Color.Orange"); break; case enumHighlightColor.red: valueRowTextBlock.SetResourceReference(ForegroundProperty, "Color.Red"); break; default: valueRowTextBlock.SetResourceReference(ForegroundProperty, "FontColor.DetailsPage.DataHistory.Value"); break; }; valueRow.Visibility = Visibility.Visible; valueRow.Opacity = 1; } else { var valueRowData = valueRowEnumerator.Current; if (!(valueRow is TextBlock valueRowTextBlock)) continue; valueRowTextBlock.ClearValue(ForegroundProperty); valueRowTextBlock.Style = dataHistoryValueStyle; valueRowTextBlock.Text = valueRowData.Content; #if !isNewFeature valueRowTextBlock.ToolTip = valueRowData.ContentDescription; #endif Style borderStyle = new Style() { BasedOn = dataHistoryValueBorderStyle }; if (valueRow.Parent is Border valueRowParentBorder) UpdateBorderThresholdValues(valueRowParentBorder, valueRowData); valueRow.Visibility = Visibility.Visible; valueRow.Opacity = 1; if (valueRowData.Content == "-" && valueRowData.IsLoading) { valueRowTextBlock.Text = "..."; } } tempTitleRowIndex++; } } catch (Exception E) { LogException(E); } finally { } } private void RefreshFunctionMarker(DetailsPageDataHistoryColumnModel columnData) { var valueRowEnumerator = columnData.ColumnValues.GetEnumerator(); foreach (var valueRow in FunctionMarkers) { if (valueRowEnumerator.MoveNext()) { var valueRowData = valueRowEnumerator.Current; if (valueRowData.UiAction != null) { valueRow.Tag = valueRowData; var tempToolTip = valueRowData.UiAction.Name; if (!string.IsNullOrEmpty(valueRowData.UiAction.Description)) tempToolTip += ": \n" + valueRowData.UiAction.Description; valueRow.ToolTip = tempToolTip; valueRow.Visibility = Visibility.Visible; } else valueRow.Visibility = Visibility.Hidden; } } } private void RefreshValueSection(DetailsPageDataHistoryColumnModel columnData) { RefreshColumnValues(columnData); RefreshFunctionMarker(columnData); } #endregion #region UpdateValues private bool DidCellValueChange(cDataHistoryValueModel oldData, cDataHistoryValueModel newData) { try { if (oldData is null || newData is null) return true; if (oldData.Content.Equals(newData.Content) == false || oldData.IsLoading != newData.IsLoading) return true; } catch (Exception E) { LogException(E); } finally { } return false; } public void UpdateHistoryValues(DetailsPageDataHistoryColumnModel columnData) { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { if (columnData?.ColumnValues is null) return; for (int i = 0; i < columnData.ColumnValues.Count; i++) { var oldValue = ColumnValues?.ColumnValues?.Count > i ? ColumnValues.ColumnValues[i] : null; var newValue = columnData.ColumnValues[i]; if (ValueControls.Count < i) continue; if (DidCellValueChange(oldValue, newValue)) { if (ValueControls[i] is TextBlock valueTextBlock) { valueTextBlock.Text = newValue?.Content; #if !isNewFeature valueTextBlock.ToolTip = newValue?.Content; #endif valueTextBlock.Visibility = Visibility.Visible; } if (ValueControls[i].Parent is Border valueBorder) { UpdateBorderThresholdValues(valueBorder, newValue); } } if (newValue.Content.Equals("Ø")) { if (ValueControls[i] is TextBlock aggregateTextBlock) switch (newValue.HighlightColor) { case enumHighlightColor.green: aggregateTextBlock.Foreground = greenBrush; break; case enumHighlightColor.orange: aggregateTextBlock.Foreground = orangeBrush; break; case enumHighlightColor.red: aggregateTextBlock.Foreground = redBrush; break; default: break; } } } if (ColumnValues is null) ColumnValues = new DetailsPageDataHistoryColumnModel(); ColumnValues.ColumnValues = columnData.ColumnValues; RefreshColumnStatusIcon(columnData.HighlightColor); Visibility = Visibility.Visible; } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } } #endregion public DetailsPageDataHistoryValueColumn() { InitializeComponent(); } #region Events #region VerticalCollapse #region VerticalCollapsedChanged public void ToggleVerticalCollapse(bool isVisible) { (MainGrid.Parent as FrameworkElement).Visibility = isVisible ? Visibility.Visible : Visibility.Collapsed; } public static readonly RoutedEvent StatusBorderClickedEvent = EventManager.RegisterRoutedEvent("StatusBorderClickedEventHandler", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DetailsPageDataHistoryValueColumn)); public event RoutedEventHandler StatusBorderClickedEventHandler { add { AddHandler(StatusBorderClickedEvent, value); } remove { RemoveHandler(StatusBorderClickedEvent, value); } } private void RaiseStatusBorderClickedEvent() { RoutedEventArgs newEventArgs = new RoutedEventArgs(StatusBorderClickedEvent); RaiseEvent(newEventArgs); } private void TitleRowBorder_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { RaiseStatusBorderClickedEvent(); } private void TitleRowBorder_TouchDown(object sender, TouchEventArgs e) { RaiseStatusBorderClickedEvent(); } #endregion #endregion #region MouseOver Events #region EnterTitleRow public static readonly RoutedEvent MouseEnterTitleRowEvent = EventManager.RegisterRoutedEvent("MouseEnterTitleRowEventHandler", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DetailsPageDataHistoryValueColumn)); public event RoutedEventHandler MouseEnterTitleRowEventHandler { add { AddHandler(MouseEnterTitleRowEvent, value); } remove { RemoveHandler(MouseEnterTitleRowEvent, value); } } private void RaiseMouseEnterTitleRowEvent() { RoutedEventArgs newEventArgs = new RoutedEventArgs(MouseEnterTitleRowEvent); RaiseEvent(newEventArgs); } private void TitleRowBorder_MouseEnter(object sender, MouseEventArgs e) { RaiseMouseEnterTitleRowEvent(); } #endregion #region LeaveTitleRow public static readonly RoutedEvent MouseLeaveTitleRowEvent = EventManager.RegisterRoutedEvent("MouseLeaveTitleRowEventHandler", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DetailsPageDataHistoryValueColumn)); public event RoutedEventHandler MouseLeaveTitleRowEventHandler { add { AddHandler(MouseLeaveTitleRowEvent, value); } remove { RemoveHandler(MouseLeaveTitleRowEvent, value); } } private void RaiseMouseLeaveTitleRowEvent() { RoutedEventArgs newEventArgs = new RoutedEventArgs(MouseLeaveTitleRowEvent); RaiseEvent(newEventArgs); } private void TitleRowBorder_MouseLeave(object sender, MouseEventArgs e) { RaiseMouseLeaveTitleRowEvent(); } #endregion #endregion private void UserControl_Initialized(object sender, EventArgs e) { SetStyles(); } #endregion #region Style Definitions private Style dataHistoryValueStyle; private Style dataHistoryValueAggregateStyle; private Style dataHistoryValueBorderStyle; private SolidColorBrush blueBrush; private SolidColorBrush greenBrush; private SolidColorBrush orangeBrush; private SolidColorBrush redBrush; private SolidColorBrush iconColor; private void SetStyles() { dataHistoryValueStyle = (Style)FindResource("DetailsPage.DataHistory.Value"); dataHistoryValueAggregateStyle = (Style)FindResource("DetailsPage.DataHistory.Value.Aggregate"); dataHistoryValueBorderStyle = (Style)FindResource("DetailsPage.DataHistory.ValueBorder"); blueBrush = (SolidColorBrush)FindResource("Color.Blue"); greenBrush = (SolidColorBrush)FindResource("Color.Green"); orangeBrush = (SolidColorBrush)FindResource("Color.Orange"); redBrush = (SolidColorBrush)FindResource("Color.Red"); iconColor = (SolidColorBrush)FindResource("Color.Menu.Icon"); } #endregion } }