using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Windows; using System.Windows.Input; using System.Windows.Interop; using System.Windows.Media.Effects; using System.Windows.Controls; using System.Threading.Tasks; using System.Windows.Media.Animation; using System.Windows.Threading; using System.Windows.Documents; using System.Windows.Media; using System.Windows.Shell; using FasdDesktopUi.Basics; using FasdDesktopUi.Basics.UiActions; using FasdDesktopUi.Basics.UserControls; using FasdDesktopUi.Basics.Models; using FasdDesktopUi.Basics.Helper; using FasdDesktopUi.Pages.SettingsPage; using FasdDesktopUi.Pages.DetailsPage.Models; using FasdDesktopUi.Pages.DetailsPage.ViewModels; using FasdDesktopUi.Pages.DetailsPage.UserControls; using C4IT.FASD.Base; using C4IT.MultiLanguage; using static C4IT.Logging.cLogManager; using F4SD_AdaptableIcon.Enums; using FasdDesktopUi.Basics.CustomEvents; using FasdDesktopUi.Basics.Converter; using FasdDesktopUi.Basics.Services.SupportCase.Controllers; namespace FasdDesktopUi.Pages.DetailsPage { public partial class DetailsPageView : SupportCasePageBase { #region Properties and Variables private int MinSizeWidth = 300; private int MinSizeHeigth = 200; private bool IsWindowLoaded = false; private bool HasZoomChanged = false; private bool isDataProviderLoading = false; private bool shouldReRunDataChangedEvent = false; private bool isHorizontalCollapsed = true; private bool isQuickActionSelectorVisible = false; private bool isQuickActionDecoratorVisible = false; private bool isNotepadDecoratorVisible = false; private readonly DispatcherTimer _midnightTimer = new DispatcherTimer(); private double _lastDesiredHeightOfWidgetCollection = 0; // to avoid resizing the main grid on every data changed event #region Notepad public bool SupportNotepad { get; private set; } = false; public bool NotepadVisibility { get; private set; } = false; public bool TicketDialogNotepadVisibility { get; private set; } = true; public object NotepadParent { get; private set; } = null; Notepad notepad; Window popoutWindow; public bool isNotepadNotEmpty = false; #endregion #endregion #region Blurring internal override void DoBlurredChanged(bool isBlured) { List uneffectedControls = new List() { nameof(SearchResultBorder), nameof(OverlayBorder), nameof(BlurBorder) }; if (!(Body.Child is Grid mainGrid)) return; foreach (FrameworkElement child in mainGrid.Children) { if (uneffectedControls.Contains(child.Name)) continue; child.Effect = isBlured ? new BlurEffect() { Radius = 15, KernelType = KernelType.Gaussian } : null; } } internal override bool CheckBlurInvoker(IBlurInvoker invoker) { try { switch (invoker) { case SettingsPageBase _: case CustomMessageBox.CustomMessageBox _: case TicketCompletion.TicketCompletion _: case SearchBar _: case SuccessPage.SuccessPage _: case BlurInvokerContainer _: return true; default: break; } } catch (Exception E) { LogException(E); } return false; } #endregion public DetailsPageView() { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { InitializeComponent(); _midnightTimer.Interval = TimeSpan.FromSeconds(1); _midnightTimer.Tick += MidnightTimer_Tick; _midnightTimer.Start(); SupportNotepad = true; var _screen = System.Windows.Forms.Screen.PrimaryScreen; Top = _screen.Bounds.Y; Left = _screen.Bounds.X; Height = 1; Width = 1; MinHeight = 0; MinWidth = 0; } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } } ~DetailsPageView() { BlurInvoker.BlurInvokerVisibilityChanged -= (obj, e) => UpdateBlurStatus(obj); } internal override void SetSupportCaseController(SupportCaseController supportCaseController) { if (_supportCaseController != null) UnsubscribeEventsOf(_supportCaseController); ResetPageToDefaultState(); SubscribeEventsOf(supportCaseController); base.SetSupportCaseController(supportCaseController); NavigationHeadingUc.SupportCaseController = supportCaseController; IsBlurred = true; RefreshControl.DataProvider = supportCaseController.SupportCaseDataProviderArtifact; NavigationHeadingUc.DataProvider = supportCaseController.SupportCaseDataProviderArtifact; cSupportCaseDataProvider.CaseChanged += DataProvider_CaseChanged; RefreshControl.IsDataIncomplete = true; RefreshControl.LoadingDataIndicatorUc.LoadingText = cMultiLanguageSupport.GetItem("DetailsPage.Loading"); CustomizableSectionUc.IsDataIncomplete = true; supportCaseController.SupportCaseDataProviderArtifact.NotepadDocumentUpdated += ResetNotepadNotification; void SubscribeEventsOf(SupportCaseController controller) { controller.AvailableCaseRelationsAdded += HandleAvailableRelationsAdded; controller.FocusedRelationsChanged += HandleFocusedRelationsChanged; controller.CaseDataChanged += HandleCaseDataChanged; controller.HeadingDataChanged += HandleHeadingDataChanged; } void UnsubscribeEventsOf(SupportCaseController controller) { controller.AvailableCaseRelationsAdded -= HandleAvailableRelationsAdded; controller.FocusedRelationsChanged -= HandleFocusedRelationsChanged; controller.CaseDataChanged -= HandleCaseDataChanged; controller.HeadingDataChanged -= HandleHeadingDataChanged; } } private void HandleAvailableRelationsAdded(object sender, RelationEventArgs e) { } private void HandleFocusedRelationsChanged(object sender, RelationEventArgs e) { IsBlurred = false; _supportCaseController.SupportCaseDataProviderArtifact.Identities = e.Relations.FirstOrDefault()?.FirstOrDefault()?.Identities; // todo remove when ShowDetailedDataAction is not dependent on Artifact anymore Dispatcher.Invoke(() => { ResetPageToDefaultState(); UpdateHealthcardSectionVisibilities(); HandleCaseDataChanged(null, null); }); } private void HandleHeadingDataChanged(object sender, HeadingDataEventArgs e) { Dispatcher.Invoke(() => NavigationHeadingUc.HeadingData = e.NewValue.ToList()); } // todo update NavigationHeadingUc_HeadingIconClickedEvent as soon as EventArgs are taken into account private void HandleCaseDataChanged(object sender, SupportCaseDataEventArgs e) { try { if (isDataChangedEventRunning) { shouldReRunDataChangedEvent = true; return; } isDataChangedEventRunning = true; Dispatcher.Invoke(() => { if (QuickActionDecorator.Child is DataCanvas dataCanvas) Dispatcher.Invoke(async () => await dataCanvas.UpdateDataAsync()); if (WidgetCollection.WidgetDataList is null || WidgetCollection.WidgetDataList.Count == 0) WidgetCollection.WidgetDataList = _supportCaseController?.GetWidgetData(); WidgetCollection.UpdateWidgetData(_supportCaseController?.GetWidgetData()); if (DataHistoryCollectionUserControl.HistoryDataList is null || DataHistoryCollectionUserControl.HistoryDataList.Count == 0) DataHistoryCollectionUserControl.HistoryDataList = _supportCaseController?.GetHistoryData(); DataHistoryCollectionUserControl.UpdateHistory(_supportCaseController?.GetHistoryData()); if (CustomizableSectionUc.ContainerCollections is null || CustomizableSectionUc.ContainerCollections.Count == 0) CustomizableSectionUc.ContainerCollections = _supportCaseController?.GetContainerData(); CustomizableSectionUc.UpdateContainerCollection(_supportCaseController?.GetContainerData()); if (this.DataContext is DetailsPageViewModel viewModel) viewModel.MenuBarData = _supportCaseController?.GetMenuBarData(); if (_lastDesiredHeightOfWidgetCollection != WidgetCollection.DesiredSize.Height) { _lastDesiredHeightOfWidgetCollection = WidgetCollection.DesiredSize.Height; MainGrid.InvalidateMeasure(); MainGrid.UpdateLayout(); } }); if (shouldReRunDataChangedEvent) HandleCaseDataChanged(sender, e); } finally { isDataChangedEventRunning = false; shouldReRunDataChangedEvent = false; } } /// /// Sets the visibility of History and Customizable Section based on the currently selected Healthcard. /// internal void UpdateHealthcardSectionVisibilities() { try { cHealthCard selectedHealthcard = _supportCaseController.SupportCaseDataProviderArtifact.HealthCardDataHelper.SelectedHealthCard; bool showHistorySection = selectedHealthcard.CategoriesHistory?.StateCategories != null && selectedHealthcard.CategoriesHistory.StateCategories.Count > 0; Dispatcher.Invoke(() => { DataHistoryCollectionUserControl.Visibility = showHistorySection ? Visibility.Visible : Visibility.Collapsed; CustomizableSectionUc.Visibility = showHistorySection ? Visibility.Collapsed : Visibility.Visible; }); } catch (Exception ex) { LogException(ex); } } private void ReinitializeNotepad() { if (SupportNotepad == true) { notepad = new Notepad(_supportCaseController?.SupportCaseDataProviderArtifact); ChangeNotepadNotification(); NotepadDecorator.Child = notepad; NotepadDecorator.Visibility = Visibility.Collapsed; notepad.Visibility = Visibility.Collapsed; NotepadVisibility = false; NotepadParent = NotepadDecorator; notepad.LockStatusChanged += NotepadLockStatusChangedAction; notepad.NotepadVisibilityChanged += NotepadChangeVisibilityAction; notepad.IsUndockedChanged += IsUndockedChangeAction; if (cFasdCockpitConfig.Instance.IsNotepadVisibleDocked == true) { NotepadChangeVisibilityAction(this, true); } } } private async Task InitialWindowPositionAsync() { var _screen = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea; var _dpi = cUtility.GetDpiFactor(); Width = _screen.Width / 2 / _dpi.Width; Height = _screen.Height / 2 / _dpi.Height; Top = _screen.Top / _dpi.Height + (_screen.Height / _dpi.Height - Height) / 2; Left = _screen.Left / _dpi.Width + (_screen.Width / _dpi.Width - Width) / 2; await Task.Delay(20); IsWindowLoaded = true; this.WindowState = WindowState.Maximized; } private void SetMinimalWindowSize() { //var _locLeft = this.PointToScreen(new Point(0, 0)).X; //var _locRight = this.PointToScreen(new Point(ActualWidth, 0)).X; //var _locMidLeft = NavigationHeadingUc.PointToScreen(new Point(NavigationHeadingUc.ActualWidth, 0)).X; //var _locMidRight = CloseCaseWithTicketIcon.PointToScreen(new Point(0, 0)).X; //var _locCorr = NavigationHeadingUc.PointFromScreen(new Point(0, NavigationHeadingUc.ActualHeight)).Y - NavigationHeadingUc.PointFromScreen(new Point(0, 0)).Y; //MinSizeWidth = (int)(_locMidLeft - _locLeft + _locRight - _locMidRight + _locCorr); MinSizeWidth = 1200; var _locTop = this.PointToScreen(new Point(0, 0)).Y; var _locBottom = this.PointToScreen(new Point(0, ActualHeight)).Y; var _locMidTop = Body.PointToScreen(new Point(0, 0)).Y; var _locMidBottom = WidgetCollection.PointToScreen(new Point(0, WidgetCollection.ActualHeight)).Y; _locMidTop += (_locMidBottom - _locMidTop) * 1.5; _locMidBottom = Body.PointToScreen(new Point(0, Body.ActualHeight)).Y; MinSizeHeigth = (int)(_locMidTop - _locTop + _locBottom - _locMidBottom); } private async void DetailsPage_Loaded(object sender, RoutedEventArgs e) { try { ReinitializeNotepad(); AddCustomEventHandlers(); await InitialWindowPositionAsync(); } catch (Exception E) { LogException(E); } } #region Events & DelegateMethods private void AddCustomEventHandlers() { AddHandler(DetailsPageDataHistorySection.HorizontalCollapseClickedEvent, new RoutedEventHandler(HorizontalCollapseWasClicked)); AddHandler(cUiActionBase.UiActionClickedEvent, new cUiActionBase.UiActionEventHandlerDelegate(UiActionWasTriggered)); AddHandler(DetailsPageStateContainer.MaximizeContainerEvent, new DetailsPageStateContainer.ContainerEventHandlerDelegate(StateContainerWasMaximized)); AddHandler(DetailsPageStateContainer.CloseMaximizedContainerEvent, new RoutedEventHandler((obj, e) => OverlayBorder.Visibility = Visibility.Collapsed)); AddHandler(QuickActionStatusMonitor.QuickActionFinishedEvent, new QuickActionStatusMonitor.UiActionEventHandlerDelegate(HandleQuickActionFinished)); BlurInvoker.BlurInvokerVisibilityChanged += (obj, e) => UpdateBlurStatus(obj); NavigationHeadingUc.HeadingIconClickedEvent += NavigationHeadingUc_HeadingIconClickedEvent; RefreshControl.RefreshButtonClicked += RefreshButtonClickedEvent; MenuBarUserControl.SearchButtonClickedAction = SearchButtonClickedAction; MenuBarUserControl.MoreButtonClickedAction = MoreButtonClickedAction; SearchBarUserControl.ChangedSearchValue = EnteredSearchValueAsync; SearchBarUserControl.CancledSearchAction = BlurBorder_Click; QuickActionSelectorUc.LockStatusChanged = QuickActionSelectorLockStatusChangedAction; CloseCaseDialogWithTicket.TicketNotepadChanged += TicketChangeNotepadAction; cFasdCockpitConfig.Instance.UiSettingsChanged += CockpitConfig_UiSettingsChanged; cConnectionStatusHelper.ApiConnectionStatusChanged += ApiConnectionStatusChanged; cHealthCardDataHelper.EditModeChanged += (obj, e) => SetEditMode(e.BooleanArg); cFocusInvoker.GotFocus += ElementGotFocus; cFocusInvoker.LostFocus += ElementLostFocus; } private void HandleQuickActionFinished(object sender, QuickActionEventArgs e) { if (!QuickTipStatusMonitorUc.IsVisible) return; QuickTipStatusMonitorUc.UpdateAutomatedStepStatus(e.QuickActionStatus, e.QuickAction); } #region BlurBorder Click private void BlurBorder_Click() { BlurBorder_Click(keepTicketCompletion: false); } private void BlurBorder_Click(bool keepTicketCompletion) { try { Dispatcher.Invoke(() => { Panel.SetZIndex(NavigationHeadingUc, 1); NavigationHeadingUc.ResetSelectors(); if (cConnectionStatusHelper.Instance?.ApiConnectionStatus == cConnectionStatusHelper.enumOnlineStatus.online) { SearchBarUserControl.Visibility = Visibility.Collapsed; SearchBarUserControl.Clear(); MenuBarUserControl.Visibility = Visibility.Visible; } SearchResultBorder.Visibility = Visibility.Collapsed; OverlayBorder.Child = null; OverlayBorder.Visibility = Visibility.Collapsed; if (BlurInvokers?.Count > 0) { foreach (var blurInvoker in BlurInvokers.ToArray()) { if (keepTicketCompletion && blurInvoker is TicketCompletion.TicketCompletion) continue; if (blurInvoker is Window blurInvokerWindow) blurInvokerWindow.Hide(); } } IsBlurred = BlurInvokers?.Count > 0; }); } catch (Exception E) { LogException(E); } } private void BlurBorder_MouseUp(object sender, MouseButtonEventArgs e) { BlurBorder_Click(); } private void BlurBorder_TouchDown(object sender, TouchEventArgs e) { BlurBorder_Click(); } #endregion #region EventMethods private void ElementGotFocus(object sender, EventArgs e) { try { FocusBorder.Visibility = Visibility.Visible; if (!(sender is FrameworkElement senderElement)) return; if (!FocusBorder.IsVisible) return; var desiredHeight = senderElement.ActualHeight; var desiredWidth = senderElement.ActualWidth; FrameworkElement placeHolderElement = new FrameworkElement() { Height = desiredHeight, Width = desiredWidth, Margin = senderElement.Margin }; FocusDecorator.Height = desiredHeight + senderElement.Margin.Top + senderElement.Margin.Bottom; FocusDecorator.Width = desiredWidth + senderElement.Margin.Left + senderElement.Margin.Right; Point? relativePoint = null; // Find the correct ancestor for the transformation FrameworkElement parent = senderElement; try { relativePoint = senderElement.TransformToAncestor(this).Transform(new Point(0, 0)); } catch (InvalidOperationException) { } if (!relativePoint.HasValue) return; if (senderElement.Parent is Decorator actualParentDecorator) { actualParentDecorator.Child = placeHolderElement; } else if (senderElement.Parent is Panel actualParentPanel) { if (actualParentPanel is Grid) { Grid.SetColumn(placeHolderElement, Grid.GetColumn(senderElement)); Grid.SetRow(placeHolderElement, Grid.GetRow(senderElement)); } actualParentPanel.Children.Insert(actualParentPanel.Children.IndexOf(senderElement), placeHolderElement); actualParentPanel.Children.Remove(senderElement); } double zoomFactor = 1.0; if (DataContext is DetailsPageViewModel viewModel) { zoomFactor = viewModel.ZoomInPercent / 100.0; } if (relativePoint != null) { var p = relativePoint.Value; Canvas.SetLeft(FocusDecorator, p.X - (senderElement.Margin.Left * zoomFactor)); Canvas.SetTop(FocusDecorator, p.Y - senderElement.Margin.Top * zoomFactor); } FocusDecorator.Child = senderElement; } catch (Exception E) { LogException(E); } } private void ElementLostFocus(object sender, EventArgs e) { try { FocusBorder.Visibility = Visibility.Collapsed; } catch (Exception E) { LogException(E); } } private async void RefreshButtonClickedEvent(object sender, EventArgs e) { try { RefreshControl.IsDataIncomplete = true; await _supportCaseController.RefreshDataForCurrentlyFocusedRelationAsync(); RefreshControl.UpdateLastDataRequestTime(); RefreshControl.IsDataIncomplete = false; } catch (Exception E) { LogException(E); } } private void HorizontalCollapseWasClicked(object sender, RoutedEventArgs e) { isHorizontalCollapsed = !isHorizontalCollapsed; ToggleHorizontalCollapse(isHorizontalCollapsed); } private async void UiActionWasTriggered(object sender, UiActionEventArgs e) { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { // define drawing area UIElement drawingArea = this; switch (e.UiAction) { case cChangeHealthCardAction _: case cShowHeadingSelectionMenuAction _: case UiShowRawHealthcardValues _: break; case cUiQuickAction _: case cShowRecommendationAction _: case cShowDetailedDataAction _: drawingArea = QuickActionDecorator; ToggleHorizontalCollapse(true, true); break; case cSubMenuAction _: drawingArea = QuickActionSelectorUc; ToggleHorizontalCollapse(true, true); break; case cUiShowNotepadQuickAction _: ToggleHorizontalCollapse(true, true); break; case cUiQuickTipAction _: drawingArea = QuickTipStatusMonitorUc; ToggleHorizontalCollapse(true, true); break; } await e.UiAction.RunUiActionAsync(e.OriginalSource, drawingArea, true, _supportCaseController?.SupportCaseDataProviderArtifact); UpdateHistoryWidth(); } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } } private void StateContainerWasMaximized(object sender, DetailsPageStateContainer.ContainerEventArgs e) { try { OverlayBorder.Child = e.MaximizedControl; OverlayBorder.Visibility = Visibility.Visible; } catch (Exception E) { LogException(E); } } private async void NavigationHeadingUc_HeadingIconClickedEvent(object sender, EventArgs e) { try { if (!(sender is FrameworkElement senderElement)) return; if (!(senderElement.Tag is cF4sdApiSearchResultRelation selectedRelation)) return; _supportCaseController.UpdateFocusedCaseRelation(selectedRelation); } catch (Exception E) { LogException(E); } finally { Mouse.OverrideCursor = null; } } private void UpdateFooterPositions() { try { if (cFasdCockpitConfig.Instance.Global.FavouriteBarAlignment is enumF4sdHorizontalAlignment.Left) { IconTimerPanel.HorizontalAlignment = HorizontalAlignment.Right; IconTimerPanel.Children.Remove(F4SDIcon); IconTimerPanel.Children.Insert(1, F4SDIcon); } else { IconTimerPanel.HorizontalAlignment = HorizontalAlignment.Left; IconTimerPanel.Children.Remove(F4SDIcon); IconTimerPanel.Children.Insert(0, F4SDIcon); } MenuBarUserControl.HorizontalAlignment = InternalEnumConverter.GetHorizontalAlignment(cFasdCockpitConfig.Instance.Global.FavouriteBarAlignment); } catch (Exception E) { LogException(E); } } private void CockpitConfig_UiSettingsChanged(object sender, EventArgs e) { UpdateHistoryWidth(); UpdateFooterPositions(); } private void ApiConnectionStatusChanged(cConnectionStatusHelper.enumOnlineStatus? Status) { try { if (Status == cConnectionStatusHelper.enumOnlineStatus.online) { Dispatcher.Invoke(() => { Footer.ClearValue(IsHitTestVisibleProperty); Footer.ClearValue(OpacityProperty); QuickActionSelectorUc.ClearValue(IsHitTestVisibleProperty); QuickActionSelectorUc.ClearValue(OpacityProperty); QuickActionDecorator.ClearValue(IsHitTestVisibleProperty); QuickActionDecorator.ClearValue(OpacityProperty); if (MenuBarUserControl.Visibility == Visibility.Collapsed) { SearchBarUserControl.Visibility = Visibility.Collapsed; MenuBarUserControl.Visibility = Visibility.Visible; } }); } else { Dispatcher.Invoke(() => { Footer.IsHitTestVisible = false; QuickActionSelectorUc.IsHitTestVisible = false; QuickActionSelectorUc.Opacity = 0.6; QuickActionDecorator.IsHitTestVisible = false; QuickActionDecorator.Opacity = 0.6; if (SearchBarUserControl.Visibility != Visibility.Visible) { MenuBarUserControl.Visibility = Visibility.Collapsed; SearchBarUserControl.Visibility = Visibility.Visible; } SearchBarUserControl.SetApiStatus(); }); } } catch (Exception E) { LogException(E); } finally { } } private void F4SDIcon_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { CustomMessageBox.CustomMessageBox.Show("1. Have you tried turning it off and on again?\n2. Are you sure it is plugged in?", "How to solve (almost) any computer problem", enumHealthCardStateLevel.Info, this); _supportCaseController.SupportCaseDataProviderArtifact.HealthCardDataHelper.IsInEditMode = true; } #region CloseCaseWithTicketIcon_Click public void CloseCaseWithTicketClick() { try { var _res = cSupportCaseDataProvider.CloseCaseWithTicket(this); if (_res) Hide(); } catch (Exception E) { LogException(E); } } private void CloseCaseWithTicketIcon_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { if (e.ChangedButton == MouseButton.Left) CloseCaseWithTicketClick(); } private void CloseCaseWithTicketIcon_TouchDown(object sender, TouchEventArgs e) { CloseCaseWithTicketClick(); } #endregion #region Window Events private void DetailsPage_Initialized(object sender, EventArgs e) { UpdateFooterPositions(); QuickActionDecorator.Child = new DataCanvas(true) { Visibility = Visibility.Collapsed }; } private void Window_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) { try { if (!(e.NewValue is bool isVisible && isVisible)) return; Show(); Activate(); Focus(); if (IsWindowLoaded) WindowState = WindowState.Maximized; } catch (Exception E) { LogException(E); } } private void Window_SizeChanged(object sender, SizeChangedEventArgs e) { UpdateHistoryWidth(); } #endregion #region Keyboard and Mouse Control Events private void Window_PreviewMouseWheel(object sender, MouseWheelEventArgs e) { try { if (Keyboard.Modifiers != ModifierKeys.Control) return; int zoom = cFasdCockpitConfig.Instance.DetailsPageZoom; if (e.Delta > 0) zoom += 5; else if (e.Delta < 0) zoom -= 5; ZoomValueTextBlock.Text = zoom + "%"; ZoomValueBorder.BeginAnimation(OpacityProperty, new DoubleAnimation(1, 0, new Duration(TimeSpan.FromSeconds(2)))); if (zoom != cFasdCockpitConfig.Instance.DetailsPageZoom) cFasdCockpitConfig.Instance.SetDetailsPageZoom(zoom); HasZoomChanged = true; } catch (Exception E) { LogException(E); } } public async Task AdjustWindowSizeAsync() { bool sizeChanged; do { sizeChanged = false; SetMinimalWindowSize(); var _p0 = this.PointFromScreen(new Point(0, 0)); var _p1 = this.PointFromScreen(new Point(MinSizeWidth, MinSizeHeigth)); var _p2 = _p1 - _p0; if (this.ActualHeight + 1 < _p2.Y) { sizeChanged = true; Height = _p2.Y; } if (this.ActualWidth + 1 < _p2.X) { sizeChanged = true; Width = _p2.X; } if (sizeChanged) await Task.Delay(1); } while (sizeChanged); } private async void Window_PreviewKeyUp(object sender, KeyEventArgs e) { try { switch (e.Key) { case Key.LeftCtrl: case Key.RightCtrl: if (HasZoomChanged) { await AdjustWindowSizeAsync(); HasZoomChanged = false; cFasdCockpitConfig.Instance.SetDetailsPageZoom(cFasdCockpitConfig.Instance.DetailsPageZoom); } break; } } catch (Exception E) { LogException(E); } } private async void Window_PreviewKeyDown(object sender, KeyEventArgs e) { try { if (SearchBarUserControl.Visibility == Visibility.Visible) { switch (e.Key) { case Key.Up: if (SearchResultsUc.IndexOfSelectedResultItem > 0) SearchResultsUc.IndexOfSelectedResultItem--; break; case Key.Down: SearchResultsUc.IndexOfSelectedResultItem++; break; case Key.Enter: SearchResultsUc.SelectCurrentResultItem(); break; case Key.Escape: BlurBorder_Click(); break; } return; } if (FocusManager.GetFocusedElement(this) is TextBox) return; if (FocusManager.GetFocusedElement(this) is RichTextBox) return; List unpinnedDataHistories = DataHistoryCollectionUserControl.HistorySectionControls.Where(x => !x.IsVerticalExpandLocked).ToList(); int expandedIndex = unpinnedDataHistories.FindIndex(x => x.IsVerticalExpanded); switch (e.Key) { case Key.OemPlus: case Key.Add: DataHistoryCollectionUserControl.ToggleVerticalCollapseDetails(false); break; case Key.OemMinus: case Key.Subtract: DataHistoryCollectionUserControl.ToggleVerticalCollapseDetails(true); break; case Key.Up: if (expandedIndex - 1 >= 0) { unpinnedDataHistories.ForEach(historySection => historySection.IsVerticalExpanded = false); DataHistoryCollectionUserControl.VerticalUncollapseDataHistory(unpinnedDataHistories[expandedIndex - 1]); } break; case Key.Down: if (expandedIndex + 1 < unpinnedDataHistories.Count) { unpinnedDataHistories.ForEach(historySection => historySection.IsVerticalExpanded = false); DataHistoryCollectionUserControl.VerticalUncollapseDataHistory(unpinnedDataHistories[expandedIndex + 1]); } break; case Key.Left: ToggleHorizontalCollapse(true); break; case Key.Right: ToggleHorizontalCollapse(false); break; case Key.F3: if (Keyboard.Modifiers == ModifierKeys.Control) SearchButtonClickedAction(); break; case Key.Q: MoreButtonClickedAction(); break; case Key.NumPad0: case Key.D0: if (Keyboard.Modifiers != ModifierKeys.Control) break; const int defaultZoom = 100; ZoomValueTextBlock.Text = defaultZoom + "%"; ZoomValueBorder.BeginAnimation(OpacityProperty, new DoubleAnimation(1, 0, new Duration(TimeSpan.FromSeconds(2)))); cFasdCockpitConfig.Instance.SetDetailsPageZoom(defaultZoom); await AdjustWindowSizeAsync(); break; default: break; } } catch (Exception E) { LogException(E); } } #endregion #region DataProvider Events (UpdateData) private void DataProvider_CaseChanged(object sender, EventArgs e) { try { Dispatcher.Invoke(() => { try { DataHistoryCollectionUserControl.DetailsCollectionScrollViewer.ScrollToTop(); DataHistoryCollectionUserControl.ToggleVerticalCollapseDetails(true); RefreshControl.UpdateLastDataRequestTime(); QuickTipStatusMonitorUc.Visibility = Visibility.Collapsed; } catch (Exception E) { LogException(E); } }); } catch (Exception E) { LogException(E); } } internal override async void DataProvider_DataChanged(object sender, EventArgs e) { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { LogEntry($"DataChanged - DataProvider for Class: {_supportCaseController?.SupportCaseDataProviderArtifact.Identities[0].Class} - Id: {_supportCaseController?.SupportCaseDataProviderArtifact.Identities[0].Id}"); if (isDataChangedEventRunning) { shouldReRunDataChangedEvent = true; LogEntry("DataChanged - Cancled event, because it's allready running."); return; } isDataChangedEventRunning = true; if (!(e is BooleanEventArgs booleanArg) || booleanArg.BooleanArg == false) isDataProviderLoading = true; Dispatcher.Invoke(UpdateHistoryWidth); if (e is BooleanEventArgs booleanArgs && booleanArgs.BooleanArg is true) BlurBorder_Click(keepTicketCompletion: true); isDataChangedEventRunning = false; if (shouldReRunDataChangedEvent) { shouldReRunDataChangedEvent = false; LogEntry("DataChanged - Called to rerun, because tried to run it while it was allready in process."); DataProvider_DataChanged(sender, e); } } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } } internal override void DataProvider_DataFullyLoaded(object sender, EventArgs e) { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { isDataProviderLoading = false; Dispatcher.Invoke(() => { NavigationHeadingUc.ClearValue(IsHitTestVisibleProperty); NavigationHeadingUc.ClearValue(OpacityProperty); RefreshControl.IsDataIncomplete = false; CustomizableSectionUc.IsDataIncomplete = false; UpdateHistoryWidth(); }); } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } } internal override void DirectConnectionHelper_DirectConnectionChanged(object sender, EventArgs e) { try { Dispatcher.Invoke(() => { bool hasDirectConnection = _supportCaseController?.SupportCaseDataProviderArtifact?.DirectConnectionHelper?.IsDirectConnectionActive ?? false; NavigationHeadingUc.HasDirectConnection = hasDirectConnection; if (hasDirectConnection) RefreshButtonClickedEvent(this, e); }); } catch (Exception E) { LogException(E); } } private void DynamicElement_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) { if (sender is Decorator) { isQuickActionDecoratorVisible = QuickActionDecorator.IsVisible; } else if (sender is QuickActionSelector) isQuickActionSelectorVisible = QuickActionSelectorUc.IsVisible; var _h = Dispatcher.Invoke(async () => { await System.Threading.Tasks.Task.Delay(1); //required, if not the additinal Data Coulmn Width in DataCanvas are not dynamic UpdateHistoryWidth(); }); } #endregion #endregion #region DelegateActions private async Task EnteredSearchValueAsync(cFilteredResults filteredResults) { await Task.CompletedTask; //SearchResultBorder.Width = SearchBarUserControl.ActualWidth; //SearchResultsUc.ShowSearchResults(filteredResults, null); //if (filteredResults?.Results == null) // SearchResultBorder.Visibility = Visibility.Collapsed; //else // SearchResultBorder.Visibility = Visibility.Visible; } private void SearchButtonClickedAction() { SearchBarUserControl.Width = MenuBarUserControl.ActualWidth; SearchBarUserControl.Visibility = Visibility.Visible; MenuBarUserControl.Visibility = Visibility.Collapsed; SearchResultBorder.Visibility = Visibility.Collapsed; SearchBarUserControl.ActivateManualSearch(); } private void MoreButtonClickedAction() { try { if (!(DataContext is DetailsPageViewModel viewModel)) return; var tempMoreQuickActionList = viewModel.MenuDrawerData; if (cF4SDCockpitXmlConfig.Instance?.CopyTemplateConfig?.CopyTemplates != null) { var tempSubMenuList = new List(); foreach (var copyTemplate in cF4SDCockpitXmlConfig.Instance?.CopyTemplateConfig?.CopyTemplates.CopyTemplates) { tempSubMenuList.Add(new cMenuDataBase(copyTemplate.Value)); } tempMoreQuickActionList.Insert(0, new cMenuDataContainer() { MenuText = cMultiLanguageSupport.GetItem("QuickAction.CopyContent"), MenuIcon = new F4SD_AdaptableIcon.IconData(enumInternIcons.menuBar_copy), UiAction = new cSubMenuAction(true) { Name = cMultiLanguageSupport.GetItem("QuickAction.CopyContent"), SubMenuData = tempSubMenuList }, SubMenuData = tempSubMenuList }); } QuickActionSelectorUc.QuickActionList = tempMoreQuickActionList; QuickActionSelectorUc.QuickActionSelectorHeading = "Quick Actions"; QuickActionSelectorUc.TempQuickActionList = null; ToggleHorizontalCollapse(true); QuickActionSelectorUc.Visibility = Visibility.Visible; QuickActionSelectorUc.CloseButtonClickedAction = BlurBorder_Click; } catch (Exception E) { LogException(E); } } private void QuickActionSelectorLockStatusChangedAction(bool isLocked) { try { if (DataHistoryCollectionUserControl.IsVisible) { cFasdCockpitConfig.Instance.IsHistoryQuickActionSelectorVisible = isLocked; cFasdCockpitConfig.Instance.Save("IsHistoryQuickActionSelectorVisible"); } else if (CustomizableSectionUc.IsVisible) { cFasdCockpitConfig.Instance.IsCustomizableQuickActionSelectorVisible = isLocked; cFasdCockpitConfig.Instance.Save("IsCustomizableQuickActionSelectorVisible"); } } catch (Exception E) { LogException(E); } } private void NotepadLockStatusChangedAction(object sender, bool isLocked) { try { cFasdCockpitConfig.Instance.IsNotepadVisibleDocked = isLocked; cFasdCockpitConfig.Instance.Save("IsNotepadVisibleDocked"); } catch (Exception E) { LogException(E); } } public void NotepadChangeVisibilityAction(object sender, bool action) { try { if (notepad == null) { return; } if (isNotepadDecoratorVisible == true) { isNotepadDecoratorVisible = false; return; } if (NotepadVisibility == true) { if (NotepadParent == popoutWindow) { IsUndockedChangeAction(this, false); notepad.IsUndocked = !notepad.IsUndocked; } NotepadDecorator.Visibility = Visibility.Collapsed; notepad.Visibility = Visibility.Collapsed; NotepadVisibility = false; ChangeNotepadNotification(); } else { if (NotepadParent != NotepadDecorator) { return; } NotepadDecorator.Visibility = Visibility.Visible; notepad.Visibility = Visibility.Visible; NotepadVisibility = true; MenuBarUserControl.ChangeNotepadNotificationVisibility(false); } isNotepadDecoratorVisible = false; } catch (Exception E) { LogException(E); } } private void IsUndockedChangeAction(object sender, bool isUndocked) { try { if (notepad == null) { return; } if (isUndocked == true) { if (!(NotepadParent == NotepadDecorator)) { return; } popoutWindow = new Window { WindowStyle = WindowStyle.None, ResizeMode = ResizeMode.NoResize, AllowsTransparency = true, Background = Brushes.Transparent, WindowStartupLocation = WindowStartupLocation.CenterScreen, Height = this.ActualHeight / 1.5, Width = this.ActualWidth / 1.5, MinHeight = ActualHeight == 0 ? 700 : 0, MinWidth = ActualWidth == 0 ? 500 : 0, Owner = this, }; WindowChrome.SetWindowChrome(popoutWindow, new WindowChrome() { CaptionHeight = 30, ResizeBorderThickness = new Thickness(10), GlassFrameThickness = new Thickness(0), CornerRadius = new CornerRadius(0), UseAeroCaptionButtons = false }); NotepadDecorator.Child = null; NotepadDecorator.Visibility = Visibility.Collapsed; popoutWindow.Content = notepad; notepad.Height = double.NaN; notepad.Width = double.NaN; NotepadParent = popoutWindow; if (notepad.IsTicketDialog == false) { IsBlurred = true; } popoutWindow.ShowDialog(); } else { if (!(NotepadParent == popoutWindow)) { return; } popoutWindow.Content = null; popoutWindow.Close(); popoutWindow = null; NotepadDecorator.Visibility = Visibility.Visible; NotepadDecorator.Child = notepad; notepad.Height = double.NaN; notepad.Width = double.NaN; NotepadParent = NotepadDecorator; if (notepad.IsTicketDialog == false) { IsBlurred = false; } else { notepad.IsTicketDialog = false; } if (TicketDialogNotepadVisibility == false) { NotepadChangeVisibilityAction(this, true); } TicketDialogNotepadVisibility = true; } } catch (Exception E) { LogException(E); } } private void ChangeNotepadNotification() { FlowDocument document = _supportCaseController?.SupportCaseDataProviderArtifact.CaseNotes; bool isFlowDocumentEmpty = !document.Blocks.Any(block => { if (block is Paragraph paragraph) { return paragraph.Inlines.Any(inline => inline is Run run && !string.IsNullOrWhiteSpace(run.Text)); } return false; }); if (!isFlowDocumentEmpty) { MenuBarUserControl.ChangeNotepadNotificationVisibility(true); } } private void ResetNotepadNotification(object sender, bool isNotEmpty) { MenuBarUserControl.ChangeNotepadNotificationVisibility(false); } private void TicketChangeNotepadAction(object sender, bool isUndocked) { try { TicketDialogNotepadVisibility = NotepadVisibility; if (NotepadVisibility == false) { NotepadChangeVisibilityAction(sender, true); } notepad.IsUndocked = !notepad.IsUndocked; notepad.IsTicketDialog = true; IsUndockedChangeAction(sender, isUndocked); } catch (Exception E) { LogException(E); } } #endregion #endregion #region Basics public void SetGeometryValues(DetailsPageGeometry detailsGeometry) { if (DataContext is DetailsPageViewModel viewModel) viewModel.SetGeometryValues(detailsGeometry); } private void ResetPageToDefaultState() { try { BlurBorder_Click(); MenuBarUserControl.Visibility = Visibility.Visible; SearchBarUserControl.Visibility = Visibility.Collapsed; QuickActionSelectorUc.QuickActionList = null; QuickActionSelectorUc.Visibility = Visibility.Collapsed; QuickActionDecorator.Child.Visibility = Visibility.Collapsed; NotepadDecorator.Visibility = Visibility.Collapsed; NotepadDecorator.Child = null; notepad = null; isQuickActionDecoratorVisible = false; isQuickActionSelectorVisible = false; if (IsLoaded) ReinitializeNotepad(); DataHistoryCollectionUserControl.ToggleVerticalCollapseDetails(true); UpdateHistoryWidth(); } catch (Exception E) { LogException(E); } } #endregion #region DataHistoryCollection public void OpenDataHistory(int dataHistoryIndex) { DataHistoryCollectionUserControl.VerticalUncollapseDataHistory(dataHistoryIndex); } private void ToggleHorizontalCollapse(bool shouldCollapse, bool quickAction = false) { try { if (DataHistoryCollectionUserControl.Visibility != Visibility.Visible) return; isHorizontalCollapsed = shouldCollapse; DataHistoryCollectionUserControl.ToggleHorizontalCollapseHistory(!shouldCollapse); if (shouldCollapse) { QuickActionSelectorUc.Visibility = isQuickActionSelectorVisible ? Visibility.Visible : Visibility.Collapsed; QuickActionDecorator.Visibility = isQuickActionDecoratorVisible ? Visibility.Visible : Visibility.Collapsed; if (isNotepadDecoratorVisible == true) { NotepadDecorator.Visibility = Visibility.Visible; } if (quickAction == false) { isNotepadDecoratorVisible = false; } } else { var tempIsQuickActionSelectorVisible = QuickActionSelectorUc.IsVisible; var tempIsQuickActionDecoratorVisible = QuickActionDecorator.IsVisible; isNotepadDecoratorVisible = NotepadDecorator.IsVisible; QuickActionSelectorUc.Visibility = Visibility.Collapsed; QuickActionDecorator.Visibility = Visibility.Collapsed; NotepadDecorator.Visibility = Visibility.Collapsed; isQuickActionSelectorVisible = tempIsQuickActionSelectorVisible; isQuickActionDecoratorVisible = tempIsQuickActionDecoratorVisible; //isNotepadDecoratorVisible = tempIsNotepadDecoratorVisible; } UpdateHistoryWidth(); } catch (Exception E) { LogException(E); } } #endregion #region Layout and "Style" public void SetZoomValue(int zoomInPercent) { if (DataContext is DetailsPageViewModel viewModel) viewModel.ZoomInPercent = zoomInPercent; } private void UpdateHistoryWidth() { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { var firstHistoryData = DataHistoryCollectionUserControl.DataHistoryCollectionStackPanel.Children[0]; if (firstHistoryData == null || !(firstHistoryData is DetailsPageDataHistorySection historySection)) return; var firstHistorySectionChild = historySection.MainGrid.Children[0]; if (firstHistorySectionChild == null || !(firstHistorySectionChild is DetailsPageDataHistoryValueColumn valueColumn)) return; UpdateLayout(); const int maxValueColumnCountIfCollaped = 5; var availableWidth = MainGrid.ActualWidth; var quickActionDecoratorWidth = QuickActionDecorator.ActualWidth == 0 ? QuickActionDecorator.ActualWidth : QuickActionDecorator.ActualWidth + 19; // +19 for margin var quickActionSelectorWidth = QuickActionSelectorUc.ActualWidth == 0 ? QuickActionSelectorUc.ActualWidth : QuickActionSelectorUc.ActualWidth + 15; // +15 for margin var quickTipSelectorWidth = QuickTipDecorator.ActualWidth == 0 ? QuickTipDecorator.ActualWidth : QuickTipDecorator.ActualWidth + 15; // +15 for margin var notePadDecoratorWidth = NotepadDecorator.ActualWidth == 0 ? NotepadDecorator.ActualWidth : NotepadDecorator.ActualWidth + 19; if (isHorizontalCollapsed) availableWidth = availableWidth - quickTipSelectorWidth - quickActionDecoratorWidth - quickActionSelectorWidth - notePadDecoratorWidth; var minimalRequiredSpaceWithoutValueColumn = historySection.TitleColumnUc.ActualWidth + historySection.TitleRowEndBorder.ActualWidth + 8; // +8 for margin and padding var maxPossibleWidthForValueColumns = availableWidth - minimalRequiredSpaceWithoutValueColumn; var valueColumnWidth = valueColumn.ActualWidth; valueColumnWidth = valueColumnWidth != 0 ? valueColumnWidth : 1; int maxValueColumnCount = Convert.ToInt32(Math.Floor(maxPossibleWidthForValueColumns / valueColumnWidth)); int valueColumnCountFactor = maxValueColumnCount; if (isHorizontalCollapsed) valueColumnCountFactor = Math.Min(maxValueColumnCount, maxValueColumnCountIfCollaped); valueColumnCountFactor = Math.Max(1, valueColumnCountFactor); var plannedWidth = minimalRequiredSpaceWithoutValueColumn + (valueColumnCountFactor * valueColumnWidth); DataHistoryCollectionUserControl.Width = plannedWidth; } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } } public void SetEditMode(bool isActive) { try { WidgetCollection.SetEditMode(isActive); CustomizableSectionUc.SetEditMode(isActive); NavigationHeadingUc.SetEditMode(isActive); } catch (Exception E) { LogException(E); } } #endregion void MidnightTimer_Tick(object sender, EventArgs e) { var correct = new TimeSpan(0, 0, 0); try { _midnightTimer.Stop(); var from = _supportCaseController?.SupportCaseDataProviderArtifact?.HealthCardDataHelper?.LoadingHelper?.LastDataRequest; if (from == null) { return; } var fromDate = from.GetValueOrDefault().ToLocalTime(); fromDate -= correct; fromDate = fromDate.Date; var nowDate = DateTime.Now; nowDate -= correct; nowDate = nowDate.Date; if (nowDate > fromDate) { RefreshButtonClickedEvent(sender, e); } } catch (Exception) { throw; } finally { _midnightTimer.Start(); } } private void CaseTimer_OnPauseStarted(object sender, EventArgs e) { PauseOverlay.Visibility = Visibility.Visible; MainContent.Effect = new BlurEffect() { Radius = 8, KernelType = KernelType.Gaussian }; } public void PauseCaseOverlay_OnPauseEnd(object sender, EventArgs e) { EndPause(); } public void EndPause() { PauseOverlay.Visibility = Visibility.Collapsed; MainContent.Effect = null; CaseTimer.EndPause(); } private void Header_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { BlurBorder_Click(); } private void Footer_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { BlurBorder_Click(); } private void IconTimerPanel_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { BlurBorder_Click(); } private void DetailsPage_SourceInitialized(object sender, EventArgs e) { IntPtr handle = new WindowInteropHelper(this).Handle; HwndSource.FromHwnd(handle).AddHook(new HwndSourceHook(WindowProc)); } public IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { const int WM_GETMINMAXINFO = 0x0024; switch (msg) { case WM_GETMINMAXINFO: if (IsLoaded) SetMinimalWindowSize(); cUtility.WmGetMinMaxInfo(hwnd, lParam, MinSizeWidth, MinSizeHeigth); handled = true; break; } return IntPtr.Zero; } private void QuickTipStatusMonitorUc_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) { QuickActionDecorator.Visibility = Visibility.Collapsed; } } }