This commit is contained in:
Meik
2025-11-11 11:03:42 +01:00
commit dc3e8a2e4c
582 changed files with 191465 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.BlurInvokerContainer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800"
IsVisibleChanged="BlurInvoker_IsActiveChanged">
<Decorator x:Name="MainDecorator">
</Decorator>
</UserControl>

View File

@@ -0,0 +1,65 @@
using C4IT.Logging;
using FasdDesktopUi.Basics.Models;
using System;
using System.Collections.Generic;
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.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class BlurInvokerContainer : UserControl, IBlurInvoker
{
#region Properties
public UIElement Child
{
get { return (UIElement)GetValue(ChildProperty); }
set { SetValue(ChildProperty, value); }
}
public static readonly DependencyProperty ChildProperty =
DependencyProperty.Register("Child", typeof(UIElement), typeof(BlurInvokerContainer), new PropertyMetadata(null, new PropertyChangedCallback(ChildChanged)));
private static void ChildChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
try
{
if (!(d is BlurInvokerContainer _me))
return;
_me.MainDecorator.Child = _me.Child;
}
catch (Exception E)
{
LogException(E);
}
}
#endregion
public BlurInvokerContainer()
{
InitializeComponent();
}
public void BlurInvoker_IsActiveChanged(object sender, DependencyPropertyChangedEventArgs e)
{
BlurInvoker.InvokeVisibilityChanged(this, new EventArgs());
}
public bool BlurInvoker_IsActive => IsVisible;
}
}

View File

@@ -0,0 +1,212 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.ComboBoxPageable"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
mc:Ignorable="d"
x:Name="ComboBoxPagableUc"
d:DesignHeight="450"
d:DesignWidth="800">
<UserControl.Resources>
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter" />
<ControlTemplate x:Key="ComboBoxPagableTemplate"
TargetType="{x:Type ComboBox}">
<Grid x:Name="templateRoot"
SnapsToDevicePixels="true">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}"
Width="0" />
</Grid.ColumnDefinitions>
<Popup x:Name="PART_Popup"
AllowsTransparency="true"
Grid.ColumnSpan="2"
IsOpen="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
Margin="1"
Placement="Bottom"
PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}">
<StackPanel>
<Grid>
<TextBox x:Name="SearchTextBox"
Style="{DynamicResource Customizable.Editable.TextBox.EditOnly}"
Background="{TemplateBinding Background}"
FontSize="14"
VerticalAlignment="Center"
Padding="27 5 5 5"
Margin="0"
TextChanged="SearchTextBox_TextChanged" />
<ico:AdaptableIcon SelectedInternIcon="menuBar_search"
HorizontalAlignment="Left"
BorderPadding="5 5 5 7"
Margin="0"
Style="{DynamicResource Menu.MenuBar.PinnedIcon.Base}" />
<TextBlock IsHitTestVisible="False"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="30 0 0 0"
Foreground="{DynamicResource FontColor.DetailsPage.DataHistory.Date}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Text, ElementName=SearchTextBox}"
Value="">
<Setter Property="Text"
Value="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Searchbar.Placeholder}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
<Border CornerRadius="7.5"
Padding="10 0"
Margin="5"
HorizontalAlignment="Center"
Background="{TemplateBinding Background}">
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center"
Background="#01010101">
<ico:AdaptableIcon x:Name="PageBackButton"
SelectedInternIcon="misc_chevron_left"
Style="{DynamicResource SettingsPage.Close.Icon}"
MouseLeftButtonUp="PageBackButton_MouseLeftButtonUp"
TouchDown="PageBackButton_TouchDown"
BorderPadding="7.5"
IconHeight="30"
IconWidth="30" />
<TextBlock x:Name="PageTrackerTextBlock"
VerticalAlignment="Center" />
<ico:AdaptableIcon x:Name="PageForButton"
SelectedInternIcon="misc_chevron_right"
Style="{DynamicResource SettingsPage.Close.Icon}"
MouseLeftButtonUp="PageForButton_MouseLeftButtonUp"
TouchDown="PageForButton_TouchDown"
BorderPadding="7.5"
IconHeight="30"
IconWidth="30" />
<CheckBox x:Name="ResetFilterCheckbox"
Style="{DynamicResource ToggleSwitch}"
Margin="20 0 0 0"
HorizontalAlignment="Left"
IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:ComboBoxPageable}}, Path=ResetFilter, Mode=TwoWay}"
VerticalAlignment="Center"
Cursor="Hand"
>
</CheckBox>
<TextBlock VerticalAlignment="Center" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:ComboBoxPageable}}, Path=ResetFilterLabel, Mode=TwoWay}"/>
</StackPanel>
</Border>
<Border MinWidth="{Binding ActualWidth, ElementName=templateRoot}"
MaxHeight="{TemplateBinding MaxDropDownHeight}">
<Border x:Name="dropDownBorder"
CornerRadius="7.5"
Background="{DynamicResource BackgroundColor.Menu.SubCategory}">
<ScrollViewer x:Name="DropDownScrollViewer">
<Grid x:Name="grid"
RenderOptions.ClearTypeHint="Enabled">
<Canvas x:Name="canvas"
HorizontalAlignment="Left"
Height="0"
VerticalAlignment="Top"
Width="0">
<Border x:Name="opaqueRect"
CornerRadius="7.5"
Background="{Binding Background, ElementName=dropDownBorder}"
Height="{Binding ActualHeight, ElementName=dropDownBorder}"
Width="{Binding ActualWidth, ElementName=dropDownBorder}" />
</Canvas>
<ItemsPresenter x:Name="ItemsPresenter"
KeyboardNavigation.DirectionalNavigation="Contained"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Grid>
</ScrollViewer>
</Border>
</Border>
</StackPanel>
</Popup>
<ToggleButton x:Name="toggleButton"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Grid.ColumnSpan="2"
IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
Style="{StaticResource ComboBoxToggleButton}" />
<ContentPresenter x:Name="contentPresenter"
ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
IsHitTestVisible="false"
Margin="{TemplateBinding Padding}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled"
Value="false">
<Setter Property="Opacity"
Value="0.7" />
</Trigger>
<Trigger Property="HasDropShadow"
SourceName="PART_Popup"
Value="true">
</Trigger>
<Trigger Property="HasItems"
Value="false">
<Setter Property="Height"
TargetName="dropDownBorder"
Value="95" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsGrouping"
Value="true" />
<Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping"
Value="false" />
</MultiTrigger.Conditions>
<Setter Property="ScrollViewer.CanContentScroll"
Value="false" />
</MultiTrigger>
<Trigger Property="ScrollViewer.CanContentScroll"
SourceName="DropDownScrollViewer"
Value="false">
<Setter Property="Canvas.Top"
TargetName="opaqueRect"
Value="{Binding VerticalOffset, ElementName=DropDownScrollViewer}" />
<Setter Property="Canvas.Left"
TargetName="opaqueRect"
Value="{Binding HorizontalOffset, ElementName=DropDownScrollViewer}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</UserControl.Resources>
<Grid>
<ComboBox x:Name="ComboBoxControl"
DropDownOpened="ComboBoxControl_DropDownOpened"
DropDownClosed="ComboBoxControl_DropDownClosed"
Background="{Binding ElementName=ComboBoxPagableUc, Path=ComboBoxBackground}"
BorderBrush="{Binding ElementName=ComboBoxPagableUc, Path=BorderBrush}"
ItemsSource="{Binding ElementName=ComboBoxPagableUc, Path=ItemData}"
SelectedItem="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:ComboBoxPageable}}, Path=SelectedItem, Mode=TwoWay}"
DisplayMemberPath="Key"
Template="{StaticResource ComboBoxPagableTemplate}" />
</Grid>
</UserControl>

View File

@@ -0,0 +1,396 @@
using C4IT.FASD.Base;
using C4IT.MultiLanguage;
using FasdDesktopUi.Basics.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Navigation;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class ComboBoxPageable : UserControl, IFocusInvoker
{
#region Fields & Properties
private const int itemsPerPage = 10;
private const double searchDelayInMilliseconds = 350;
private int pageIndex = 0;
private int pageCount = 1;
private readonly Timer timer = new Timer(searchDelayInMilliseconds);
private readonly cF4sdHealthSelectionDataRequest searchData = new cF4sdHealthSelectionDataRequest() { Search = string.Empty, Page = 0, PageSize = itemsPerPage };
public int? ParentIndex { get; set; }
public UIElement ParentElement { get; set; }
public string ResetFilterLabel
{
get { return (string)GetValue(ResetFilterLabelProperty); }
set { SetValue(ResetFilterLabelProperty, value); }
}
public static readonly DependencyProperty ResetFilterLabelProperty =
DependencyProperty.Register("ResetFilterLabel", typeof(string), typeof(ComboBoxPageable), new PropertyMetadata(cMultiLanguageSupport.GetItem("Dialog.CloseCase.ResetFilter")));
public bool ResetFilter
{
get { return (bool)GetValue(ResetFilterProperty); }
set { SetValue(ResetFilterProperty, value); }
}
public static readonly DependencyProperty ResetFilterProperty =
DependencyProperty.Register("ResetFilter", typeof(bool), typeof(ComboBoxPageable), new PropertyMetadata(false, new PropertyChangedCallback(ResetFilterChanged)));
private static void ResetFilterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
try
{
if (!(d is ComboBoxPageable me))
return;
me.searchData.ResetFilter = me.ResetFilter;
me.InvokeSearchValueChanged();
}
catch (Exception E)
{
LogException(E);
}
}
#region TotalItemCount
public int TotalItemCount
{
get { return (int)GetValue(TotalItemCountProperty); }
set { SetValue(TotalItemCountProperty, value); }
}
public static readonly DependencyProperty TotalItemCountProperty =
DependencyProperty.Register("TotalItemCount", typeof(int), typeof(ComboBoxPageable), new PropertyMetadata(0, new PropertyChangedCallback(TotalItemCountChanged)));
private static void TotalItemCountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
try
{
if (!(d is ComboBoxPageable me))
return;
me.pageCount = me.TotalItemCount % itemsPerPage == 0 ? me.TotalItemCount / itemsPerPage : (me.TotalItemCount / itemsPerPage) + 1;
me.UpdatePageTracker();
}
catch (Exception E)
{
LogException(E);
}
}
#endregion
public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register(
"SelectedItem",
typeof(object),
typeof(ComboBoxPageable),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public object SelectedItem
{
get { return GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
#region SearchDataChanged
public EventHandler<cF4sdHealthSelectionDataRequest> SearchDataChanged
{
get { return (EventHandler<cF4sdHealthSelectionDataRequest>)GetValue(SearchDataChangedProperty); }
set { SetValue(SearchDataChangedProperty, value); }
}
public static readonly DependencyProperty SearchDataChangedProperty =
DependencyProperty.Register("SearchDataChanged", typeof(EventHandler<cF4sdHealthSelectionDataRequest>), typeof(ComboBoxPageable), new PropertyMetadata(null));
#endregion
#region ItemData
public ObservableCollection<KeyValuePair<string, object>> ItemData
{
get { return (ObservableCollection<KeyValuePair<string, object>>)GetValue(ItemDataProperty); }
set
{
SetValue(ItemDataProperty, value);
}
}
public static readonly DependencyProperty ItemDataProperty =
DependencyProperty.Register("ItemData", typeof(ObservableCollection<KeyValuePair<string, object>>), typeof(ComboBoxPageable), new PropertyMetadata(null));
#endregion
#region Styles
public Brush ComboBoxBackground
{
get { return (Brush)GetValue(ComboBoxBackgroundProperty); }
set { SetValue(ComboBoxBackgroundProperty, value); }
}
public static readonly DependencyProperty ComboBoxBackgroundProperty =
DependencyProperty.Register("ComboBoxBackground", typeof(Brush), typeof(ComboBoxPageable), new PropertyMetadata(Brushes.Transparent));
#endregion
#endregion
public ComboBoxPageable()
{
InitializeComponent();
timer.Elapsed += TimerElapsed;
}
private void TimerElapsed(object sender, ElapsedEventArgs e)
{
try
{
timer.Stop();
Dispatcher.Invoke(InvokeSearchValueChanged);
}
catch (Exception E)
{
LogException(E);
}
}
private void InvokeSearchValueChanged()
{
try
{
searchData.Page = pageIndex;
if (SearchDataChanged != null)
SearchDataChanged.Invoke(this, searchData);
}
catch (Exception E)
{
LogException(E);
}
}
public KeyValuePair<string, object>? GetSelectedValue()
{
try
{
if (ComboBoxControl.SelectedItem is KeyValuePair<string, object> selectedItem)
return selectedItem;
}
catch (Exception E)
{
LogException(E);
}
return null;
}
#region Paging Events
#region PageBack
private void PageBackButton_Click(RoutedEventArgs e)
{
if (pageIndex <= 0)
{
e.Handled = true;
return;
}
pageIndex--;
InvokeSearchValueChanged();
UpdatePageTracker();
e.Handled = true;
}
private void PageBackButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
PageBackButton_Click(e);
}
private void PageBackButton_TouchDown(object sender, TouchEventArgs e)
{
PageBackButton_Click(e);
}
#endregion
#region PageFor
private void PageForButton_Click(RoutedEventArgs e)
{
if (pageIndex + 1 >= pageCount)
return;
pageIndex++;
InvokeSearchValueChanged();
UpdatePageTracker();
e.Handled = true;
}
private void PageForButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
PageForButton_Click(e);
}
private void PageForButton_TouchDown(object sender, TouchEventArgs e)
{
PageForButton_Click(e);
}
#endregion
#endregion
private void UpdatePageTracker()
{
try
{
var pageTrackerElement = ComboBoxControl.Template.FindName("PageTrackerTextBlock", ComboBoxControl);
if (!(pageTrackerElement is TextBlock pageTrackerTextBlock))
return;
pageTrackerTextBlock.Text = $"{pageIndex + 1} / {pageCount}";
}
catch (Exception E)
{
LogException(E);
}
}
private void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
try
{
if (!(sender is TextBox searchTextBox))
return;
pageIndex = 0;
searchData.Search = searchTextBox.Text;
UpdatePageTracker();
timer.Stop();
timer.Start();
}
catch (Exception E)
{
LogException(E);
}
}
private void ComboBoxControl_DropDownClosed(object sender, EventArgs e)
{
timer.Stop();
cFocusInvoker.InvokeLostFocus(this, e);
}
private void ComboBoxControl_DropDownOpened(object sender, EventArgs e)
{
try
{
// Elterninfo nur setzen, wenn (noch) nicht sinnvoll vorhanden
bool invalidIndex = false;
if (ParentElement is Panel p && (ParentIndex == null || ParentIndex < 0 || ParentIndex > p.Children.Count))
invalidIndex = true;
if (ParentElement == null || invalidIndex)
{
ParentElement = this.Parent as UIElement;
if (this.Parent is Panel panel)
ParentIndex = panel.Children.IndexOf(this);
else
ParentIndex = null;
}
cFocusInvoker.InvokeGotFocus(this, e);
InvokeSearchValueChanged();
#region Focus auf Textfeld setzen beim Öffnen der Combobox
if (!(sender is ComboBox comboBox)) return;
// Zugriff auf das Popup-Element
Popup partPopup = comboBox.Template.FindName("PART_Popup", comboBox) as Popup;
if (partPopup == null) return;
// Verzögerter Fokus
var _h = Dispatcher.BeginInvoke((Action)(() =>
{
if (partPopup.IsOpen)
{
// Suchen des SearchTextBox-Element innerhalb des Popups
TextBox searchTextBox = FindVisualChild<TextBox>(partPopup.Child, "SearchTextBox");
if (searchTextBox != null)
{
// Setzen des Fokus auf TextBox
searchTextBox.Focus();
}
}
}), System.Windows.Threading.DispatcherPriority.Loaded);
#endregion
}
catch (Exception E)
{
LogException(E);
}
}
private static T FindVisualChild<T>(DependencyObject parent, string childName) where T : DependencyObject
{
if (parent == null) return null;
T foundChild = null;
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
var childType = child as T;
if (childType == null)
{
foundChild = FindVisualChild<T>(child, childName);
if (foundChild != null) break;
}
else if (!string.IsNullOrEmpty(childName))
{
var frameworkElement = child as FrameworkElement;
if (frameworkElement != null && frameworkElement.Name == childName)
{
return (T)child;
}
}
else
{
return (T)child;
}
}
return foundChild;
}
}
}

View File

@@ -0,0 +1,50 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.CustomDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800"
x:Name="YesNoControl">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisibility" />
<vc:BoolOrToVisibilityConverter x:Key="BoolOrToVisibilityConverter" />
</UserControl.Resources>
<Border Padding="10"
CornerRadius="10"
Background="{DynamicResource BackgroundColor.DetailsPage.Widget.Value}">
<DockPanel>
<ico:AdaptableIcon SelectedInternIcon="window_close"
DockPanel.Dock="Top"
HorizontalAlignment="Right"
Style="{DynamicResource SettingsPage.Close.Icon}" />
<local:YesNoButton HasYesNoButtons="{Binding ElementName=YesNoControl, Path=HasYesNoButtons}"
HasYesNoText="{Binding ElementName=YesNoControl, Path=HasYesNoText}"
DockPanel.Dock="Bottom"
HorizontalAlignment="Center"
ButtonHasBeenClicked="YesNoButton_ButtonHasBeenClicked">
<local:YesNoButton.Visibility>
<MultiBinding Converter="{StaticResource BoolOrToVisibilityConverter}">
<Binding Path="HasYesNoButtons" ElementName="YesNoControl"/>
<Binding Path="HasYesNoText" ElementName="YesNoControl"/>
</MultiBinding>
</local:YesNoButton.Visibility>
</local:YesNoButton>
<StackPanel x:Name="MainStack" />
</DockPanel>
</Border>
</UserControl>

View File

@@ -0,0 +1,110 @@
using FasdDesktopUi.Basics.CustomEvents;
using FasdDesktopUi.Basics.Helper;
using FasdDesktopUi.Basics.Models;
using System;
using System.Windows;
using System.Windows.Controls;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class CustomDialog : UserControl, IFocusInvoker
{
#region Proeprties and Fields
public int? ParentIndex { get; set; }
public UIElement ParentElement { get; set; }
#region HasYesNoButtons
public bool HasYesNoButtons
{
get { return (bool)GetValue(HasYesNoButtonsProperty); }
set { SetValue(HasYesNoButtonsProperty, value); }
}
public static readonly DependencyProperty HasYesNoButtonsProperty =
DependencyProperty.Register("HasYesNoButtons", typeof(bool), typeof(CustomDialog), new PropertyMetadata(true));
#endregion
#region HasYesNoText
public bool HasYesNoText
{
get { return (bool)GetValue(HasYesNoTextProperty); }
set { SetValue(HasYesNoTextProperty, value); }
}
public static readonly DependencyProperty HasYesNoTextProperty =
DependencyProperty.Register("HasYesNoText", typeof(bool), typeof(CustomDialog), new PropertyMetadata(true));
#endregion
#region ContainerData
public cContainerData ContainerData
{
get { return (cContainerData)GetValue(ContainerDataProperty); }
set { SetValue(ContainerDataProperty, value); }
}
public static readonly DependencyProperty ContainerDataProperty =
DependencyProperty.Register("ContainerData", typeof(cContainerData), typeof(CustomDialog), new PropertyMetadata(new cContainerData(), new PropertyChangedCallback(ContainerDataHasChanged)));
private static void ContainerDataHasChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
try
{
if (!(d is CustomDialog _me))
return;
_me.UpdateDialogContent();
}
catch (Exception E)
{
LogException(E);
}
}
#endregion
#endregion
public CustomDialog()
{
InitializeComponent();
}
private void UpdateDialogContent()
{
try
{
if (ContainerData is null)
return;
MainStack.Children.Clear();
foreach (var dialogComponentData in ContainerData)
{
if (cUiElementHelper.DrawCustomizableContainerComponent(dialogComponentData, this, out var createdControl))
{
createdControl.Margin = new Thickness(0, 5, 0, 5);
MainStack.Children.Add(createdControl);
}
}
}
catch (Exception E)
{
LogException(E);
}
}
private void YesNoButton_ButtonHasBeenClicked(object sender, BooleanEventArgs e)
{
}
}
}

View File

@@ -0,0 +1,20 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.CustomMenu"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
Name="CustomMenuUc"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid x:Name="MainGrid">
<ScrollViewer x:Name="MainScrollViewer"
VerticalScrollBarVisibility="Auto">
<StackPanel x:Name="MainStackPanel" />
</ScrollViewer>
</Grid>
</UserControl>

View File

@@ -0,0 +1,230 @@
using FasdDesktopUi.Basics.CustomEvents;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.UiActions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class CustomMenu : UserControl
{
#region Properties
#region MenuDataList DependencyPoperty
private static void MenuDataListChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is CustomMenu _me))
return;
_me.ClearControl();
_me.AddCustomMenuItems();
_me.UpdateCornerRadius();
if (_me.IsKeyboardNavigatable)
_me.IndexOfSelectedMenuItem = 0;
}
public static readonly DependencyProperty MenuDataListProperty =
DependencyProperty.Register("MenuDataList", typeof(List<cMenuDataBase>), typeof(CustomMenu), new PropertyMetadata(new List<cMenuDataBase>(), new PropertyChangedCallback(MenuDataListChangedCallback)));
public List<cMenuDataBase> MenuDataList
{
get { return (List<cMenuDataBase>)GetValue(MenuDataListProperty); }
set { SetValue(MenuDataListProperty, value); }
}
#endregion
#region IndexOfSelectedMenuItem DependencyProperty
private static void IndexOfSelectedMenuItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is CustomMenu _me && e.NewValue is int index))
return;
if (!_me.IsKeyboardNavigatable)
return;
foreach (CustomMenuItem menuItem in _me.MainStackPanel.Children)
{
menuItem.MenuItemBorder.SetResourceReference(StyleProperty, "Menu.MainCategory");
if (index < 0 || index > _me.MainStackPanel.Children.Count)
continue;
if (_me.MainStackPanel.Children.IndexOf(menuItem) == index)
menuItem.MenuItemBorder.SetResourceReference(StyleProperty, "Menu.MainCategory.Hover");
}
}
public static readonly DependencyProperty IndexOfSelectedMenuItemProperty =
DependencyProperty.Register("IndexOfSelectedMenuItem", typeof(int), typeof(CustomMenu), new PropertyMetadata(-1, new PropertyChangedCallback(IndexOfSelectedMenuItemChanged)));
public int IndexOfSelectedMenuItem
{
get { return (int)GetValue(IndexOfSelectedMenuItemProperty); }
set { SetValue(IndexOfSelectedMenuItemProperty, value); }
}
#endregion
#region IsKeyboardNavigatable
public static readonly DependencyProperty IsKeyboardNavigatableProperty =
DependencyProperty.Register("IsKeyboardNavigatable", typeof(bool), typeof(CustomMenuItem), new PropertyMetadata(false));
public bool IsKeyboardNavigatable
{
get { return (bool)GetValue(IsKeyboardNavigatableProperty); }
set { SetValue(IsKeyboardNavigatableProperty, value); }
}
#endregion
#endregion
public CustomMenu()
{
InitializeComponent();
}
public CustomMenu(bool drawWithBorder = false)
{
InitializeComponent();
if (drawWithBorder)
DrawControlWithBorder();
}
private void DrawControlWithBorder()
{
var tempBorder = new Border() { Padding = new Thickness(10), CornerRadius = new CornerRadius(10) };
tempBorder.SetResourceReference(BackgroundProperty, "BackgroundColor.Menu.Categories");
var tempControl = MainScrollViewer;
MainGrid.Children.Remove(tempControl);
MainGrid.Children.Add(tempBorder);
tempBorder.Child = tempControl;
}
private void ClearControl()
{
MainStackPanel.Children.Clear();
IndexOfSelectedMenuItem = -1;
}
private void AddCustomMenuItems()
{
if (MenuDataList == null)
return;
foreach (var menuItemData in MenuDataList)
{
var menuItem = new CustomMenuItem(false) { MenuData = menuItemData };
menuItem.MouseEnter += MenuItem_MouseEnter;
MainStackPanel.Children.Add(menuItem);
}
}
private void UpdateCornerRadius()
{
const double cornerRadius = 10;
if (MainStackPanel.Children.Count <= 0)
return;
if (MainStackPanel.Children[0] is CustomMenuItem menuItemFirst)
{
var tempCornerRadius = menuItemFirst.MenuItemBorder.CornerRadius;
tempCornerRadius.TopLeft = cornerRadius;
tempCornerRadius.TopRight = cornerRadius;
menuItemFirst.MenuItemBorder.CornerRadius = tempCornerRadius;
}
if (MainStackPanel.Children[MainStackPanel.Children.Count - 1] is CustomMenuItem menuItemLast)
{
var tempCornerRadiusLast = menuItemLast.MenuItemBorder.CornerRadius;
tempCornerRadiusLast.BottomLeft = cornerRadius;
tempCornerRadiusLast.BottomRight = cornerRadius;
menuItemLast.MenuItemBorder.CornerRadius = tempCornerRadiusLast;
}
}
private void MenuItem_MouseEnter(object sender, MouseEventArgs e)
{
if (!(sender is CustomMenuItem menuItem))
return;
CustomEventManager.RaiseIndexChangedEvent(this, -1, MainStackPanel.Children.IndexOf(menuItem));
}
internal void ShowDetailHeading(bool showDetailHeadings)
{
try
{
foreach (var resultItem in MainStackPanel.Children.OfType<CustomMenuItem>())
{
resultItem.ShowDetailHeadings(showDetailHeadings);
}
}
catch (Exception ex)
{
LogException(ex);
}
}
internal void HightlightItemAt(int index)
{
try
{
foreach (CustomMenuItem resultItem in MainStackPanel.Children)
{
if (MainStackPanel.Children.IndexOf(resultItem) == index)
{
resultItem.MenuItemBorder.SetResourceReference(StyleProperty, "Menu.MainCategory.Hover");
CustomEventManager.RaiseMenuDataChangedEvent(this, resultItem.MenuData);
}
else
resultItem.MenuItemBorder.SetResourceReference(StyleProperty, "Menu.MainCategory");
}
}
catch (Exception ex)
{
LogException(ex);
}
}
internal void SelectItemAt(int index)
{
try
{
if (MenuDataList is null)
return;
if (index < 0)
return;
if (MenuDataList.Count == 0 || MenuDataList.Count <= index)
return;
cUiActionBase uiAction = MenuDataList[index].UiAction;
if (uiAction is null || uiAction.DisplayType == Enums.enumActionDisplayType.disabled)
return;
cUiActionBase.RaiseEvent(uiAction, this, this);
}
catch (Exception E)
{
LogException(E);
}
}
}
}

View File

@@ -0,0 +1,144 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.CustomMenuItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
Name="CustomMenuItemUc"
mc:Ignorable="d"
d:DesignHeight="45"
d:DesignWidth="350" Initialized="CustomMenuItemUc_Initialized">
<UserControl.Resources>
<vc:NullValueToVisibilityConverter x:Key="NullToVisibility" />
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter" />
</UserControl.Resources>
<Border x:Name="MenuItemBorder"
Style="{DynamicResource Menu.MainCategory}"
MouseLeftButtonUp="MenuItemBorder_Click"
TouchDown="MenuItemBorder_Click"
MouseEnter="MenuItemBorder_MouseEnter"
MouseLeave="MenuItemBorder_MouseLeave">
<Grid x:Name="MenuItemContent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ico:AdaptableIcon x:Name="MenuItemIcon"
Grid.Column="0" />
<ico:AdaptableIcon x:Name="MenuItemOverlayIcon"
Grid.Column="0"
BorderPadding="10 10 0 0"
Margin="0 0 -5 -5"/>
<StackPanel Grid.Column="1"
Margin="15 0 15 0"
VerticalAlignment="Center"
IsHitTestVisible="False">
<Border x:Name="CustomTextBlockBorder"
ClipToBounds="True">
<Grid x:Name="CustomTextGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock x:Name="CustomTextBlock"
Grid.Column="0"
TextTrimming="CharacterEllipsis" />
<TextBlock x:Name="CustomTrailingTextBlock"
Grid.Column="1"
Margin="10 0 0 0"
TextTrimming="CharacterEllipsis"
HorizontalAlignment="Right"
TextAlignment="Right"
Visibility="Collapsed" />
</Grid>
</Border>
<Border x:Name="CustomTextBlockBorderBottom"
ClipToBounds="True"
Visibility="Collapsed">
<TextBlock x:Name="CustomTextBlockBottom"
TextTrimming="CharacterEllipsis"
FontWeight="UltraLight" />
</Border>
</StackPanel>
<Border x:Name="SubMenuCounterBorder"
Grid.Column="2"
Height="15"
Width="15"
Margin="-15 0 0 0"
Background="{DynamicResource Color.FunctionMarker}"
CornerRadius="15"
Visibility="Collapsed">
<TextBlock x:Name="SubMenuCounterTextBlock"
HorizontalAlignment="Center" VerticalAlignment="Center"
Margin="0"
FontSize="9"
Padding="0,0,0,1"
Foreground="White" />
</Border>
<ico:AdaptableIcon x:Name="LoadingIcon"
Grid.Column="2"
Style="{x:Null}"
Visibility="Collapsed"
SelectedInternGif="loadingSpinner" />
<Grid x:Name="SearchRelationGrid"
Visibility="Collapsed"
Grid.Column="2"
VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition SharedSizeGroup="SearchResultDetails" />
</Grid.ColumnDefinitions>
<TextBlock x:Name="LastSeenTextBox"
Grid.Row="0"
Grid.Column="0"
FontSize="10"
Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Searchbar.LastSeen}" />
<TextBlock x:Name="LessThanTextBlock"
Margin="5 0 5 0"
Grid.Row="0"
Grid.Column="1"
FontSize="10"
HorizontalAlignment="Right" />
<TextBlock x:Name="ActivityTextBlock"
Grid.Column="0"
Grid.Row="1"
FontSize="10"
Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Searchbar.Activity}" />
<Border x:Name="ActivityIndicator"
Grid.Row="1"
Grid.Column="1"
Margin="5 0 5 0"
CornerRadius="1.5"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Height="5"
Width="40"
Background="{DynamicResource Color.FunctionMarker}" />
</Grid>
</Grid>
</Border>
</UserControl>

View File

@@ -0,0 +1,261 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using FasdDesktopUi.Basics.Converter;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.UiActions;
using C4IT.FASD.Base;
using static C4IT.Logging.cLogManager;
using MaterialIcons;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class CustomMenuItem : UserControl
{
#region Properties
#region MenuData
private cMenuDataBase _menuData = new cMenuDataBase();
private readonly bool _isLean;
public cMenuDataBase MenuData
{
get { return _menuData; }
set
{
if (_menuData != value)
{
_menuData = value;
MenuDataChanged();
}
}
}
private void MenuDataChanged()
{
if (MenuData.MenuIcon.Intern != null)
MenuItemIcon.SelectedInternIcon = MenuData.MenuIcon.Intern;
else if (MenuData.MenuIcon.Material != null)
MenuItemIcon.SelectedMaterialIcon = MenuData.MenuIcon.Material;
MenuItemIcon.IconHeight = MenuData.MenuIconSize * MenuItemIcon.IconHeight;
MenuItemIcon.IconWidth = MenuData.MenuIconSize * MenuItemIcon.IconWidth;
switch (MenuData.UiAction?.DisplayType)
{
case Enums.enumActionDisplayType.hidden:
//todo: add hidden state
break;
case Enums.enumActionDisplayType.disabled:
MenuItemContent.SetValue(OpacityProperty, 0.5);
MenuItemBorder.SetResourceReference(StyleProperty, "Menu.MainCategory.NoHover");
MenuItemBorder.SetValue(ToolTipProperty, string.IsNullOrWhiteSpace(MenuData.UiAction.AlternativeDescription) ? MenuData.UiAction.Description : MenuData.UiAction.AlternativeDescription);
try
{
MenuItemBorder.MouseLeftButtonUp -= MenuItemBorder_Click;
MenuItemBorder.TouchDown -= MenuItemBorder_Click;
}
catch { }
break;
case Enums.enumActionDisplayType.enabled:
MenuItemContent.ClearValue(OpacityProperty);
MenuItemBorder.ClearValue(IsHitTestVisibleProperty);
break;
}
MenuItemBorder.ToolTip = !string.IsNullOrEmpty(MenuData.UiAction?.Description) ? MenuData.UiAction?.Description : null;
ToolTip = !string.IsNullOrEmpty(MenuData.UiAction?.Description) ? MenuData.UiAction?.Description : null;
CustomTextBlock.Text = MenuData.MenuText;
CustomTextBlockBottom.Text = MenuData.MenuText;
if (string.IsNullOrWhiteSpace(MenuData.TrailingText))
{
CustomTrailingTextBlock.Text = string.Empty;
CustomTrailingTextBlock.Visibility = Visibility.Collapsed;
}
else
{
CustomTrailingTextBlock.Text = MenuData.TrailingText;
CustomTrailingTextBlock.Visibility = Visibility.Visible;
}
DrawEnhancedMenuInformation();
}
private void DrawEnhancedMenuInformation()
{
try
{
if (MenuData is cMenuDataContainer containerMenuData)
DrawContainer(containerMenuData);
else if (MenuData is cMenuDataSearchRelation searchRelationMenuData)
DrawSearchRelation(searchRelationMenuData);
else if (MenuData is cMenuDataLoading)
LoadingIcon.Visibility = Visibility.Visible;
else
DrawDefault();
}
catch (Exception E)
{
LogException(E);
}
void DrawContainer(cMenuDataContainer containerMenuData)
{
SubMenuCounterBorder.Visibility = Visibility.Visible;
var count = 0;
foreach (var entry in containerMenuData.SubMenuData)
{
if (entry.UiAction?.DisplayType == null || entry.UiAction?.DisplayType == Enums.enumActionDisplayType.enabled)
count++;
}
if (count == 0)
SubMenuCounterTextBlock.Text = "-";
else
SubMenuCounterTextBlock.Text = count.ToString();
}
void DrawSearchRelation(cMenuDataSearchRelation searchRelationMenuData)
{
if (!(searchRelationMenuData.Data is cF4sdApiSearchResultRelation relationData))
return;
if (searchRelationMenuData.IsMatchingRelation)
{
LoadingIcon.SelectedMaterialIcon = MaterialIconType.ic_link;
LoadingIcon.ClearValue(StyleProperty);
LoadingIcon.Visibility = Visibility.Visible;
}
if (relationData.Type is enumF4sdSearchResultClass.Ticket)
{
if (relationData.Infos is null)
return;
if (relationData.Infos.TryGetValue("Summary", out var ticketSummary))
{
CustomTextBlockBottom.Text = ticketSummary;
CustomTextBlockBorderBottom.Visibility = Visibility.Visible;
}
if (relationData.Infos.TryGetValue("StatusId", out var ticketStatusId))
{
Enum.TryParse(ticketStatusId, true, out enumTicketStatus ticketStatus);
switch (ticketStatus)
{
case enumTicketStatus.Unknown:
break;
case enumTicketStatus.New:
case enumTicketStatus.InProgress:
case enumTicketStatus.OnHold:
MenuItemIcon.SelectedMaterialIcon = MaterialIconType.ic_drafts;
break;
case enumTicketStatus.Closed:
MenuItemIcon.SelectedMaterialIcon = MaterialIconType.ic_mail;
break;
default:
break;
}
}
}
else
{
SearchRelationGrid.Visibility = Visibility.Visible;
var lastUsedTimeSpan = DateTime.UtcNow - searchRelationMenuData.LastUsed;
LanguageDefinitionsConverter valueConverter = new LanguageDefinitionsConverter();
string lastSeenText = null;
if (Math.Floor(lastUsedTimeSpan.TotalHours) > 24)
lastSeenText = valueConverter.Convert(Math.Ceiling(lastUsedTimeSpan.TotalDays), null, "Searchbar.LessThan.Days", null) as string;
else if (Math.Floor(lastUsedTimeSpan.TotalHours) >= 1)
lastSeenText = valueConverter.Convert(Math.Ceiling(lastUsedTimeSpan.TotalHours), null, "Searchbar.LessThan.Hours", null) as string;
else
lastSeenText = valueConverter.Convert(Math.Ceiling(lastUsedTimeSpan.TotalMinutes), null, "Searchbar.LessThan.Min", null) as string;
LessThanTextBlock.Text = lastSeenText;
ActivityIndicator.Width = Math.Max(ActivityIndicator.Width * relationData.UsingLevel, ActivityIndicator.Width * 0.1);
}
}
void DrawDefault()
{
if (string.IsNullOrWhiteSpace(MenuData.SubMenuText))
return;
CustomTextBlockBottom.Text = MenuData.SubMenuText;
CustomTextBlockBorderBottom.Visibility = Visibility.Visible;
}
}
#endregion
#endregion
public CustomMenuItem(bool isLean)
{
_isLean = isLean;
InitializeComponent();
}
#region Events
private void MenuItemBorder_Click(object sender, InputEventArgs e)
{
if (MenuData.UiAction == null)
return;
cUiActionBase.RaiseEvent(MenuData.UiAction, this, this);
}
#region Hover
private void MenuItemBorder_MouseEnter(object sender, MouseEventArgs e)
{
cUtility.SetTickerTextAnimation(CustomTextBlock, CustomTextBlockBorder);
if (string.IsNullOrWhiteSpace(CustomTextBlockBottom.Text) is false)
cUtility.SetTickerTextAnimation(CustomTextBlockBottom, CustomTextBlockBorderBottom);
}
private void MenuItemBorder_MouseLeave(object sender, MouseEventArgs e)
{
CustomTextBlock.TextTrimming = TextTrimming.CharacterEllipsis;
CustomTextBlock.BeginAnimation(MarginProperty, null);
CustomTextBlockBorder.ClearValue(WidthProperty);
CustomTextBlockBorderBottom.ClearValue(WidthProperty);
if (string.IsNullOrWhiteSpace(CustomTextBlockBottom.Text) is false)
{
CustomTextBlockBottom.TextTrimming = TextTrimming.CharacterEllipsis;
CustomTextBlockBottom.BeginAnimation(MarginProperty, null);
}
}
#endregion
#endregion
public void ShowDetailHeadings(bool showDetails)
{
SearchRelationGrid.ColumnDefinitions[0].Width =
showDetails ? new GridLength(1, GridUnitType.Auto) : new GridLength(0);
}
private void CustomMenuItemUc_Initialized(object sender, EventArgs e)
{
if (_isLean)
MenuItemBorder.Height = 30;
}
}
}

View File

@@ -0,0 +1,45 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.AdjustableParameterSection"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800">
<UserControl.Resources>
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter" />
</UserControl.Resources>
<Border Background="{DynamicResource BackgroundColor.Menu.MainCategory}"
CornerRadius="10"
Padding="7.5">
<StackPanel>
<StackPanel Orientation="Horizontal">
<ico:AdaptableIcon x:Name="CollapseButton"
Style="{DynamicResource SettingsPage.Close.Icon}"
BorderPadding="5"
SelectedMaterialIcon="ic_remove"
MouseLeftButtonUp="CollapseButton_MouseLeftButtonUp"
TouchDown="CollapseButton_TouchDown" />
<TextBlock Style="{DynamicResource DetailsPage.DataHistory.TitleColumn.OverviewTitle}"
Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=QuickAction.Parameter}" />
</StackPanel>
<Border x:Name="ParameterBorder"
Padding="10 7.5">
<StackPanel x:Name="ParameterStack" />
</Border>
</StackPanel>
</Border>
</UserControl>

View File

@@ -0,0 +1,376 @@
using C4IT.FASD.Base;
using C4IT.Logging;
using FasdDesktopUi.Basics.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
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.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class AdjustableParameterSection : UserControl, IFocusInvoker
{
#region Variables & Properties
private double parameterBorderHeight = 0.0;
public int? ParentIndex { get; private set; }
public UIElement ParentElement { get; private set; }
#region Parameters
public Dictionary<string, cAdjustableParameter> AdjustableParameters
{
get { return (Dictionary<string, cAdjustableParameter>)GetValue(AdjustableParametersProperty); }
set { SetValue(AdjustableParametersProperty, value); }
}
public static readonly DependencyProperty AdjustableParametersProperty =
DependencyProperty.Register("AdjustableParameters", typeof(Dictionary<string, cAdjustableParameter>), typeof(AdjustableParameterSection), new PropertyMetadata(new Dictionary<string, cAdjustableParameter>(), new PropertyChangedCallback(AdjustableParametersChanged)));
private static void AdjustableParametersChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is AdjustableParameterSection _me))
return;
_me.UpdateAdjustableParameters();
}
#endregion
public Dictionary<cAdjustableParameter, object> ParameterValues { get; set; } = new Dictionary<cAdjustableParameter, object>();
#endregion
public AdjustableParameterSection()
{
InitializeComponent();
}
private void UpdateIFocusInvokerValues()
{
try
{
if (Parent is UIElement parentElement)
{
ParentElement = parentElement;
if (parentElement is Panel panel)
ParentIndex = panel.Children.IndexOf(this);
}
}
catch (Exception E)
{
LogException(E);
}
}
private void UpdateAdjustableParameters()
{
try
{
ParameterStack.Children.Clear();
ParameterValues.Clear();
ParameterBorder.BeginAnimation(HeightProperty, null);
ParameterBorder.Height = double.NaN;
if (AdjustableParameters is null)
return;
foreach (var parameter in AdjustableParameters)
{
try
{
if (!(ParameterValues.ContainsKey(parameter.Value)))
ParameterValues.Add(parameter.Value, null);
var parameterValue = parameter.Value;
switch (parameterValue)
{
case cAdjustableParameterBoolean booleanParameter:
AddBooleanParameter(parameter.Key, booleanParameter);
break;
case cAdjustableParameterNumerical numericalParameter:
AddNumericalParameter(parameter.Key, numericalParameter);
break;
case cAdjustableParameterDropDown dropDownParameter:
AddDropDownParameter(parameter.Key, dropDownParameter);
break;
default:
break;
}
}
catch (Exception E)
{
LogException(E);
}
}
ParameterBorder.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
parameterBorderHeight = ParameterBorder.DesiredSize.Height;
ParameterBorder.Height = parameterBorderHeight;
UpdateIFocusInvokerValues();
}
catch (Exception E)
{
LogException(E);
}
finally
{
}
}
#region Helper
private void AddBooleanParameter(string parameterKey, cAdjustableParameterBoolean booleanParameter)
{
try
{
DockPanel outerPanel = new DockPanel() { Margin = new Thickness(2.5) };
ParameterValues[booleanParameter] = booleanParameter.Default ? $"-{booleanParameter.ParameterName}" : string.Empty;
CheckBox valueCheckBox = new CheckBox() { IsChecked = booleanParameter.Default };
valueCheckBox.Checked += new RoutedEventHandler((sender, e) => ParameterValues[booleanParameter] = $"-{booleanParameter.ParameterName}");
valueCheckBox.Unchecked += new RoutedEventHandler((sender, e) => ParameterValues[booleanParameter] = string.Empty);
DockPanel.SetDock(valueCheckBox, Dock.Right);
valueCheckBox.SetResourceReference(StyleProperty, "ToggleSwitch");
outerPanel.Children.Add(valueCheckBox);
TextBlock parameterNameTextBlock = new TextBlock() { Text = booleanParameter.Names.GetValue(), Margin = new Thickness(0, 0, 7.5, 0) };
if(!string.IsNullOrEmpty(booleanParameter.Descriptions.GetValue()))
{
parameterNameTextBlock.ToolTip = booleanParameter.Descriptions.GetValue();
}
parameterNameTextBlock.SetResourceReference(ForegroundProperty, "FontColor.DetailsPage.DataHistory.Value");
outerPanel.Children.Add(parameterNameTextBlock);
ParameterStack.Children.Add(outerPanel);
}
catch (Exception E)
{
LogException(E);
}
}
private void AddNumericalParameter(string parameterKey, cAdjustableParameterNumerical numericalParameter)
{
try
{
DockPanel outerPanel = new DockPanel() { Margin = new Thickness(2.5) };
ParameterValues[numericalParameter] = numericalParameter.Default;
TextBox valueTextBox = new TextBox() { Text = numericalParameter.Default.ToString(), Width = 35, TextAlignment = TextAlignment.Center };
valueTextBox.SetResourceReference(ForegroundProperty, "FontColor.DetailsPage.DataHistory.Value");
valueTextBox.SetResourceReference(BackgroundProperty, "BackgroundColor.DetailsPage.DataHistory.TitleColumn");
valueTextBox.SetResourceReference(BorderBrushProperty, "BackgroundColor.DetailsPage.DataHistory.ValueColumn");
valueTextBox.PreviewKeyDown += ((sender, e) =>
{
if (double.TryParse(valueTextBox.Text, out var parsedValue))
ParameterValues[numericalParameter] = parsedValue;
});
valueTextBox.PreviewTextInput += new TextCompositionEventHandler((sender, e) =>
{
var plannedValue = valueTextBox.Text.Insert(valueTextBox.CaretIndex, e.Text);
if (double.TryParse(plannedValue, out var parsedValue))
ParameterValues[numericalParameter] = parsedValue;
else
e.Handled = true;
});
DockPanel.SetDock(valueTextBox, Dock.Right);
outerPanel.Children.Add(valueTextBox);
TextBlock parameterNameTextBlock = new TextBlock() { Text = numericalParameter.Names.GetValue(), Margin = new Thickness(0, 0, 7.5, 0) };
if (!string.IsNullOrEmpty(numericalParameter.Descriptions.GetValue()))
{
parameterNameTextBlock.ToolTip = numericalParameter.Descriptions.GetValue();
}
parameterNameTextBlock.SetResourceReference(ForegroundProperty, "FontColor.DetailsPage.DataHistory.Value");
outerPanel.Children.Add(parameterNameTextBlock);
ParameterStack.Children.Add(outerPanel);
}
catch (Exception E)
{
LogException(E);
}
}
private void AddDropDownParameter(string parameterKey, cAdjustableParameterDropDown dropDownParameter)
{
try
{
DockPanel outerPanel = new DockPanel() { Margin = new Thickness(2.5) };
ParameterValues[dropDownParameter] = dropDownParameter.Default;
ComboBox valueComboBox = new ComboBox() { SelectedItem = dropDownParameter.Default, MinWidth = 125 };
valueComboBox.Style = (Style)FindResource("DarkComboBox");
valueComboBox.DropDownOpened += (sender, e) => cFocusInvoker.InvokeGotFocus(this, e);
valueComboBox.DropDownClosed += (sender, e) => cFocusInvoker.InvokeLostFocus(this, e);
foreach (var dropDownValue in dropDownParameter.DropdownValues)
{
try
{
var tempComboBoxItem = new ComboBoxItem() { Content = dropDownValue.DisplayValues.GetValue(), Tag = dropDownValue.Value };
if (dropDownParameter.DropdownValues?.First() == dropDownValue && dropDownParameter.DropdownValues?.Last() == dropDownValue)
tempComboBoxItem.SetResourceReference(StyleProperty, "ComboBoxSingleItem");
else if (dropDownParameter.DropdownValues?.First() == dropDownValue)
tempComboBoxItem.SetResourceReference(StyleProperty, "ComboBoxFirstItem");
else if (dropDownParameter.DropdownValues?.Last() == dropDownValue)
tempComboBoxItem.SetResourceReference(StyleProperty, "ComboBoxLastItem");
valueComboBox.Items.Add(tempComboBoxItem);
}
catch (Exception E)
{
LogException(E);
}
}
var selectedIndex = -1;
var defaultValue = dropDownParameter.DropdownValues.FirstOrDefault(value => value.Value == dropDownParameter.Default);
if (defaultValue != null)
selectedIndex = dropDownParameter.DropdownValues.IndexOf(defaultValue);
valueComboBox.SelectionChanged += ((sender, e) =>
{
try
{
if (!(sender is ComboBox senderComboBox))
return;
if (!(senderComboBox.SelectedItem is FrameworkElement selectedElement))
return;
ParameterValues[dropDownParameter] = selectedElement.Tag;
}
catch (Exception E)
{
LogException(E);
}
});
valueComboBox.SelectedIndex = selectedIndex;
DockPanel.SetDock(valueComboBox, Dock.Right);
outerPanel.Children.Add(valueComboBox);
TextBlock parameterNameTextBlock = new TextBlock() { VerticalAlignment = VerticalAlignment.Center, Text = dropDownParameter.Names.GetValue(), Margin = new Thickness(0, 0, 7.5, 0) };
if (!string.IsNullOrEmpty(dropDownParameter.Descriptions.GetValue()))
{
parameterNameTextBlock.ToolTip = dropDownParameter.Descriptions.GetValue();
}
parameterNameTextBlock.SetResourceReference(ForegroundProperty, "FontColor.DetailsPage.DataHistory.Value");
outerPanel.Children.Add(parameterNameTextBlock);
ParameterStack.Children.Add(outerPanel);
}
catch (Exception E)
{
LogException(E);
}
}
#endregion
private void ToggleCollapse(bool shouldCollapse)
{
try
{
const double animatinDurationInSeconds = 0.2;
if (shouldCollapse)
ParameterBorder.BeginAnimation(HeightProperty, new DoubleAnimation(0, TimeSpan.FromSeconds(animatinDurationInSeconds)));
else
ParameterBorder.BeginAnimation(HeightProperty, new DoubleAnimation(parameterBorderHeight, TimeSpan.FromSeconds(animatinDurationInSeconds)));
CollapseButton.SelectedMaterialIcon = shouldCollapse ? MaterialIcons.MaterialIconType.ic_add : MaterialIcons.MaterialIconType.ic_remove;
}
catch (Exception E)
{
LogException(E);
}
}
public void ToggleIsActive(bool isActive)
{
try
{
if (isActive)
{
UpdateAdjustableParameters();
foreach (UIElement element in ParameterStack.Children)
{
element.IsEnabled = true;
}
}
else
{
ToggleCollapse(true);
foreach (UIElement element in ParameterStack.Children)
{
element.IsEnabled = false;
}
}
}
catch (Exception E)
{
LogException(E);
}
}
#region CollapseButton_Click
private void CollapseButton_Click()
{
try
{
bool shouldCollapse = ParameterBorder.ActualHeight - ParameterBorder.Padding.Top - ParameterBorder.Padding.Bottom != 0;
ToggleCollapse(shouldCollapse);
}
catch (Exception E)
{
LogException(E);
}
}
private void CollapseButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
CollapseButton_Click();
}
private void CollapseButton_TouchDown(object sender, TouchEventArgs e)
{
CollapseButton_Click();
}
#endregion
}
}

View File

@@ -0,0 +1,45 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.DataCanvas"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:converter="clr-namespace:FasdDesktopUi.Basics.Converter"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="400"
Name="DataCanvasUc">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisibility" />
<converter:DataCanvasIsCloseButtonVisibileConverter x:Key="IsCloseButtonVisible" />
</UserControl.Resources>
<StackPanel x:Name="MainStackPanel">
<local:QuickActionStatusMonitor x:Name="QuickActionStatusUc"
QuickActionFinished="QuickActionStatusUc_QuickActionFinished"
IsCloseButtonVisible="{Binding ElementName=DataCanvasUc, Path=DataCanvasData, Converter={StaticResource IsCloseButtonVisible}, ConverterParameter={x:Static converter:enumDataCanvasTypes.quickActionStatusMonitor} }" />
<local:DetailedData x:Name="DetailedDataUc"
Visibility="{Binding ElementName=DataCanvasUc, Path=IsDetailedLayout, Converter={StaticResource BoolToVisibility}}"
IsCloseButtonVisible="{Binding ElementName=DataCanvasUc, Path=DataCanvasData, Converter={StaticResource IsCloseButtonVisible}, ConverterParameter={x:Static converter:enumDataCanvasTypes.detailedData} }" />
<local:DetailedChart x:Name="DetailedChartUc"
HorizontalAlignment="Stretch"
Width="385"
Visibility="{Binding ElementName=DataCanvasUc, Path=IsDetailedLayout, Converter={StaticResource BoolToVisibility}}"
IsCloseButtonVisible="{Binding ElementName=DataCanvasUc, Path=DataCanvasData, Converter={StaticResource IsCloseButtonVisible}, ConverterParameter={x:Static converter:enumDataCanvasTypes.detailedData} }" />
<local:DynamicChart x:Name="DynamicChartUc"
HorizontalAlignment="Stretch"
Width="385"
Visibility="{Binding ElementName=DataCanvasUc, Path=IsDetailedLayout, Converter={StaticResource BoolToVisibility}}"
IsCloseButtonVisible="{Binding ElementName=DataCanvasUc, Path=DataCanvasData, Converter={StaticResource IsCloseButtonVisible}, ConverterParameter={x:Static converter:enumDataCanvasTypes.detailedData} }" />
<local:DetailedRecommendation x:Name="RecommendationUc"
Width="{Binding ElementName=DetailedDataUc, Path=ActualWidth, UpdateSourceTrigger=PropertyChanged}"
MinWidth="300"
Visibility="{Binding ElementName=DataCanvasUc, Path=IsDetailedLayout, Converter={StaticResource BoolToVisibility}}"
IsCloseButtonVisible="{Binding ElementName=DataCanvasUc, Path=DataCanvasData, Converter={StaticResource IsCloseButtonVisible}, ConverterParameter={x:Static converter:enumDataCanvasTypes.recommendation} }" />
</StackPanel>
</UserControl>

View File

@@ -0,0 +1,259 @@
using C4IT.Logging;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Pages.DetailsPage.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel;
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.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class DataCanvas : UserControl
{
#region Properties
private cSupportCaseDataProvider dataProvider;
public cSupportCaseDataProvider DataProvider
{
get => dataProvider;
set
{
if (DataCanvasData.GetDetailedDataAsync != null)
{
if (dataProvider != null)
dataProvider.HealthCardDataHelper.DataRefreshed -= HealthCardDataHelper_DataRefreshed;
value.HealthCardDataHelper.DataRefreshed += HealthCardDataHelper_DataRefreshed;
}
dataProvider = value;
QuickActionStatusUc.DataProvider = value;
}
}
#region DataCanvasData
private static void DataCanvasDataChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
try
{
var oldData = e.OldValue as cDataCanvasDataModel;
var newData = e.NewValue as cDataCanvasDataModel;
if (!(d is DataCanvas _me))
return;
if (_me.dataProvider != null)
{
if (oldData.GetDetailedDataAsync != null)
_me.dataProvider.HealthCardDataHelper.DataRefreshed -= _me.HealthCardDataHelper_DataRefreshed;
if (newData.GetDetailedDataAsync != null)
_me.dataProvider.HealthCardDataHelper.DataRefreshed += _me.HealthCardDataHelper_DataRefreshed;
}
_me.QuickActionStatusUc.CancelQuickAction();
_me.RecommendationUc.RecommendationData = _me.DataCanvasData.RecommendationData;
_me.RecommendationUc.CloseButtonClickedAction = _me.CloseDataCanvas;
if (_me.DataCanvasData.ChartData is null && _me.DataCanvasData.DetailedChartData is null)
{
_me.DetailedDataUc.DetailedInformationData = _me.DataCanvasData.DetailedData;
_me.DetailedDataUc.CloseButtonClickedAction = _me.CloseDataCanvas;
_me.DetailedChartUc.ChartData = null;
_me.DynamicChartUc.ChartData = null;
}
else if (_me.DataCanvasData.ChartData is null)
{
_me.DetailedChartUc.ChartData = _me.DataCanvasData.DetailedChartData;
_me.DynamicChartUc.ChartData = null;
_me.DetailedDataUc.DetailedInformationData = null;
_me.DetailedChartUc.CloseButtonClickedAction = _me.CloseDataCanvas;
}
else
{
_me.DynamicChartUc.ChartData = _me.DataCanvasData.ChartData;
_me.DetailedChartUc.ChartData = null;
_me.DetailedDataUc.DetailedInformationData = null;
_me.DynamicChartUc.CloseButtonClickedAction = _me.CloseDataCanvas;
}
_me.QuickActionStatusUc.QuickActionData = _me.DataCanvasData.QuickActionStatusMonitorData;
_me.QuickActionStatusUc.CloseButtonClickedAction = _me.CloseDataCanvas;
_me.QuickActionStatusUc.QuickActionOutputs.Clear();
_me.QuickActionStatusUc.MeasureValues = null;
}
catch (Exception E)
{
LogException(E);
}
}
public static readonly RoutedEvent DataCanvasWasClosedEvent = EventManager.RegisterRoutedEvent("DataCanvasWasClosed", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DataCanvas));
public event RoutedEventHandler DataCanvasWasClosed
{
add { AddHandler(DataCanvasWasClosedEvent, value); }
remove { RemoveHandler(DataCanvasWasClosedEvent, value); }
}
private void CloseDataCanvas()
{
//Visibility = Visibility.Collapsed;
if (this.Parent is FrameworkElement parentElement)
parentElement.Visibility = Visibility.Collapsed;
QuickActionStatusUc.CancelQuickAction();
RaiseEvent(new RoutedEventArgs(DataCanvasWasClosedEvent));
}
public static readonly DependencyProperty DataCanvasDataProperty =
DependencyProperty.Register("DataCanvasData", typeof(cDataCanvasDataModel), typeof(DataCanvas), new PropertyMetadata(new cDataCanvasDataModel(), new PropertyChangedCallback(DataCanvasDataChangedCallback)));
public cDataCanvasDataModel DataCanvasData
{
get { return (cDataCanvasDataModel)GetValue(DataCanvasDataProperty); }
set { SetValue(DataCanvasDataProperty, value); }
}
#endregion
#region SubMenuData
private static void SubMenuDataChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is DataCanvas _me))
return;
}
public static readonly DependencyProperty SubMenuDataProperty =
DependencyProperty.Register("SubMenuData", typeof(List<cMenuDataBase>), typeof(DataCanvas), new PropertyMetadata(new List<cMenuDataBase>(), new PropertyChangedCallback(SubMenuDataChangedCallback)));
public List<cMenuDataBase> SubMenuData
{
get { return (List<cMenuDataBase>)GetValue(SubMenuDataProperty); }
set { SetValue(SubMenuDataProperty, value); }
}
#endregion
#region isDetailedLayout
public static readonly DependencyProperty IsDetailedLayoutProperty =
DependencyProperty.Register("IsDetailedLayout", typeof(bool), typeof(DataCanvas), new PropertyMetadata(false));
public bool IsDetailedLayout
{
get { return (bool)GetValue(IsDetailedLayoutProperty); }
set { SetValue(IsDetailedLayoutProperty, value); }
}
#endregion
#endregion
public DataCanvas()
{
InitializeComponent();
DetailedChartUc.Visibility = Visibility.Visible;
}
public DataCanvas(bool drawInScrollViewer)
{
InitializeComponent();
if (!drawInScrollViewer)
return;
var tempDataCanvas = MainStackPanel;
ScrollViewer scrollViewer = new ScrollViewer() { Padding = new Thickness(0, 0, 10, 10), VerticalScrollBarVisibility = ScrollBarVisibility.Auto };
DataCanvasUc.Content = scrollViewer;
scrollViewer.Content = tempDataCanvas;
}
private async void HealthCardDataHelper_DataRefreshed(object sender, EventArgs e)
{
try
{
var detailedData = DataCanvasData.DetailedData;
var detailedChartData = DataCanvasData.DetailedChartData;
var chartData = DataCanvasData.ChartData;
if (DataCanvasData.GetDetailedDataAsync != null)
detailedData = await DataCanvasData.GetDetailedDataAsync.Invoke();
if (DataCanvasData.GetDatailedChartDataAsync != null)
detailedChartData = await DataCanvasData.GetDatailedChartDataAsync.Invoke();
if (DataCanvasData.GetChartDataAsync != null)
chartData = await DataCanvasData.GetChartDataAsync.Invoke();
var tempDataCanvasData = new cDataCanvasDataModel()
{
GetDetailedDataAsync = DataCanvasData.GetDetailedDataAsync,
GetDatailedChartDataAsync = DataCanvasData.GetDatailedChartDataAsync,
GetChartDataAsync = DataCanvasData.GetChartDataAsync,
RecommendationData = DataCanvasData.RecommendationData,
QuickActionStatusMonitorData = DataCanvasData.QuickActionStatusMonitorData,
};
if (detailedChartData is null && chartData is null)
tempDataCanvasData.DetailedData = detailedData;
else if (chartData is null)
tempDataCanvasData.DetailedChartData = detailedChartData;
else
tempDataCanvasData.ChartData = chartData;
DataCanvasData = tempDataCanvasData;
}
catch (Exception E)
{
LogException(E);
}
}
public void InsertNewDetailedData(List<object> newDetailedData)
{
try
{
var tempDetailedData = DetailedDataUc.DetailedInformationData.FullDetailedData;
if (tempDetailedData == null || tempDetailedData.Count <= 0)
return;
tempDetailedData.Insert(1, newDetailedData);
DetailedDataUc.DetailedInformationData = new cDetailedDataModel() { Heading = DetailedDataUc.DetailedInformationData.Heading, FullDetailedData = tempDetailedData };
DetailedDataUc.DetailedDataListView.SelectedItem = DetailedDataUc.DetailedDataListView.Items[0]; // todo: check if best solution with index = 0
}
catch (Exception E)
{
LogException(E);
}
finally
{
}
}
private void QuickActionStatusUc_QuickActionFinished(object sender, QuickActionEventArgs e)
{
if (Window.GetWindow(this) is Pages.DetailsPage.DetailsPageView)
InsertNewDetailedData(e.QuickActionResult);
}
}
}

View File

@@ -0,0 +1,303 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.DetailedChart"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
Name="ChartUc"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisibility" />
<vc:NullValueToVisibilityConverter x:Key="NullToVisibility" />
</UserControl.Resources>
<Border CornerRadius="10"
Margin="0 0 0 10"
Height="270"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
Visibility="{Binding ElementName=ChartUc, Path=ChartData, Converter={StaticResource NullToVisibility}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="42" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="45" />
</Grid.ColumnDefinitions>
<Border Grid.Column="0"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
CornerRadius="10,0,0,0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"
x:Name="TitleBlock"
HorizontalAlignment="Center"
Margin="0,5,-42,0"
FontFamily="Calibri"
FontSize="14"
FontWeight="Bold"
Foreground="{DynamicResource Color.Menu.Icon}">
</TextBlock>
<TextBlock Grid.Row="1"
x:Name="DateBlock"
HorizontalAlignment="Center"
Margin="0,0,-42,0"
FontFamily="Calibri"
FontSize="13"
FontWeight="Regular"
Foreground="{DynamicResource Color.Menu.Icon}">
</TextBlock>
</Grid>
</Border>
<ico:AdaptableIcon x:Name="CloseButton"
Grid.Column="2"
SelectedInternIcon="window_close"
MouseLeftButtonUp="CloseButton_MouseLeftButtonUp"
TouchDown="CloseButton_TouchDown"
Style="{DynamicResource SettingsPage.Close.Icon}"
Visibility="{Binding ElementName=ChartUc, Path=IsCloseButtonVisible, Converter={StaticResource BoolToVisibility}}" />
</Grid>
<Grid Grid.Row="1"
Margin="10,10,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="32" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="28" />
</Grid.RowDefinitions>
<Grid Grid.Column="0"
Grid.Row="0"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Border Grid.RowSpan="5"
x:Name="GraphicBorder"
Panel.ZIndex="1">
<Border x:Name="CanvasBorder">
<Canvas x:Name="GraphicCanvas"
Panel.ZIndex="1" />
</Border>
</Border>
<Border Grid.Row="0"
BorderThickness="1"
Height="1"
Margin="5,0,5,0">
<Border.BorderBrush>
<DrawingBrush Viewport="0,0,10,10"
ViewportUnits="Absolute"
TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="{DynamicResource HorizontalLineColor}">
<GeometryDrawing.Geometry>
<GeometryGroup>
<RectangleGeometry Rect="0,0,50,50" />
<RectangleGeometry Rect="50,50,50,0" />
</GeometryGroup>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Border.BorderBrush>
</Border>
<Border Grid.Row="1"
BorderThickness="1"
Height="1"
Margin="5,0,5,0">
<Border.BorderBrush>
<DrawingBrush Viewport="0,0,10,10"
ViewportUnits="Absolute"
TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="{DynamicResource HorizontalLineColor}">
<GeometryDrawing.Geometry>
<GeometryGroup>
<RectangleGeometry Rect="0,0,50,50" />
<RectangleGeometry Rect="50,50,50,0" />
</GeometryGroup>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Border.BorderBrush>
</Border>
<Border Grid.Row="2"
BorderThickness="1"
Height="1"
Margin="5,0,5,0">
<Border.BorderBrush>
<DrawingBrush Viewport="0,0,10,10"
ViewportUnits="Absolute"
TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="{DynamicResource HorizontalLineColor}">
<GeometryDrawing.Geometry>
<GeometryGroup>
<RectangleGeometry Rect="0,0,50,50" />
<RectangleGeometry Rect="50,50,50,0" />
</GeometryGroup>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Border.BorderBrush>
</Border>
<Border Grid.Row="3"
BorderThickness="1"
Height="1"
Margin="5,0,5,0">
<Border.BorderBrush>
<DrawingBrush Viewport="0,0,10,10"
ViewportUnits="Absolute"
TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="{DynamicResource HorizontalLineColor}">
<GeometryDrawing.Geometry>
<GeometryGroup>
<RectangleGeometry Rect="0,0,50,50" />
<RectangleGeometry Rect="50,50,50,0" />
</GeometryGroup>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Border.BorderBrush>
</Border>
<Border Grid.Row="4"
BorderThickness="1"
Height="1"
Margin="5,0,5,0">
<Border.BorderBrush>
<DrawingBrush Viewport="0,0,10,10"
ViewportUnits="Absolute"
TileMode="Tile">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="{DynamicResource HorizontalLineColor}">
<GeometryDrawing.Geometry>
<GeometryGroup>
<RectangleGeometry Rect="0,0,50,50" />
<RectangleGeometry Rect="50,50,50,0" />
</GeometryGroup>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Border.BorderBrush>
</Border>
</Grid>
<Border Name="PercentBorder"
Grid.Column="2"
Grid.Row="0"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"
Text="100%"
VerticalAlignment="Center"
FontFamily="Calibri"
FontSize="11"
Foreground="{DynamicResource Color.Menu.Icon}">
</TextBlock>
<TextBlock Grid.Row="1"
Text="75%"
VerticalAlignment="Center"
FontFamily="Calibri"
FontSize="11"
Foreground="{DynamicResource Color.Menu.Icon}">
</TextBlock>
<TextBlock Grid.Row="2"
Text="50%"
VerticalAlignment="Center"
FontFamily="Calibri"
FontSize="11"
Foreground="{DynamicResource Color.Menu.Icon}">
</TextBlock>
<TextBlock Grid.Row="3"
Text="25%"
VerticalAlignment="Center"
FontFamily="Calibri"
FontSize="11"
Foreground="{DynamicResource Color.Menu.Icon}">
</TextBlock>
<TextBlock Grid.Row="4"
Text="0%"
VerticalAlignment="Center"
FontFamily="Calibri"
FontSize="11"
Foreground="{DynamicResource Color.Menu.Icon}">
</TextBlock>
</Grid>
</Border>
<Grid x:Name="TimeStampGrid"
Grid.Column="0"
Grid.Row="1"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
Margin="0,0,0,15">
</Grid>
</Grid>
</Grid>
</Border>
</UserControl>

View File

@@ -0,0 +1,435 @@
using FasdDesktopUi.Basics.Models;
using System;
using System.Collections.Generic;
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.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
{
[Obsolete("Instead use " + nameof(DynamicChart))]
public partial class DetailedChart : UserControl
{
#region Variables
static bool wasRendered = false;
int DataDurationStart = 0;
int DataDurationEnd = 0;
int DataDurationTotal = 0;
int ReducedTimeStamps = 0;
DateTime firstTime;
#endregion
#region Dependency Properties
#region ChartData
public cDetailedChartModel ChartData
{
get { return (cDetailedChartModel)GetValue(ChartDataProperty); }
set { SetValue(ChartDataProperty, value); }
}
public static readonly DependencyProperty ChartDataProperty =
DependencyProperty.Register("ChartData", typeof(cDetailedChartModel), typeof(DetailedChart), new PropertyMetadata(null, new PropertyChangedCallback(HandleDependancyPropertyChanged)));
private static void HandleDependancyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is DetailedChart me)) return;
me.BindingValueChange();
}
#endregion
#region IsCloseButtonVisible
public static readonly DependencyProperty IsCloseButtonVisibleProperty =
DependencyProperty.Register("IsCloseButtonVisible", typeof(bool), typeof(DetailedChart), new PropertyMetadata(false));
public bool IsCloseButtonVisible
{
get { return (bool)GetValue(IsCloseButtonVisibleProperty); }
set { SetValue(IsCloseButtonVisibleProperty, value); }
}
#endregion
#endregion
public Action CloseButtonClickedAction { get; set; }
[Obsolete("Instead use " + nameof(DynamicChart))]
public DetailedChart()
{
InitializeComponent();
}
#region Binding
public void BindingValueChange()
{
try
{
if (ChartData?.Data == null || ChartData.Data.Count <= 0) return;
GraphicCanvas.Children.Clear();
TimeStampGrid.Children.Clear();
TimeStampGrid.ColumnDefinitions.Clear();
GraphicDataProperty.Clear();
ReducedTimeStamps = 0;
FillGraphicDataProperty();
FillVariables();
CreateDateTitle();
SetCanvasBorderPadding();
CreateTimeStamps();
DrawGraphicData();
if (!wasRendered)
{
wasRendered = true;
var _h = Dispatcher.Invoke(async () =>
{
await Task.Delay(50);
BindingValueChange();
});
}
}
catch (Exception E)
{
LogException(E);
}
}
#endregion
#region GraphicDataProperty
public List<cChartValue> GraphicDataProperty { get; set; } = new List<cChartValue>();
public void FillGraphicDataProperty()
{
try
{
if (ChartData?.Data == null) return;
var reverseData = ChartData.Data.ToList();
reverseData.Reverse();
if ((DateTime)reverseData[0][ChartData.TimeIndex] < (DateTime)reverseData[reverseData.Count() - 1][ChartData.TimeIndex])
{
foreach (var item in reverseData)
{
cChartValue data = new cChartValue();
data.Value = (double)item[ChartData.ValueIndex];
data.Duration = int.Parse(item[ChartData.DurationIndex].ToString());
data.Time = (DateTime)item[ChartData.TimeIndex];
data.Time = data.Time.ToLocalTime();
GraphicDataProperty.Add(data);
}
}
else if ((DateTime)ChartData.Data[0][ChartData.TimeIndex] < (DateTime)ChartData.Data[ChartData.Data.Count() - 1][ChartData.TimeIndex] || ChartData.Data.Count == 1)
{
foreach (var item in ChartData.Data)
{
cChartValue data = new cChartValue();
data.Value = (double)item[ChartData.ValueIndex];
data.Duration = int.Parse(item[ChartData.DurationIndex].ToString());
data.Time = (DateTime)item[ChartData.TimeIndex];
data.Time = data.Time.ToLocalTime();
GraphicDataProperty.Add(data);
}
}
}
catch (Exception E)
{
LogException(E);
}
}
#endregion
#region FillVariables
public void FillVariables()
{
try
{
firstTime = GraphicDataProperty.First<cChartValue>().Time;
DateTime lastTime = GraphicDataProperty.Last<cChartValue>().Time;
int lastDuration = GraphicDataProperty.Last<cChartValue>().Duration;
lastTime = lastTime.AddMilliseconds(lastDuration);
DataDurationStart = firstTime.Hour;
if (lastTime.Minute != 0)
{
lastTime = lastTime.AddMinutes(60 - (lastDuration / 60000));
}
DataDurationEnd = lastTime.Hour;
DataDurationTotal = DataDurationEnd - DataDurationStart;
if (firstTime.Date < lastTime.Date)
{
if (DataDurationTotal < 2)
{
DataDurationTotal = (24 - DataDurationStart) + DataDurationEnd;
}
}
if (DataDurationTotal > 18)
{
ReducedTimeStamps = 3;
if (DataDurationTotal % 4 == 3)
{
DataDurationTotal += 3;
}
else if (DataDurationTotal % 4 == 2)
{
DataDurationTotal += 2;
}
else if (DataDurationTotal % 4 == 1)
{
DataDurationTotal += 1;
}
}
else if (DataDurationTotal > 12)
{
ReducedTimeStamps = 2;
if (DataDurationTotal % 3 == 2)
{
DataDurationTotal += 2;
}
else if (DataDurationTotal % 3 == 1)
{
DataDurationTotal += 1;
}
}
else if (DataDurationTotal > 6)
{
ReducedTimeStamps = 1;
if (DataDurationTotal % 2 == 1)
{
DataDurationTotal += 1;
}
}
}
catch (Exception E)
{
LogException(E);
}
}
#endregion
#region Create Date Title
public void CreateDateTitle()
{
try
{
DateTime dataDate = GraphicDataProperty.First<cChartValue>().Time;
dataDate = dataDate.Date;
DateBlock.Text = dataDate.ToString("dddd, dd.MM.yyyy");
TitleBlock.Text = ChartData.ChartTitle;
}
catch (Exception E)
{
LogException(E);
}
}
#endregion
#region SetCanvasBorderPadding
public void SetCanvasBorderPadding()
{
try
{
double borderWidth = GraphicBorder.ActualWidth;
double paddingWidth = borderWidth / (((double)DataDurationTotal + 1) * 2.0);
double borderHeight = GraphicBorder.ActualHeight;
double paddingHeight = borderHeight / 10.0;
paddingHeight = Math.Max(0, paddingHeight);
paddingWidth = Math.Max(0, paddingWidth);
GraphicBorder.Padding = new Thickness(paddingWidth, paddingHeight, paddingWidth, paddingHeight);
GraphicBorder.UpdateLayout();
CanvasBorder.UpdateLayout();
}
catch (Exception E)
{
LogException(E);
}
}
#endregion
#region Time Stamps
public void CreateTimeStamps()
{
try
{
for (int i = 0; i <= DataDurationTotal; i++)
{
ColumnDefinition timeStamp = new ColumnDefinition();
timeStamp.Width = new GridLength(1, GridUnitType.Star);
TimeStampGrid.ColumnDefinitions.Add(timeStamp);
if (ReducedTimeStamps == 3 && i % 4 != 0)
{
continue;
}
if (ReducedTimeStamps == 2 && i % 3 != 0)
{
continue;
}
if (ReducedTimeStamps == 1 && i % 2 != 0)
{
continue;
}
TextBlock TimeStampText = new TextBlock()
{
Text = (firstTime.AddHours(i)).Hour.ToString() + ":00",
FontFamily = new FontFamily("Calibri"),
FontSize = 11,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
TextAlignment = TextAlignment.Center,
TextTrimming = TextTrimming.None,
};
TimeStampText.SetResourceReference(TextBlock.ForegroundProperty, "Color.Menu.Icon");
if (DataDurationTotal > 10)
{
TimeStampText.Margin = new Thickness(-7, 0, -7, 0);
}
Grid.SetColumn(TimeStampText, i);
TimeStampGrid.Children.Add(TimeStampText);
}
}
catch (Exception E)
{
LogException(E);
}
}
#endregion
#region Draw Data
public double CalculateSetLeft(DateTime dataTime)
{
double setLeft = (double)dataTime.Hour + ((double)dataTime.Minute / 60.0);
setLeft = (setLeft - (double)DataDurationStart) * ((double)CanvasBorder.ActualWidth / ((double)DataDurationTotal));
return setLeft;
}
public void DrawGraphicData()
{
try
{
double setLeft = 0.0;
double setFactor = 0.0;
setFactor = (GraphicCanvas.ActualHeight - 8.0) / 100.0;
foreach (var data in GraphicDataProperty)
{
DateTime dataTime = data.Time;
double dataValue = data.Value;
int dataDuration = data.Duration;
Border border = new Border
{
Height = 8.0,
Width = (double)dataDuration * ((double)CanvasBorder.ActualWidth / ((double)DataDurationTotal)) / 3600000.0,
CornerRadius = new CornerRadius(4.0),
ToolTip = dataTime.ToShortTimeString() + " - " + dataTime.AddMilliseconds(dataDuration).ToShortTimeString() + " | " + (int)dataValue + "%"
};
if (border.Width < 8)
{
border.Width = 8;
}
if (ChartData.IsThresholdActive == false)
{
border.Background = new SolidColorBrush(Color.FromRgb(0, 157, 221));
}
else if (dataValue >= ChartData.ErrorThreshold)
{
border.Background = new SolidColorBrush(Color.FromRgb(206, 61, 54));
}
else if (dataValue >= ChartData.WarningThreshold)
{
border.Background = new SolidColorBrush(Color.FromRgb(251, 157, 40));
}
else
{
border.Background = new SolidColorBrush(Color.FromRgb(117, 177, 89));
}
setLeft = CalculateSetLeft(dataTime);
Canvas.SetBottom(border, dataValue * setFactor);
Canvas.SetLeft(border, setLeft);
GraphicCanvas.Children.Add(border);
}
}
catch (Exception E)
{
LogException(E);
}
}
#endregion
#region Close Button
private void CloseButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
CloseButton_Click();
}
private void CloseButton_TouchDown(object sender, TouchEventArgs e)
{
CloseButton_Click();
}
private void CloseButton_Click()
{
CloseButtonClickedAction?.Invoke();
}
#endregion
public class cChartValue
{
public DateTime Time { get; set; }
public double Value { get; set; }
public int Duration { get; set; }
}
}
}

View File

@@ -0,0 +1,146 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.DetailedData"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:converter="clr-namespace:FasdDesktopUi.Basics.Converter"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800"
x:Name="DetailedDataUc">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisibility" />
<converter:NullValueToVisibilityConverter x:Key="NullToVisibility" />
<converter:LanguageDefinitionsConverter x:Key="LanguageConverter" />
<Style TargetType="GridViewColumnHeader" x:Key="NoColumnHeaderStyle">
<Setter Property="Template" Value="{x:Null}"/>
</Style>
</UserControl.Resources>
<Border Margin="0 0 0 10"
Visibility="{Binding ElementName=DetailedDataUc, Path=DetailedInformationData, Converter={StaticResource NullToVisibility}}"
CornerRadius="10"
Padding="10"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}">
<StackPanel x:Name="mainStackPanel">
<StackPanel.Resources>
<Style TargetType="GridViewColumnHeader">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GridViewColumnHeader}">
<TextBlock Style="{DynamicResource DetailsPage.DataHistory.TitleColumn.OverviewTitle}"
Text="{TemplateBinding Content}"
Margin="0 0 15 5"
Padding="5"
TextAlignment="Left"
HorizontalAlignment="Left" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="ListViewItem"
BasedOn="{StaticResource DetailsPage.DataHistory.Value}">
<Setter Property="Background"
Value="{DynamicResource BackgroundColor.DetailsPage.DataHistory.TitleColumn}" />
<Setter Property="Foreground"
Value="{DynamicResource FontColor.DetailsPage.DataHistory.Value}" />
<Setter Property="FontWeight"
Value="Regular" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border Margin="0 0.5"
BorderBrush="Transparent"
BorderThickness="0"
Background="{TemplateBinding Background}">
<GridViewRowPresenter Height="30"
HorizontalAlignment="Stretch"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Width="Auto"
Content="{TemplateBinding Content}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Background"
Value="{DynamicResource HighlightBackgroundColor.DetailsPage.DataHistory.TitleColumn}" />
<Setter Property="Foreground"
Value="{DynamicResource FontColor.Menu.Categories.Hover}" />
</Trigger>
<Trigger Property="IsSelected"
Value="True">
<Setter Property="Background"
Value="{DynamicResource HighlightBackgroundColor.DetailsPage.DataHistory.TitleColumn}" />
<Setter Property="Foreground"
Value="{DynamicResource FontColor.Menu.Categories.Hover}" />
</Trigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<DockPanel>
<StackPanel Orientation="Horizontal" DockPanel.Dock="Right" Visibility="{Binding IsCloseButtonVisible, ElementName=DetailedDataUc, Converter={StaticResource BoolToVisibility}}">
<ico:AdaptableIcon x:Name="CopyButton" x:FieldModifier="private"
Style="{DynamicResource SettingsPage.Close.Icon}"
SelectedInternIcon="menuBar_copy"
ToolTip="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=DetailsPage.DetailTable.CopyContent}"
MouseUp="CopyButton_MouseUp" TouchDown="CopyButton_TouchDown"
/>
<ico:AdaptableIcon x:Name="DownloadButton" x:FieldModifier="private"
Style="{DynamicResource SettingsPage.Close.Icon}"
SelectedMaterialIcon="ic_file_download"
Margin="-12,0,0,0"
ToolTip="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=DetailsPage.DetailTable.ContentDownload}"
MouseUp="DownloadButton_MouseUp" TouchDown="DownloadButton_TouchDown"
/>
<ico:AdaptableIcon x:Name="CloseButton" x:FieldModifier="private"
Style="{DynamicResource SettingsPage.Close.Icon}"
MouseUp="CloseButton_MouseUp"
TouchDown="CloseButton_TouchDown"
SelectedInternIcon="window_close"
Margin="-12,0,0,0"
/>
</StackPanel>
<ico:AdaptableIcon DockPanel.Dock="Left"
VerticalAlignment="Center"
PrimaryIconColor="{DynamicResource Color.FunctionMarker}"
BorderPadding="0"
IconHeight="10"
IconWidth="10"
SelectedInternIcon="misc_dot" />
<TextBlock Text="{Binding DetailedInformationData.Heading, ElementName=DetailedDataUc}"
DockPanel.Dock="Left"
Style="{DynamicResource DetailsPage.DataHistory.TitleColumn.OverviewTitle}"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10" />
</DockPanel>
<ListView x:Name="DetailedDataListView"
ItemsSource="{Binding ListViewData, ElementName=DetailedDataUc}"
BorderThickness="0"
Background="Transparent"
PreviewMouseWheel="ListView_PreviewMouseWheel">
</ListView>
</StackPanel>
</Border>
</UserControl>

View File

@@ -0,0 +1,223 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.UiActions;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class DetailedData : UserControl
{
#region Properties
#region ListViewDataSource
#region ListViewHeaders
public List<object> ListViewHeaders
{
get
{
if (DetailedInformationData.FullDetailedData?.Count > 0)
{
var _retVal = DetailedInformationData.FullDetailedData[0];
var _ret = _retVal as List<object>;
return _ret;
}
return new List<object>();
}
}
#endregion
#region ListViewData
internal static readonly DependencyPropertyKey ListViewDataKey = DependencyProperty.RegisterReadOnly("ListViewData", typeof(List<object>), typeof(DetailedData), new PropertyMetadata(new List<object>()));
public static readonly DependencyProperty ListViewDataProperty = ListViewDataKey.DependencyProperty;
public List<object> ListViewData => (List<object>)GetValue(ListViewDataProperty);
#endregion
#endregion
#region DetailedData
private static void DetailedDataChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is DetailedData _me))
return;
if (_me.DetailedInformationData == null)
return;
int _skip = _me.DetailedInformationData.HasColumnHeaders? 1 : 0;
if (_me.DetailedInformationData.FullDetailedData.Count < _skip)
return;
var listViewDataKeyValue = _me.DetailedInformationData.FullDetailedData.Count > _skip ? _me.DetailedInformationData.FullDetailedData.Skip(_skip).ToList() : new List<object>();
_me.SetValue(ListViewDataKey, listViewDataKeyValue);
_me.UpdateListView();
}
public static readonly DependencyProperty DetailedInformationDataProperty =
DependencyProperty.Register("DetailedInformationData", typeof(cDetailedDataModel), typeof(DetailedData), new PropertyMetadata(new cDetailedDataModel(), new PropertyChangedCallback(DetailedDataChangedCallback)));
public cDetailedDataModel DetailedInformationData
{
get { return (cDetailedDataModel)GetValue(DetailedInformationDataProperty); }
set { SetValue(DetailedInformationDataProperty, value); }
}
#endregion
#region IsCloseButtonVisible
public static readonly DependencyProperty IsCloseButtonVisibleProperty =
DependencyProperty.Register("IsCloseButtonVisible", typeof(bool), typeof(DetailedData), new PropertyMetadata(false));
public bool IsCloseButtonVisible
{
get { return (bool)GetValue(IsCloseButtonVisibleProperty); }
set { SetValue(IsCloseButtonVisibleProperty, value); }
}
#endregion
public Action CloseButtonClickedAction { get; set; }
#endregion
public DetailedData()
{
InitializeComponent();
}
private void UpdateListView()
{
DetailedDataListView.ClearValue(ListView.ViewProperty);
if (ListViewHeaders.Count < 0)
return;
GridView newGridView = new GridView() { AllowsColumnReorder = false };
// set the header style (header present or not)
var _data = DetailedInformationData;
if (!_data.HasColumnHeaders)
{
object _objStyle = this.FindResource("NoColumnHeaderStyle");
if (_objStyle is Style _style)
if (!DetailedDataListView.Resources.Contains(typeof(GridViewColumnHeader)))
DetailedDataListView.Resources.Add(typeof(GridViewColumnHeader), _style);
}
else
{
if (DetailedDataListView.Resources.Contains(typeof(GridViewColumnHeader)))
DetailedDataListView.Resources.Remove(typeof(GridViewColumnHeader));
}
// create the header columns
for (int i = 0; i < ListViewHeaders.Count; i++)
{
BindingBase bindingBase = new Binding($"[{i}]");
object _header = null;
if (_data.HasColumnHeaders)
_header = ListViewHeaders[i];
var _gvColumn = new GridViewColumn() { Header = _header, DisplayMemberBinding = bindingBase };
newGridView.Columns.Add(_gvColumn);
}
DetailedDataListView.View = newGridView;
}
private void ListView_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
if (sender is ListView && !e.Handled)
{
e.Handled = true;
var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
{
RoutedEvent = MouseWheelEvent,
Source = sender
};
var parent = ((Control)sender).Parent as UIElement;
parent.RaiseEvent(eventArg);
}
}
#region CloseButton_Click
private void CloseButton_Click()
{
if (CloseButtonClickedAction != null)
CloseButtonClickedAction.Invoke();
}
private void CloseButton_MouseUp(object sender, MouseButtonEventArgs e)
{
CloseButton_Click();
}
private void CloseButton_TouchDown(object sender, TouchEventArgs e)
{
CloseButton_Click();
}
#endregion
#region CopyButton_Click
private async Task CopyButton_ClickAsync()
{
var uiAction = new cUiCopyDetailsTableContent(DetailedInformationData);
cUiActionBase.RaiseEvent(uiAction, this, this);
await cUtility.ChangeIconToCheckAsync(CopyButton);
}
private async void CopyButton_MouseUp(object sender, MouseButtonEventArgs e)
{
await CopyButton_ClickAsync();
}
private async void CopyButton_TouchDown(object sender, TouchEventArgs e)
{
await CopyButton_ClickAsync();
}
#endregion
#region DownloadButton_Click
private void DownloadButton_Click()
{
var uiAction = new cUiSaveDetailsTableContent(DetailedInformationData);
cUiActionBase.RaiseEvent(uiAction, this, this);
}
private void DownloadButton_MouseUp(object sender, MouseButtonEventArgs e)
{
DownloadButton_Click();
}
private void DownloadButton_TouchDown(object sender, TouchEventArgs e)
{
DownloadButton_Click();
}
#endregion
}
}

View File

@@ -0,0 +1,67 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.DetailedRecommendation"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Pages.DetailsPage.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:converter="clr-namespace:FasdDesktopUi.Basics.Converter"
x:Name="RecommendationUc"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisibility"/>
<converter:NullValueToVisibilityConverter x:Key="NullToVisibility"/>
</UserControl.Resources>
<Border Visibility="{Binding ElementName=RecommendationUc, Path=RecommendationData, Converter={StaticResource NullToVisibility}}"
Padding="10"
CornerRadius="10"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}">
<StackPanel>
<DockPanel>
<ico:AdaptableIcon x:Name="CloseButton"
DockPanel.Dock="Right"
Style="{DynamicResource SettingsPage.Close.Icon}"
MouseUp="CloseButton_MouseUp"
TouchDown="CloseButton_TouchDown"
Visibility="{Binding ElementName=RecommendationUc, Path=IsCloseButtonVisible, Converter={StaticResource BoolToVisibility}}"
SelectedInternIcon="window_close" />
<ico:AdaptableIcon x:Name="RecommendationIcon"
x:FieldModifier="private"
DockPanel.Dock="Left"
VerticalAlignment="Center"
PrimaryIconColor="{DynamicResource Color.Blue}"
BorderPadding="0"
IconHeight="15"
IconWidth="15"
SelectedInternIcon="status_info" />
<TextBlock Text="{Binding RecommendationData.Category, ElementName=RecommendationUc}"
DockPanel.Dock="Left"
Style="{DynamicResource DetailsPage.DataHistory.TitleColumn.OverviewTitle}"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10" />
</DockPanel>
<Border Padding="10"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.TitleColumn}"
CornerRadius="10">
<TextBlock Text="{Binding ElementName=RecommendationUc, Path=RecommendationData.Recommendation}"
Foreground="{DynamicResource FontColor.DetailsPage.DataHistory.Value}"
FontFamily="Calibri"
FontSize="14"
FontWeight="Regular"
TextWrapping="Wrap"/>
</Border>
</StackPanel>
</Border>
</UserControl>

View File

@@ -0,0 +1,116 @@
using F4SD_AdaptableIcon;
using F4SD_AdaptableIcon.Enums;
using FasdDesktopUi.Basics.Helper;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Pages.DetailsPage.Models;
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;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class DetailedRecommendation : UserControl
{
#region Properties
#region RecommendationData
public static readonly DependencyProperty RecommendationDataProperty =
DependencyProperty.Register("RecommendationData", typeof(cRecommendationDataModel), typeof(DetailedRecommendation), new PropertyMetadata(new cRecommendationDataModel()));
public cRecommendationDataModel RecommendationData
{
get { return (cRecommendationDataModel)GetValue(RecommendationDataProperty); }
set { SetValue(RecommendationDataProperty, value); }
}
#endregion
#region IsCloseButtonVisible
public static readonly DependencyProperty IsCloseButtonVisibleProperty =
DependencyProperty.Register("IsCloseButtonVisible", typeof(bool), typeof(DetailedRecommendation), new PropertyMetadata(false));
public bool IsCloseButtonVisible
{
get { return (bool)GetValue(IsCloseButtonVisibleProperty); }
set { SetValue(IsCloseButtonVisibleProperty, value); }
}
#endregion
#region Icon
public IconData Icon
{
get { return (IconData)GetValue(IconProperty); }
set { SetValue(IconProperty, value); }
}
public static readonly DependencyProperty IconProperty =
DependencyProperty.Register("Icon", typeof(IconData), typeof(DetailedRecommendation), new PropertyMetadata(new IconData(enumInternIcons.status_info), HandleIconChanged));
private static void HandleIconChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is DetailedRecommendation recommendation && e.NewValue is IconData iconData)
{
IconHelper.SetIconValue(recommendation.RecommendationIcon, iconData);
}
}
public string PrimaryIconColorResourceName
{
get { return (string)GetValue(PrimaryIconColorResourceNameProperty); }
set { SetValue(PrimaryIconColorResourceNameProperty, value); }
}
public static readonly DependencyProperty PrimaryIconColorResourceNameProperty =
DependencyProperty.Register("PrimaryIconColorResourceName", typeof(string), typeof(DetailedRecommendation), new PropertyMetadata("Color.Blue", HandleColorChanged));
private static void HandleColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is DetailedRecommendation recommendation)
{
recommendation.RecommendationIcon.SetResourceReference(AdaptableIcon.AdaptableIcon.PrimaryIconColorProperty, e.NewValue);
}
}
#endregion
public Action CloseButtonClickedAction { get; set; }
#endregion
public DetailedRecommendation()
{
InitializeComponent();
}
private void CloseButton_Click()
{
if (CloseButtonClickedAction != null)
CloseButtonClickedAction.Invoke();
}
private void CloseButton_MouseUp(object sender, MouseButtonEventArgs e)
{
CloseButton_Click();
}
private void CloseButton_TouchDown(object sender, TouchEventArgs e)
{
CloseButton_Click();
}
}
}

View File

@@ -0,0 +1,127 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.DynamicChart"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
Name="DynChartUc"
mc:Ignorable="d"
SizeChanged="UserControl_SizeChanged"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisibility" />
<vc:NullValueToVisibilityConverter x:Key="NullToVisibility" />
</UserControl.Resources>
<Border CornerRadius="10"
Margin="0 0 0 10"
Height="270"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
Visibility="{Binding ElementName=DynChartUc, Path=ChartData, Converter={StaticResource NullToVisibility}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="42" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!--#region Kopfzeile -->
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="45" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="45" />
</Grid.ColumnDefinitions>
<ico:AdaptableIcon x:Name="BarChartButton"
Grid.Column="0"
SelectedMaterialIcon="ic_sort"
MouseLeftButtonUp="ChangeChartType_MouseLeftButtonUp"
TouchDown="ChangeChartType_TouchDown"
Style="{DynamicResource Menu.MenuBar.PinnedIcon.Color}"
Visibility="Collapsed" RenderTransformOrigin="0.5,0.5">
<ico:AdaptableIcon.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="-90"/>
<TranslateTransform/>
</TransformGroup>
</ico:AdaptableIcon.RenderTransform>
</ico:AdaptableIcon>
<ico:AdaptableIcon x:Name="LineGraphButton"
Grid.Column="0"
SelectedMaterialIcon="ic_clear_all"
MouseLeftButtonUp="ChangeChartType_MouseLeftButtonUp"
TouchDown="ChangeChartType_TouchDown"
Style="{DynamicResource Menu.MenuBar.PinnedIcon.Color}"
Visibility="Visible"/>
<Border Grid.Column="2"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
CornerRadius="10,0,0,0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"
x:Name="TitleBlock"
HorizontalAlignment="Center"
Margin="0,5,0,0"
FontFamily="Calibri"
FontSize="14"
FontWeight="Bold"
Foreground="{DynamicResource Color.Menu.Icon}">
</TextBlock>
<TextBlock Grid.Row="1"
x:Name="DateBlock"
HorizontalAlignment="Center"
FontFamily="Calibri"
FontSize="13"
FontWeight="Regular"
Foreground="{DynamicResource Color.Menu.Icon}">
</TextBlock>
</Grid>
</Border>
<ico:AdaptableIcon x:Name="CloseButton"
Grid.Column="4"
SelectedInternIcon="window_close"
MouseLeftButtonUp="CloseButton_MouseLeftButtonUp"
TouchDown="CloseButton_TouchDown"
Style="{DynamicResource SettingsPage.Close.Icon}"
Visibility="{Binding ElementName=DynChartUc, Path=IsCloseButtonVisible, Converter={StaticResource BoolToVisibility}}"/>
</Grid>
<!--#endregion-->
<!--#region Inhalt -->
<Grid Grid.Row="1"
Margin="10">
<Border x:Name="GraphicBorder"
Panel.ZIndex="1">
<Border x:Name="CanvasBorder">
<Canvas x:Name="GraphicCanvas"
Panel.ZIndex="1"/>
</Border>
</Border>
</Grid>
<!--#endregion-->
</Grid>
</Border>
</UserControl>

View File

@@ -0,0 +1,832 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using FasdDesktopUi.Basics.Models;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class DynamicChart : UserControl
{
#region Variables
int DataDurationStart;
int DataDurationEnd;
int DataDurationTotal;
int timeSkip;
private double PaddingTop;
private double PaddingBottom;
private double PaddingLeft;
private double PaddingRight;
private double DataHeight;
private double DataWidth;
private LinearTransformation xCoordinate;
private LinearTransformation yCoordinate;
Size sizeY;
Size sizeX;
#endregion
#region Properties
#region ChartData
public cChartModel ChartData
{
get { return (cChartModel)GetValue(ChartDataProperty); }
set { SetValue(ChartDataProperty, value); }
}
public static readonly DependencyProperty ChartDataProperty =
DependencyProperty.Register("ChartData", typeof(cChartModel), typeof(DynamicChart), new PropertyMetadata(null, new PropertyChangedCallback(HandleDependancyPropertyChanged)));
private static void HandleDependancyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is DynamicChart me)) return;
me.BindingValueChange();
}
#endregion
#region IsCloseButtonVisible
public bool IsCloseButtonVisible
{
get { return (bool)GetValue(IsCloseButtonVisibleProperty); }
set { SetValue(IsCloseButtonVisibleProperty, value); }
}
public static readonly DependencyProperty IsCloseButtonVisibleProperty =
DependencyProperty.Register("IsCloseButtonVisible", typeof(bool), typeof(DynamicChart), new PropertyMetadata(false));
#endregion
#region IsBarChart
public bool isBarChart
{
get { return (bool)GetValue(isBarChartProperty); }
set { SetValue(isBarChartProperty, value); }
}
// Using a DependencyProperty as the backing store for isBarChart. This enables animation, styling, binding, etc...
public static readonly DependencyProperty isBarChartProperty =
DependencyProperty.Register("isBarChart", typeof(bool), typeof(DynamicChart), new PropertyMetadata(true, new PropertyChangedCallback(HandleBarChartPropertyChanged)));
private static void HandleBarChartPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is DynamicChart me)) return;
me.ChartTypeChange();
}
#endregion
#region GraphicDataProperty
public List<cChartValue> GraphicDataProperty { get; set; } = new List<cChartValue>();
#endregion
#endregion
#region Internal Classes
public class cChartValue
{
public DateTime Time { get; set; }
public double Value { get; set; }
public int Duration { get; set; }
}
public class LinearTransformation
{
private double x0;
private double x1;
private double z0;
private double z1;
private double a;
private double c;
public LinearTransformation(double x0, double x1, double z0, double z1)
{
this.x0 = x0;
this.x1 = x1;
this.z0 = z0;
this.z1 = z1;
a = (x1 - x0) / (z1 - z0);
c = x0 - (a * z0);
}
public double GetCoordinate(double x)
{
return a * x + c;
}
}
#endregion
public Action CloseButtonClickedAction { get; set; }
#region Restructure
public void BindingValueChange()
{
try
{
ClearControl();
if (ChartData == null)
{
return;
}
if (this.ActualHeight == 0 || this.ActualWidth == 0)
{
return;
}
SetGraphicDataProperty();
SetTitle();
SetDate();
SetTime();
SetCanvas();
SetScale();
SetTimeStamps();
SetLines();
if (isBarChart == true)
{
SetValuesBarChart();
}
else
{
SetValuesLineGraph();
}
}
catch (Exception E)
{
LogException(E);
}
}
public void ChartTypeChange()
{
try
{
GraphicCanvas.Children.Clear();
if (isBarChart == true)
{
BarChartButton.Visibility = Visibility.Collapsed;
LineGraphButton.Visibility = Visibility.Visible;
SetScale();
SetTimeStamps();
SetLines();
SetValuesBarChart();
}
else
{
BarChartButton.Visibility = Visibility.Visible;
LineGraphButton.Visibility = Visibility.Collapsed;
SetScale();
SetTimeStamps();
SetLines();
SetValuesLineGraph();
}
}
catch (Exception E)
{
LogException(E);
}
}
#endregion
#region Methods
public void SetGraphicDataProperty()
{
try
{
if (ChartData?.Data == null) return;
var reverseData = ChartData.Data.ToList();
reverseData.Reverse();
if ((DateTime)reverseData[0][ChartData.TimeIndex] < (DateTime)reverseData[reverseData.Count() - 1][ChartData.TimeIndex])
{
foreach (var item in reverseData)
{
if (item[ChartData.ValueIndex] == null)
{
continue;
}
cChartValue data = new cChartValue();
data.Value = (double)Convert.ChangeType(item[ChartData.ValueIndex], typeof(double));
if (ChartData.DurationIndex > -1)
data.Duration = int.Parse(item[ChartData.DurationIndex].ToString());
data.Time = (DateTime)item[ChartData.TimeIndex];
data.Time = data.Time.ToLocalTime();
GraphicDataProperty.Add(data);
}
}
else if ((DateTime)ChartData.Data[0][ChartData.TimeIndex] < (DateTime)ChartData.Data[ChartData.Data.Count() - 1][ChartData.TimeIndex] || ChartData.Data.Count == 1)
{
foreach (var item in ChartData.Data)
{
if (item[ChartData.ValueIndex] == null)
{
continue;
}
cChartValue data = new cChartValue();
data.Value = (double)Convert.ChangeType(item[ChartData.ValueIndex], typeof(double));
if (ChartData.DurationIndex > -1)
data.Duration = int.Parse(item[ChartData.DurationIndex].ToString());
data.Time = (DateTime)item[ChartData.TimeIndex];
data.Time = data.Time.ToLocalTime();
GraphicDataProperty.Add(data);
}
}
}
catch (Exception E)
{
LogException(E);
}
}
public void ClearControl()
{
TitleBlock.Text = string.Empty;
DateBlock.Text = string.Empty;
GraphicCanvas.Children.Clear();
GraphicDataProperty.Clear();
}
public void SetTitle()
{
TitleBlock.Text = ChartData.ChartTitle;
}
public void SetDate()
{
try
{
DateTime dataDate = GraphicDataProperty.First<cChartValue>().Time;
dataDate = dataDate.Date;
DateBlock.Text = $"{dataDate.ToString("dddd", new CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage))}, {dataDate.ToString("d", new CultureInfo(cFasdCockpitConfig.Instance.SelectedLanguage))}";
}
catch (Exception E)
{
LogException(E);
}
}
public void SetTime()
{
try
{
DateTime firstTime = GraphicDataProperty.First<cChartValue>().Time;
DateTime lastTime = GraphicDataProperty.Last<cChartValue>().Time;
int lastDuration = GraphicDataProperty.Last<cChartValue>().Duration;
lastTime = lastTime.AddMilliseconds(lastDuration);
DataDurationStart = firstTime.Hour;
DataDurationEnd = lastTime.Hour + 1;
TimeSpan totalDuration = lastTime - firstTime;
DataDurationTotal = DataDurationEnd - DataDurationStart + (24 * totalDuration.Days);
DataDurationTotal = GetNextLogicalTotalDuration(DataDurationTotal);
// temp fix
DataDurationEnd = DataDurationStart + DataDurationTotal;
timeSkip = (int)Math.Ceiling(DataDurationTotal / 5.0);
}
catch (Exception E)
{
LogException(E);
}
// this is a temporary helper method to keep the structure of the current state of the charts.
// however the logic should be rethought and maybe finally replaced for a even more dynamic approach
int GetNextLogicalTotalDuration(int totalDuration)
{
if (totalDuration < 0)
return 24 + totalDuration;
else if (totalDuration <= 3)
return 3;
else if (totalDuration <= 5)
return 5;
else if (totalDuration <= 8)
return 8;
else if (totalDuration <= 10)
return 10;
else if (totalDuration <= 12)
return 12;
else if (totalDuration <= 15)
return 15;
else if (totalDuration <= 18)
return 18;
else if (totalDuration <= 20)
return 20;
else return 24;
}
}
public void SetCanvas()
{
try
{
string textY;
if (ChartData.UnitFormat.Contains("{0}"))
{
textY = String.Format(ChartData.UnitFormat, ChartData.MaxValue.ToString());
}
else
{
textY = ChartData.MaxValue.ToString() + ChartData.UnitFormat;
}
sizeY = GetStringSize(textY, 11, new System.Windows.Media.FontFamily("Calibri"));
string textX = "09:00";
sizeX = GetStringSize(textX, 11, new System.Windows.Media.FontFamily("Calibri"));
PaddingTop = 5 + (sizeY.Height / 2);
PaddingRight = 10 + sizeY.Width;
PaddingBottom = 10 + sizeX.Height + PaddingTop;
PaddingLeft = 10 + (sizeX.Width / 2);
DataHeight = GraphicCanvas.ActualHeight - PaddingTop - PaddingBottom;
DataWidth = GraphicCanvas.ActualWidth - PaddingLeft - PaddingRight;
yCoordinate = new LinearTransformation(PaddingTop + DataHeight, PaddingTop, ChartData.MinValue, ChartData.MaxValue);
xCoordinate = new LinearTransformation(PaddingLeft, PaddingLeft + DataWidth, DataDurationStart * 3600000, (DataDurationStart + DataDurationTotal) * 3600000);
}
catch (Exception E)
{
LogException(E);
}
}
public void SetScale()
{
try
{
int Minimum = 0;
if ((ChartData.MinValue / ChartData.StepLengthScale) % 1 != 0)
{
int Multiplikator = ChartData.MinValue / ChartData.StepLengthScale;
Multiplikator++;
Minimum = Multiplikator * ChartData.MinValue;
}
else
{
Minimum = ChartData.MinValue;
}
for (int i = Minimum; i <= ChartData.MaxValue; i += ChartData.StepLengthScale)
{
string text;
if (ChartData.UnitFormat.Contains("{0}"))
{
text = String.Format(ChartData.UnitFormat, i.ToString());
}
else
{
text = i.ToString() + ChartData.UnitFormat;
}
TextBlock textBlock = new TextBlock()
{
Text = text,
FontFamily = new FontFamily("Calibri"),
FontSize = 11,
};
textBlock.SetResourceReference(TextBlock.ForegroundProperty, "Color.Menu.Icon");
Canvas.SetTop(textBlock, yCoordinate.GetCoordinate(i) - (sizeY.Height / 2));
Canvas.SetLeft(textBlock, PaddingLeft + DataWidth + 1);
GraphicCanvas.Children.Add(textBlock);
}
}
catch (Exception E)
{
LogException(E);
}
}
public void SetTimeStamps()
{
try
{
for (int i = DataDurationStart; i <= DataDurationEnd; i++)
{
if ((DataDurationStart - i) % timeSkip != 0)
{
continue;
}
string timeStamp;
int timeStampTime = i;
if (timeStampTime > 24)
{
timeStampTime -= 24;
}
if (i < 10)
{
timeStamp = "0" + timeStampTime.ToString() + ":00";
}
else
{
timeStamp = timeStampTime.ToString() + ":00";
}
TextBlock textBlock = new TextBlock()
{
Text = timeStamp,
FontFamily = new FontFamily("Calibri"),
FontSize = 11,
};
textBlock.SetResourceReference(TextBlock.ForegroundProperty, "Color.Menu.Icon");
Canvas.SetTop(textBlock, PaddingTop + DataHeight + (sizeX.Height / 2));
Canvas.SetLeft(textBlock, (xCoordinate.GetCoordinate(i * 3600000)) - (sizeX.Width / 2));
GraphicCanvas.Children.Add(textBlock);
}
}
catch (Exception E)
{
LogException(E);
}
}
public void SetLines()
{
try
{
int Minimum = 0;
if ((ChartData.MinValue / ChartData.StepLengthLine) % 1 != 0)
{
int Multiplikator = ChartData.MinValue / ChartData.StepLengthLine;
Multiplikator++;
Minimum = Multiplikator * ChartData.MinValue;
}
else
{
Minimum = ChartData.MinValue;
}
for (int i = Minimum; i <= ChartData.MaxValue; i += ChartData.StepLengthLine)
{
Point point1 = new Point(PaddingLeft, yCoordinate.GetCoordinate(i));
Point point2 = new Point(PaddingLeft + DataWidth, yCoordinate.GetCoordinate(i));
Line dottedLine = new Line();
dottedLine.SetResourceReference(Line.StrokeProperty, "HorizontalLineColor");
dottedLine.StrokeThickness = 1;
dottedLine.StrokeDashArray = new DoubleCollection { 5, 5 };
dottedLine.X1 = point1.X;
dottedLine.Y1 = point1.Y;
dottedLine.X2 = point2.X;
dottedLine.Y2 = point2.Y;
GraphicCanvas.Children.Add(dottedLine);
}
}
catch (Exception E)
{
LogException(E);
}
}
public void SetValuesLineGraph()
{
try
{
foreach (var data in GraphicDataProperty)
{
DateTime dataTime = data.Time;
double dataValue = data.Value;
int dataDuration = data.Duration;
double time = dataTime.TimeOfDay.TotalMilliseconds;
double xLeft = xCoordinate.GetCoordinate(time);
double xRight = xCoordinate.GetCoordinate(time + dataDuration);
double y = 0;
if (dataValue > ChartData.MaxValue)
{
y = yCoordinate.GetCoordinate(ChartData.MaxValue) - 5;
}
else if (dataValue < ChartData.MinValue)
{
y = yCoordinate.GetCoordinate(ChartData.MinValue) + 5;
}
else
{
y = yCoordinate.GetCoordinate(dataValue);
}
Border border = new Border()
{
Height = 6.0,
Width = xRight - xLeft,
CornerRadius = new CornerRadius(4.0),
ToolTip = dataTime.ToShortTimeString() + " - " + dataTime.AddMilliseconds(dataDuration).ToShortTimeString() + " | " + dataValue,
};
if (border.Width < 6)
{
border.Width = 6;
}
if (ChartData.IsThresholdActive == false)
{
border.Background = new SolidColorBrush(Color.FromRgb(0, 157, 221));
}
else
{
if (ChartData.IsDirectionUp == false)
{
if (dataValue <= ChartData.ErrorThreshold)
{
border.Background = new SolidColorBrush(Color.FromRgb(206, 61, 54));
}
else if (dataValue <= ChartData.WarningThreshold)
{
border.Background = new SolidColorBrush(Color.FromRgb(251, 157, 40));
}
else
{
border.Background = new SolidColorBrush(Color.FromRgb(117, 177, 89));
}
}
else
{
if (dataValue >= ChartData.ErrorThreshold)
{
border.Background = new SolidColorBrush(Color.FromRgb(206, 61, 54));
}
else if (dataValue >= ChartData.WarningThreshold)
{
border.Background = new SolidColorBrush(Color.FromRgb(251, 157, 40));
}
else
{
border.Background = new SolidColorBrush(Color.FromRgb(117, 177, 89));
}
}
}
Canvas.SetTop(border, y - (border.Height / 2));
Canvas.SetLeft(border, xLeft);
GraphicCanvas.Children.Add(border);
}
}
catch (Exception E)
{
LogException(E);
}
}
public void SetValuesBarChart()
{
try
{
foreach (var data in GraphicDataProperty)
{
DateTime dataTime = data.Time;
double dataValue = data.Value;
int dataDuration = data.Duration;
double time = dataTime.TimeOfDay.TotalMilliseconds;
double xLeft = xCoordinate.GetCoordinate(time);
double xRight = xCoordinate.GetCoordinate(time + dataDuration);
double y = 0;
if (dataValue > ChartData.MaxValue)
{
y = yCoordinate.GetCoordinate(ChartData.MaxValue) - 5;
}
else if (dataValue < ChartData.MinValue)
{
y = yCoordinate.GetCoordinate(ChartData.MinValue) + 5;
}
else
{
y = yCoordinate.GetCoordinate(dataValue);
}
Border border = new Border()
{
Height = yCoordinate.GetCoordinate(0) - y,
Width = xRight - xLeft,
CornerRadius = new CornerRadius(2, 2, 0, 0),
ToolTip = dataTime.ToShortTimeString() + " - " + dataTime.AddMilliseconds(dataDuration).ToShortTimeString() + " | " + dataValue,
};
if (border.Width < 6)
{
border.Width = 6;
}
if (ChartData.IsThresholdActive == false)
{
border.Background = new SolidColorBrush(Color.FromRgb(0, 157, 221));
}
else
{
if (ChartData.IsDirectionUp == false)
{
if (dataValue <= ChartData.ErrorThreshold)
{
border.Background = new SolidColorBrush(Color.FromRgb(206, 61, 54));
}
else if (dataValue <= ChartData.WarningThreshold)
{
border.Background = new SolidColorBrush(Color.FromRgb(251, 157, 40));
}
else
{
border.Background = new SolidColorBrush(Color.FromRgb(117, 177, 89));
}
}
else
{
if (dataValue >= ChartData.ErrorThreshold)
{
border.Background = new SolidColorBrush(Color.FromRgb(206, 61, 54));
}
else if (dataValue >= ChartData.WarningThreshold)
{
border.Background = new SolidColorBrush(Color.FromRgb(251, 157, 40));
}
else
{
border.Background = new SolidColorBrush(Color.FromRgb(117, 177, 89));
}
}
}
Canvas.SetTop(border, y);
Canvas.SetLeft(border, xLeft);
GraphicCanvas.Children.Add(border);
}
}
catch (Exception E)
{
LogException(E);
}
}
#endregion
public DynamicChart()
{
InitializeComponent();
}
#region CloseButton_Click
private void CloseButton_Click()
{
if (CloseButtonClickedAction != null)
CloseButtonClickedAction.Invoke();
}
private void CloseButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
CloseButton_Click();
}
private void CloseButton_TouchDown(object sender, TouchEventArgs e)
{
CloseButton_Click();
}
#endregion
#region ChangeChartType_Click
private void ChangeChartType_Click(object sender)
{
if (!(sender is FrameworkElement senderElement))
{
return;
}
if (senderElement.Name == "BarChartButton")
{
isBarChart = true;
}
if (senderElement.Name == "LineGraphButton")
{
isBarChart = false;
}
}
private void ChangeChartType_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
ChangeChartType_Click(sender);
}
private void ChangeChartType_TouchDown(object sender, TouchEventArgs e)
{
ChangeChartType_Click(sender);
}
#endregion
private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e)
{
BindingValueChange();
}
public static Size GetStringSize(string text, double fontSize, FontFamily fontFamily)
{
CultureInfo cultureInfo = CultureInfo.GetCultureInfo("de-DE");
FlowDirection flowDirection = FlowDirection.LeftToRight;
#pragma warning disable CS0618 // Type or member is obsolete
FormattedText formattedText = new FormattedText(
text,
cultureInfo,
flowDirection,
new Typeface(fontFamily.Source),
fontSize,
Brushes.Black
);
#pragma warning restore CS0618 // Type or member is obsolete
return new Size(formattedText.Width, formattedText.Height);
}
}
}

View File

@@ -0,0 +1,139 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.QuickActionStatusMonitor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:gif="http://wpfanimatedgif.codeplex.com"
xmlns:converter="clr-namespace:FasdDesktopUi.Basics.Converter"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800"
x:Name="QuickActionStatusMonitorUc"
IsVisibleChanged="BlurInvoker_IsActiveChanged">
<UserControl.Resources>
<converter:NullValueToVisibilityConverter x:Key="NullToVisibility" />
<converter:LanguageDefinitionsConverter x:Key="LanguageConverter" />
<BooleanToVisibilityConverter x:Key="BoolToVisibility" />
</UserControl.Resources>
<Border Visibility="{Binding ElementName=QuickActionStatusMonitorUc, Path=QuickActionData, Converter={StaticResource NullToVisibility}}"
CornerRadius="10"
Padding="10"
Margin="0 0 0 10"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}">
<StackPanel>
<DockPanel LastChildFill="False">
<ico:AdaptableIcon x:Name="CloseButton"
DockPanel.Dock="Right"
Style="{DynamicResource SettingsPage.Close.Icon}"
MouseUp="CloseButton_MouseUp"
TouchDown="CloseButton_TouchDown"
Visibility="{Binding ElementName=QuickActionStatusMonitorUc, Path=IsCloseButtonVisible, Converter={StaticResource BoolToVisibility}}"
SelectedInternIcon="window_close" />
<ico:AdaptableIcon x:Name="ExecuteButton"
DockPanel.Dock="Left"
VerticalAlignment="Center"
BorderPadding="2.5"
IconHeight="15"
IconWidth="15"
Style="{DynamicResource SettingsPage.Close.Icon}"
MouseUp="ExecuteButton_MouseUp"
TouchDown="ExecuteButton_TouchDown"
SelectedInternIcon="misc_play" />
<ico:AdaptableIcon DockPanel.Dock="Left"
Style="{DynamicResource Menu.MenuBar.PinnedIcon.Base}"
ToolTip="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=QuickAction.Permission.User}"
VerticalAlignment="Center"
Margin="7.5 0 0 0"
BorderPadding="0"
IconHeight="15"
IconWidth="15"
Visibility="{Binding ElementName=QuickActionStatusMonitorUc, Path=QuickActionData.RequiresUserPermission, Converter={StaticResource BoolToVisibility}}"
SelectedInternIcon="misc_user" />
<TextBlock Text="{Binding QuickActionData.ActionName, ElementName=QuickActionStatusMonitorUc}"
DockPanel.Dock="Left"
Style="{DynamicResource DetailsPage.DataHistory.TitleColumn.OverviewTitle}"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10" />
<ico:AdaptableIcon x:Name="CopyButton"
Visibility="Collapsed"
DockPanel.Dock="Left"
Style="{DynamicResource SettingsPage.Close.Icon}"
VerticalAlignment="Center"
BorderPadding="0"
IconHeight="15"
IconWidth="15"
MouseLeftButtonUp="CopyButton_MouseLeftButtonUp"
TouchDown="CopyButton_TouchDown"
SelectedInternIcon="menuBar_copy" />
<ico:AdaptableIcon x:Name="SecretButton"
Visibility="Collapsed"
DockPanel.Dock="Left"
Style="{DynamicResource SettingsPage.Close.Icon}"
Margin="5 0 0 0"
VerticalAlignment="Center"
BorderPadding="0"
IconHeight="15"
IconWidth="15"
MouseLeftButtonUp="SecretButton_MouseLeftButtonUp"
TouchDown="SecretButton_TouchDown"
SelectedMaterialIcon="ic_visibility" />
</DockPanel>
<Border Padding="7.5"
Background="{DynamicResource BackgroundColor.Menu.MainCategory}"
CornerRadius="10">
<DockPanel x:Name="CompletionStatusPanel">
<DockPanel.Resources>
<Style TargetType="TextBlock"
BasedOn="{StaticResource DetailsPage.DataHistory.Value}">
<Setter Property="FontWeight"
Value="Regular" />
<Setter Property="Foreground"
Value="{DynamicResource FontColor.DetailsPage.DataHistory.Value}" />
<Setter Property="TextAlignment"
Value="Left" />
<Setter Property="TextWrapping"
Value="Wrap" />
</Style>
<Style TargetType="ico:AdaptableIcon"
BasedOn="{StaticResource SlimPage.Widget.Header.Icon}">
<Setter Property="Margin"
Value="7.5 2.5" />
</Style>
</DockPanel.Resources>
</DockPanel>
</Border>
<StackPanel x:Name="QuickActionResultStack" />
<Border Padding="7.5"
CornerRadius="10"
Margin="0 7.5 0 0"
Background="{DynamicResource BackgroundColor.Menu.MainCategory}"
Visibility="{Binding ElementName=QuickActionStatusMonitorUc, Path=MeasureValues, Converter={StaticResource NullToVisibility}}">
<Grid x:Name="MeasureValueGrid" />
</Border>
<local:AdjustableParameterSection x:Name="AdjustableParameterSectionUc"
Margin="0 7.5 0 0"
AdjustableParameters="{Binding ElementName=QuickActionStatusMonitorUc, Path=QuickActionData.QuickActionParameters}"
Visibility="{Binding ElementName=QuickActionStatusMonitorUc, Path=QuickActionData.QuickActionParameters, Converter={StaticResource NullToVisibility}}" />
</StackPanel>
</Border>
</UserControl>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,162 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.QuickActionStatusMonitorResultElement"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800">
<UserControl.Resources>
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter" />
<Style TargetType="TextBlock"
BasedOn="{StaticResource DetailsPage.DataHistory.Value}">
<Setter Property="FontWeight"
Value="Bold" />
<Setter Property="Foreground"
Value="{DynamicResource FontColor.DetailsPage.DataHistory.Value}" />
<Setter Property="TextAlignment"
Value="Left" />
<Setter Property="TextWrapping"
Value="Wrap" />
<Style.Triggers>
<EventTrigger RoutedEvent="Control.MouseLeftButtonUp">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation From="0.4"
Duration="0:0:1"
FillBehavior="Stop"
Storyboard.TargetProperty="Opacity" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
<Style TargetType="ico:AdaptableIcon"
BasedOn="{StaticResource SlimPage.Widget.Header.Icon}">
<Setter Property="Margin"
Value="2.5 -7.5 2.5 2.5" />
<Setter Property="BorderPadding"
Value="0" />
<Setter Property="IconHeight"
Value="35" />
<Setter Property="IconWidth"
Value="35" />
</Style>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Border Grid.Row="0"
x:Name="QuickActionErrorContainer"
Padding="7.5"
Margin="0 7.5 0 0"
Background="{DynamicResource BackgroundColor.Menu.MainCategory}"
CornerRadius="10">
<ScrollViewer HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=QuickAction.Result.ErrorInfo}"
Margin="0 0 0 3"
Foreground="{DynamicResource Color.Red}" />
<Grid x:Name="QuickActionErrorGrid"
Grid.Row="1">
<Grid.Resources>
<Style TargetType="Border">
<Setter Property="Padding"
Value="5 0" />
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0"
Margin="8 0 0 0">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"
x:Name="ResultCodeLabel"
Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=QuickAction.Result.ErrorInfo.ResultCode}"/>
<TextBlock Grid.Row="1"
x:Name="ErrorCodeLabel"
Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=QuickAction.Result.ErrorInfo.ErrorCode}" />
<TextBlock Grid.Row="2"
x:Name="ErrorDescrLabel"
Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=QuickAction.Result.ErrorInfo.ErrorDescription}" />
</Grid>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"
x:Name="ResultCodeText"
Margin="3 0 0 0"
Cursor="{DynamicResource Cursor.Copy}"
MouseLeftButtonUp="ValueTextBlock_Click"
TouchDown="ValueTextBlock_Click" />
<TextBlock Grid.Row="1"
x:Name="ErrorCodeText"
Margin="3 0 0 0"
Cursor="{DynamicResource Cursor.Copy}"
MouseLeftButtonUp="ValueTextBlock_Click"
TouchDown="ValueTextBlock_Click" />
<TextBlock Grid.Row="2"
x:Name="ErrorDescrText"
Margin="3 0 0 0"
Cursor="{DynamicResource Cursor.Copy}"
MouseLeftButtonUp="ValueTextBlock_Click"
TouchDown="ValueTextBlock_Click" />
</Grid>
</Grid>
</Grid>
</ScrollViewer>
</Border>
<Border Grid.Row="1"
Padding="7.5"
Background="{DynamicResource BackgroundColor.Menu.MainCategory}"
CornerRadius="10"
Margin="0 7.5 0 0">
<DockPanel>
<ico:AdaptableIcon DockPanel.Dock="Left"
x:Name="PartyPopperGif"
Visibility="Collapsed"
SelectedInternGif="partyPopper" />
<ScrollViewer HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<Grid x:Name="QuickActionResultGrid">
<Grid.Resources>
<Style TargetType="Border">
<Setter Property="Padding"
Value="5 0" />
</Style>
</Grid.Resources>
</Grid>
</ScrollViewer>
</DockPanel>
</Border>
</Grid>
</UserControl>

View File

@@ -0,0 +1,388 @@
using C4IT.FASD.Base;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using static C4IT.Logging.cLogManager;
using static FasdDesktopUi.Basics.UserControls.QuickActionStatusMonitor;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class QuickActionStatusMonitorResultElement : UserControl
{
private const string secretTag = "Secret";
private const string veiledTextTag = "ClearText";
public QuickActionStatusMonitorResultElement()
{
InitializeComponent();
}
public void SetQuickActionOutputData(cF4sdQuickActionRevision.cOutput output, cSupportCaseDataProvider dataProvider, cFasdQuickAction quickActionDefinition)
{
try
{
ResetQuickActionResultGrid();
if (output is null)
return;
if (output.ResultCode == enumQuickActionSuccess.successfull)
PartyPopperGif.Visibility = Visibility.Visible;
if (cQuickActionOutput.HasError(output))
SetErrorOutput(output);
else
QuickActionErrorContainer.Visibility = Visibility.Collapsed;
var quickActionOutput = cQuickActionOutput.GetQuickActionOutput(output, dataProvider);
switch (quickActionOutput)
{
case cQuickActionOutputSingle singleOutput:
SetSingleOutput(singleOutput, quickActionDefinition);
break;
case cQuickActionOutputList listOutput:
SetListOutput(listOutput, quickActionDefinition);
break;
case cQuickActionOutputObject objectOutput:
SetObjectOutput(objectOutput, quickActionDefinition);
break;
default:
break;
}
}
catch (Exception E)
{
LogException(E);
}
}
private void ResetQuickActionResultGrid()
{
QuickActionResultGrid.Children.Clear();
QuickActionResultGrid.RowDefinitions.Clear();
QuickActionResultGrid.ColumnDefinitions.Clear();
}
private void SetErrorOutput(cF4sdQuickActionRevision.cOutput output)
{
try
{
if (output is null)
return;
if (output.ResultCode != null
&& output.ResultCode.Value != enumQuickActionSuccess.unknown
&& output.ResultCode.Value != enumQuickActionSuccess.error)
{
ResultCodeLabel.Visibility = Visibility.Collapsed;
ResultCodeText.Visibility = Visibility.Collapsed;
}
else
{
ResultCodeLabel.Visibility = Visibility.Visible;
ResultCodeText.Visibility = Visibility.Visible;
ResultCodeText.Text = output?.ResultCode?.ToString();
}
if (output?.ErrorCode != null && output?.ErrorCode != 0)
{
ErrorCodeLabel.Visibility = Visibility.Visible;
ErrorCodeText.Visibility = Visibility.Visible;
var strErr = output?.ErrorCode?.ToString() ?? "";
var unsigned = (uint)(output.ErrorCode);
var strHex = unsigned.ToString("X");
strErr += " (0x" + strHex + ")";
ErrorCodeText.Text = strErr;
}
else
{
ErrorCodeLabel.Visibility = Visibility.Collapsed;
ErrorCodeText.Visibility = Visibility.Collapsed;
}
if (!string.IsNullOrEmpty(output?.ErrorDescription))
{
ErrorDescrLabel.Visibility = Visibility.Visible;
ErrorDescrText.Visibility = Visibility.Visible;
ErrorDescrText.Text = output?.ErrorDescription;
}
else
{
ErrorDescrLabel.Visibility = Visibility.Collapsed;
ErrorDescrText.Visibility = Visibility.Collapsed;
}
QuickActionErrorContainer.Visibility = Visibility.Visible;
}
catch (Exception ex)
{
LogException(ex);
}
}
private void SetSingleOutput(cQuickActionOutputSingle output, cFasdQuickAction quickActionDefinition)
{
try
{
if (output.Value is null)
return;
string displayValue = output.GetDisplayValue(quickActionDefinition.ColumnOutputFormattings);
var resultTextBlock = new TextBlock() { Text = !string.IsNullOrWhiteSpace(displayValue) ? displayValue : null };
resultTextBlock.SetResourceReference(Control.CursorProperty, "Cursor.Copy");
resultTextBlock.MouseLeftButtonUp += ValueTextBlock_Click;
resultTextBlock.TouchDown += ValueTextBlock_Click;
cColumnOutputFormatting formatting = null;
if (output.Key != null)
quickActionDefinition.ColumnOutputFormattings.TryGetValue(output.Key, out formatting);
formatting = formatting ?? quickActionDefinition.ColumnOutputFormattings?.Values?.FirstOrDefault();
if (formatting != null)
{
string displayValueSecret = output.GetDisplayValue(quickActionDefinition.ColumnOutputFormattings, true);
var resultTextBlockSecret = new TextBlock() { Text = !string.IsNullOrWhiteSpace(displayValueSecret) ? displayValueSecret : null, Visibility = Visibility.Collapsed, Tag = secretTag };
resultTextBlockSecret.SetResourceReference(Control.CursorProperty, "Cursor.Copy");
resultTextBlockSecret.MouseLeftButtonUp += ValueTextBlock_Click;
resultTextBlockSecret.TouchDown += ValueTextBlock_Click;
ReplaceClickSenderOf(resultTextBlock, resultTextBlockSecret);
resultTextBlock.Tag = veiledTextTag;
QuickActionResultGrid.Children.Add(resultTextBlockSecret);
}
QuickActionResultGrid.Children.Add(resultTextBlock);
}
catch (Exception ex)
{
LogException(ex);
}
}
private void SetListOutput(cQuickActionOutputList listOutput, cFasdQuickAction quickActionDefinition)
{
try
{
if (listOutput.Values is null || listOutput.Values.Count <= 0)
return;
var columnFormattings = quickActionDefinition.ColumnOutputFormattings;
List<KeyValuePair<string, object>> headingValues = listOutput.Values[0];
QuickActionResultGrid.RowDefinitions.Add(new RowDefinition());
for (int i = 0; i < headingValues.Count; i++)
{
QuickActionResultGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(0, GridUnitType.Auto) });
string columnKey = headingValues[i].Key;
if (cUtility.ShouldHideQuickActionOutput(columnKey, quickActionDefinition))
continue;
string displayValue = columnKey;
if (quickActionDefinition.ColumnOutputFormattings?.TryGetValue(columnKey, out var columnFormatting) ?? false)
displayValue = columnFormatting.Names.GetValue();
TextBlock headingTextBlock = new TextBlock() { Text = displayValue };
Border headingBorder = new Border() { Child = headingTextBlock };
Grid.SetRow(headingBorder, 0);
Grid.SetColumn(headingBorder, i);
QuickActionResultGrid.Children.Add(headingBorder);
}
for (int row = 0; row < listOutput.Values.Count; row++)
{
QuickActionResultGrid.RowDefinitions.Add(new RowDefinition());
for (int column = 0; column < listOutput.Values[row].Count; column++)
{
string columnKey = listOutput.Values[0][column].Key;
if (cUtility.ShouldHideQuickActionOutput(columnKey, quickActionDefinition))
continue;
string displayValue = listOutput.GetDisplayValue(row, column, columnFormattings);
if (string.IsNullOrEmpty(displayValue))
continue;
TextBlock valueTextBlock = new TextBlock { FontWeight = FontWeights.Normal, Text = displayValue };
valueTextBlock.SetResourceReference(Control.CursorProperty, "Cursor.Copy");
valueTextBlock.MouseLeftButtonUp += ValueTextBlock_Click;
valueTextBlock.TouchDown += ValueTextBlock_Click;
Border valueBorder = new Border() { Child = valueTextBlock };
Grid.SetRow(valueBorder, row + 1);
Grid.SetColumn(valueBorder, column);
bool hasSecretValue = columnFormattings?[columnKey]?.IsSecret ?? false;
if (hasSecretValue)
{
string displayValueSecret = listOutput.GetDisplayValue(row, column, columnFormattings, true);
TextBlock valueTextBlockSecret = new TextBlock { FontWeight = FontWeights.Normal, Text = displayValueSecret };
valueTextBlockSecret.SetResourceReference(Control.CursorProperty, "Cursor.Copy");
valueTextBlockSecret.MouseLeftButtonUp += ValueTextBlock_Click;
valueTextBlockSecret.TouchDown += ValueTextBlock_Click;
ReplaceClickSenderOf(valueTextBlock, valueTextBlockSecret);
Border valueBorderSecret = new Border() { Child = valueTextBlockSecret, Visibility = Visibility.Collapsed, Tag = secretTag };
valueBorder.Tag = veiledTextTag;
Grid.SetRow(valueBorderSecret, row + 1);
Grid.SetColumn(valueBorderSecret, column);
QuickActionResultGrid.Children.Add(valueBorderSecret);
}
QuickActionResultGrid.Children.Add(valueBorder);
}
}
}
catch (Exception ex)
{
LogException(ex);
}
}
private void SetObjectOutput(cQuickActionOutputObject objectOutput, cFasdQuickAction quickActionDefinition)
{
try
{
if (objectOutput.Values?.Count <= 0)
return;
QuickActionResultGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(0, GridUnitType.Auto) });
for (int i = 0; i < objectOutput.Values.Count; i++)
{
string columnKey = objectOutput.Values[i].Key;
// Has to be done, no matter if value should be hidden. Else the following Grid.SetRow's affect the wrong row.
QuickActionResultGrid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
if (cUtility.ShouldHideQuickActionOutput(columnKey, quickActionDefinition))
continue;
string displayValue = columnKey;
if (quickActionDefinition.ColumnOutputFormattings?.TryGetValue(columnKey, out var columnFormatting) ?? false)
displayValue = columnFormatting.Names.GetValue();
TextBlock headingTextBlock = new TextBlock() { Text = displayValue };
Border headingBorder = new Border() { Child = headingTextBlock };
Grid.SetColumn(headingBorder, 0);
Grid.SetRow(headingBorder, i);
QuickActionResultGrid.Children.Add(headingBorder);
}
QuickActionResultGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(0, GridUnitType.Auto) });
for (int i = 0; i < objectOutput.Values.Count; i++)
{
string columnKey = objectOutput.Values[i].Key;
if (cUtility.ShouldHideQuickActionOutput(columnKey, quickActionDefinition))
continue;
string displayValue = objectOutput.GetDisplayValue(i, quickActionDefinition.ColumnOutputFormattings);
if (string.IsNullOrWhiteSpace(displayValue))
continue;
TextBlock valueTextBlock = new TextBlock() { FontWeight = FontWeights.Normal, Text = displayValue };
valueTextBlock.SetResourceReference(Control.CursorProperty, "Cursor.Copy");
valueTextBlock.MouseLeftButtonUp += ValueTextBlock_Click;
valueTextBlock.TouchDown += ValueTextBlock_Click;
Border valueBorder = new Border() { Child = valueTextBlock };
Grid.SetRow(valueBorder, i);
Grid.SetColumn(valueBorder, 1);
QuickActionResultGrid.Children.Add(valueBorder);
if (quickActionDefinition.ColumnOutputFormattings is null || string.IsNullOrWhiteSpace(columnKey))
continue;
if (quickActionDefinition.ColumnOutputFormattings.TryGetValue(columnKey, out var formatting) && (formatting?.IsSecret ?? false))
{
string displayValueSecret = objectOutput.GetDisplayValue(i, quickActionDefinition.ColumnOutputFormattings, true);
TextBlock valueTextBlockSecret = new TextBlock() { FontWeight = FontWeights.Normal, Text = displayValueSecret };
valueTextBlockSecret.SetResourceReference(Control.CursorProperty, "Cursor.Copy");
valueTextBlockSecret.MouseLeftButtonUp += ValueTextBlock_Click;
valueTextBlockSecret.TouchDown += ValueTextBlock_Click;
ReplaceClickSenderOf(valueTextBlock, valueTextBlockSecret);
Border valueBorderSecret = new Border() { Child = valueTextBlockSecret, Visibility = Visibility.Collapsed, Tag = secretTag };
Grid.SetRow(valueBorderSecret, i);
Grid.SetColumn(valueBorderSecret, 1);
QuickActionResultGrid.Children.Add(valueBorderSecret);
valueBorder.Tag = veiledTextTag;
}
}
}
catch (Exception ex)
{
LogException(ex);
}
}
private void ValueTextBlock_Click(object sender, InputEventArgs e)
{
try
{
if (!(sender is TextBlock textBlock))
return;
System.Windows.Forms.Clipboard.SetText(textBlock.Text);
}
catch (Exception ex)
{
LogException(ex);
}
}
private void ReplaceClickSenderOf(UIElement from, UIElement to)
{
try
{
from.MouseLeftButtonUp -= ValueTextBlock_Click;
from.TouchDown -= ValueTextBlock_Click;
from.MouseLeftButtonUp += (s, e) => ValueTextBlock_Click(to, e);
from.TouchDown += (s, e) => ValueTextBlock_Click(to, e);
}
catch (Exception ex)
{
LogException(ex);
}
}
internal void ToggleSecretVisibility(bool secretsAreShown)
{
try
{
var taggedResultElements = QuickActionResultGrid.Children.OfType<FrameworkElement>().Where(element => element.Tag != null);
foreach (var resultElement in taggedResultElements)
{
if (resultElement.Tag.Equals(secretTag))
resultElement.Visibility = secretsAreShown ? Visibility.Visible : Visibility.Collapsed;
if (resultElement.Tag.Equals(veiledTextTag))
resultElement.Visibility = secretsAreShown ? Visibility.Collapsed : Visibility.Visible;
}
}
catch (Exception ex)
{
LogException(ex);
}
}
}
}

View File

@@ -0,0 +1,35 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.DontShowAgainDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800"
d:Background="White"
x:Name="DontShowAgainUc">
<UserControl.Resources>
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter" />
</UserControl.Resources>
<Border Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.TitleColumn}"
Padding="10"
CornerRadius="7.5">
<StackPanel>
<TextBlock Text="{Binding ElementName=DontShowAgainUc, Path=Text}"
Foreground="{DynamicResource FontColor.DetailsPage.DataHistory.ControlBar.Text}"
FontSize="16" />
<CheckBox x:Name="DontShowAgainCheck"
Margin="0 10 0 0"
IsChecked="{Binding ElementName=DontShowAgainUc, Path=IsChecked}"
Checked="DontShowAgainCheck_Checked"
Unchecked="DontShowAgainCheck_Unchecked"
Foreground="{DynamicResource FontColor.DetailsPage.DataHistory.ControlBar.Text}"
Content="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Global.Dialog.DontShowAgain}" />
</StackPanel>
</Border>
</UserControl>

View File

@@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
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.Navigation;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class DontShowAgainDialog : UserControl
{
#region Properties
#region Text
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(DontShowAgainDialog), new PropertyMetadata(string.Empty));
#endregion
#region IsChecked
public bool IsChecked
{
get { return (bool)GetValue(IsCheckedProperty); }
set { SetValue(IsCheckedProperty, value); }
}
public static readonly DependencyProperty IsCheckedProperty =
DependencyProperty.Register("IsChecked", typeof(bool), typeof(DontShowAgainDialog), new PropertyMetadata(false));
#endregion
#region IsCheckedChanged
public EventHandler<bool> IsCheckedChanged
{
get { return (EventHandler<bool>)GetValue(IsCheckedChangedProperty); }
set { SetValue(IsCheckedChangedProperty, value); }
}
public static readonly DependencyProperty IsCheckedChangedProperty =
DependencyProperty.Register("IsCheckedChanged", typeof(EventHandler<bool>), typeof(DontShowAgainDialog), new PropertyMetadata(null));
#endregion
#endregion
public DontShowAgainDialog()
{
InitializeComponent();
}
private void DontShowAgainCheck_Checked(object sender, RoutedEventArgs e)
{
try
{
if (IsCheckedChanged is null)
return;
IsCheckedChanged.Invoke(this, true);
}
catch (Exception E)
{
LogException(E);
}
}
private void DontShowAgainCheck_Unchecked(object sender, RoutedEventArgs e)
{
try
{
if (IsCheckedChanged is null)
return;
IsCheckedChanged.Invoke(this, false);
}
catch (Exception E)
{
LogException(E);
}
}
}
}

View File

@@ -0,0 +1,32 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.EditWidgetValueControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800">
<Grid x:Name="MainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Border x:Name="EditControlBorder" />
<ico:AdaptableIcon x:Name="EditButton"
Grid.Column="2"
MouseLeftButtonUp="EditButton_MouseLeftButtonUp"
TouchDown="EditButton_TouchDown"
SelectedMaterialIcon="ic_edit"
Style="{DynamicResource SettingsPage.Close.Icon}"
Margin="0"
BorderPadding="6.5"
IconWidth="28"
IconHeight="28"
VerticalAlignment="Center" />
</Grid>
</UserControl>

View File

@@ -0,0 +1,182 @@
using FasdDesktopUi.Basics.Models;
using System;
using System.Collections.Generic;
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.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class EditWidgetValueControl : UserControl, IFocusInvoker
{
#region Properties and fields
private object originalValue;
private bool isValueChanged = false;
private Action setFocus;
public int? ParentIndex { get; set; }
public UIElement ParentElement { get; set; }
#region EditableValueInformation
public cEditableValueInformationBase EditableValueInformation
{
get { return (cEditableValueInformationBase)GetValue(EditableValueInformationProperty); }
set { SetValue(EditableValueInformationProperty, value); }
}
public static readonly DependencyProperty EditableValueInformationProperty =
DependencyProperty.Register("EditableValueInformation", typeof(cEditableValueInformationBase), typeof(EditWidgetValueControl), new PropertyMetadata(null, new PropertyChangedCallback(EditableValueChanged)));
private static void EditableValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
try
{
if (!(d is EditWidgetValueControl _me))
return;
_me.originalValue = _me.EditableValueInformation.CurrentValue;
_me.UpdateEditControlBorder();
}
catch (Exception E)
{
LogException(E);
}
}
#endregion
#endregion
public EditWidgetValueControl()
{
InitializeComponent();
}
private void UpdateEditControlBorder()
{
try
{
switch (EditableValueInformation)
{
case cEditValueInformationSelection editSelectionInformation:
{
if (editSelectionInformation.SelectionValues is null || editSelectionInformation.SelectionValues?.Count <= 0)
return;
ComboBox editComboBox = new ComboBox();
foreach (var listValue in editSelectionInformation.SelectionValues)
{
ComboBoxItem tempComboBoxItem = new ComboBoxItem() { Content = listValue.Value, Tag = listValue.Key };
editComboBox.Items.Add(tempComboBoxItem);
}
var currentSelectedValue = editSelectionInformation.SelectionValues.FirstOrDefault(value => value.Key?.Equals(editSelectionInformation.CurrentValue) ?? false);
editComboBox.SelectedIndex = editSelectionInformation.SelectionValues.IndexOf(currentSelectedValue);
editComboBox.DropDownOpened += (sender, e) => cFocusInvoker.InvokeGotFocus(this, e);
editComboBox.DropDownClosed += (sender, e) => cFocusInvoker.InvokeLostFocus(this, e);
editComboBox.SelectionChanged += (sender, e) =>
{
if (editComboBox.SelectedItem is FrameworkElement selectedElement)
UpdateEditIcon(selectedElement.Tag);
};
EditControlBorder.Child = editComboBox;
EditButton.Visibility = Visibility.Collapsed;
}
break;
case cEditValueInformationText editTextInformation:
{
if (editTextInformation.CurrentValue is null)
return;
TextBox editTextBox = new TextBox() { Text = editTextInformation.CurrentValue.ToString() };
editTextBox.TextChanged += (sender, e) => UpdateEditIcon(editTextBox.Text);
EditButton.Visibility = Visibility.Visible;
EditControlBorder.Child = editTextBox;
setFocus = (() =>
{
editTextBox.Focus();
editTextBox.Select(0, editTextBox.Text.Length);
});
}
break;
default:
break;
}
}
catch (Exception E)
{
LogException(E);
}
}
private void UpdateEditIcon(object newValue)
{
try
{
if (originalValue is null || newValue is null)
return;
isValueChanged = originalValue.ToString().Equals(newValue.ToString(), StringComparison.InvariantCultureIgnoreCase) is false;
if (isValueChanged)
EditButton.SelectedMaterialIcon = MaterialIcons.MaterialIconType.ic_undo;
else
EditButton.SelectedMaterialIcon = MaterialIcons.MaterialIconType.ic_edit;
}
catch (Exception E)
{
LogException(E);
}
}
#region Evetns
#region EditButton_Click
private void EditButton_Click()
{
if (isValueChanged)
{
UpdateEditControlBorder();
UpdateEditIcon(originalValue);
}
else
{
setFocus?.Invoke();
}
}
private void EditButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
EditButton_Click();
}
private void EditButton_TouchDown(object sender, TouchEventArgs e)
{
EditButton_Click();
}
#endregion
#endregion
}
}

View File

@@ -0,0 +1,21 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.FunctionMarker"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:converter="clr-namespace:FasdDesktopUi.Basics.Converter"
mc:Ignorable="d"
d:DesignHeight="65"
d:DesignWidth="50"
x:Name="FunctionMarkerControl">
<Grid>
<ico:AdaptableIcon x:Name="FunctionDot"
Style="{DynamicResource Basic.FunctionMarker.Base}"
SelectedInternIcon="{Binding ElementName=FunctionMarkerControl, Path=SelectedIcon}" />
</Grid>
</UserControl>

View File

@@ -0,0 +1,187 @@
using FasdDesktopUi.Basics.Enums;
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 FasdDesktopUi.Basics.UserControls.AdaptableIcon;
using C4IT.FASD.Base;
using F4SD_AdaptableIcon.Enums;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class FunctionMarker : UserControl
{
public Brush PreviousColor;
public Brush FunctionMarkerColor;
public Style TitleFunctionMarkerStyle;
#region SelectedIcon
public static readonly DependencyProperty SelectedIconProperty =
DependencyProperty.Register("SelectedIcon", typeof(enumInternIcons), typeof(FunctionMarker), new PropertyMetadata(enumInternIcons.misc_dot));
public enumInternIcons SelectedIcon
{
get { return (enumInternIcons)GetValue(SelectedIconProperty); }
set { SetValue(SelectedIconProperty, value); }
}
#endregion
public FunctionMarker()
{
InitializeComponent();
FunctionMarkerColor = (SolidColorBrush)FindResource("Color.FunctionMarker");
TitleFunctionMarkerStyle = (Style)FindResource("Basic.FunctionMarker.Title");
}
public static FunctionMarker SetUpFunctionMarker(Panel parent, FunctionMarkerClick function, bool isTitleFunctionMarker = false, enumInternIcons selectedMarker = enumInternIcons.misc_dot)
{
FunctionMarker functionMarker = new FunctionMarker { Visibility = Visibility.Hidden, SelectedIcon = selectedMarker };
functionMarker.functionMarkerClick = function;
functionMarker.MouseUp += functionMarker.FunctionMarker_MouseUp;
functionMarker.TouchDown += functionMarker.FunctionMarker_TouchDown;
if (!isTitleFunctionMarker)
{
var siblingBorder = parent.Children.OfType<Border>().FirstOrDefault();
if (siblingBorder != null)
{
siblingBorder.Cursor = Cursors.Hand;
siblingBorder.MouseEnter += FunctionMarker_MouseEnter;
siblingBorder.MouseLeave += FunctionMarker_MouseLeave;
siblingBorder.MouseUp += functionMarker.FunctionMarker_MouseUp;
siblingBorder.TouchDown += functionMarker.FunctionMarker_TouchDown;
siblingBorder.Tag = functionMarker.Tag;
}
functionMarker.MouseEnter += FunctionMarker_MouseEnter;
functionMarker.MouseLeave += FunctionMarker_MouseLeave;
}
else
{
functionMarker.FunctionDot.Style = functionMarker.TitleFunctionMarkerStyle;
}
parent.Children.Insert(0, functionMarker);
return functionMarker;
}
#region Events
#region Click
public delegate void FunctionMarkerClick(object sender);
private FunctionMarkerClick functionMarkerClick;
private void FunctionMarker_Click(object sender)
{
if (sender is FunctionMarker clickedFunctionMarker)
{
if (functionMarkerClick != null)
{
functionMarkerClick.Invoke(clickedFunctionMarker);
return;
}
}
if (sender is FrameworkElement clickedFrameworkElement)
{
if (clickedFrameworkElement.Parent is Panel parentPanel)
{
var potentialFunctionMarker = parentPanel.Children.OfType<FunctionMarker>().FirstOrDefault();
if (potentialFunctionMarker != null)
{
if (functionMarkerClick != null)
functionMarkerClick.Invoke(potentialFunctionMarker);
}
}
}
}
private void FunctionMarker_MouseUp(object sender, MouseButtonEventArgs e)
{
FunctionMarker_Click(sender);
}
private void FunctionMarker_TouchDown(object sender, TouchEventArgs e)
{
FunctionMarker_Click(sender);
}
#endregion
#region Hover FunctionMarker
private static void FunctionMarker_MouseEnter(object sender, MouseEventArgs e)
{
if (sender is FunctionMarker functionMarker)
{
var parentStackPanel = (Panel)functionMarker.Parent;
var border = parentStackPanel.Children.OfType<Border>().FirstOrDefault();
if (border != null)
{
functionMarker.PreviousColor = border.Background;
border.Background = functionMarker.FunctionMarkerColor;
}
}
else if (sender is Border valueBorder)
{
if (valueBorder.Parent is Panel borderParentPanel)
{
var siblingFunctionMarker = borderParentPanel.Children.OfType<FunctionMarker>().FirstOrDefault();
if (siblingFunctionMarker.Visibility == Visibility.Visible)
{
siblingFunctionMarker.PreviousColor = valueBorder.Background;
valueBorder.Background = siblingFunctionMarker.PreviousColor == Brushes.Transparent ? Brushes.Transparent : siblingFunctionMarker.FunctionMarkerColor;
valueBorder.Cursor = siblingFunctionMarker.PreviousColor == Brushes.Transparent ? null : Cursors.Hand;
}
}
}
}
private static void FunctionMarker_MouseLeave(object sender, MouseEventArgs e)
{
if (sender is FunctionMarker functionMarker)
{
var parentStackPanel = (Panel)functionMarker.Parent;
var border = parentStackPanel.Children.OfType<Border>().FirstOrDefault();
if (border != null)
{
border.ClearValue(BackgroundProperty);
}
}
else if (sender is Border valueBorder)
{
valueBorder.ClearValue(BackgroundProperty);
valueBorder.ClearValue(CursorProperty);
}
}
#endregion
#endregion
}
}

View File

@@ -0,0 +1,32 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.LoadingDataIndicator"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
x:Name="LoadingDataIndicatorUc"
mc:Ignorable="d"
d:DesignHeight="12"
d:DesignWidth="800">
<UserControl.Resources>
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter" />
</UserControl.Resources>
<StackPanel Orientation="Horizontal">
<ico:AdaptableIcon BorderPadding="0"
VerticalAlignment="Center"
IconHeight="12"
IconWidth="12"
Margin="5 0 5 0"
SelectedInternGif="loadingSpinner" />
<TextBlock Style="{DynamicResource DetailsPage.DataHistory.ControlBar.Text}"
VerticalAlignment="Center"
Text="{Binding ElementName=LoadingDataIndicatorUc, Path=LoadingText}" />
</StackPanel>
</UserControl>

View File

@@ -0,0 +1,38 @@
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;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class LoadingDataIndicator : UserControl
{
#region Properties
public string LoadingText
{
get { return (string)GetValue(LoadingTextProperty); }
set { SetValue(LoadingTextProperty, value); }
}
public static readonly DependencyProperty LoadingTextProperty =
DependencyProperty.Register("LoadingText", typeof(string), typeof(LoadingDataIndicator), new PropertyMetadata(string.Empty));
#endregion
public LoadingDataIndicator()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,124 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.LoginMask"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
x:Name="LoginMaskUc"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Border Padding="10"
CornerRadius="10"
Background="{DynamicResource BackgroundColor.Menu.Categories}" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" MinWidth="300" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0"
Target="{Binding ElementName=UserNameInput}"
Content="Name :"/>
<TextBox x:Name="UserNameInput"
Text="{Binding ElementName=LoginMaskUc, Path=UserName}"
Grid.Row="0"
Grid.Column="1"
Background="Transparent"
BorderBrush="{StaticResource Color.SoftContrast}"
BorderThickness="0 0 0 1"
VerticalAlignment="Center"
Padding="3"/>
<Label Grid.Row="1"
Target="{Binding ElementName=PasswordInput}"
Content="Password: "/>
<PasswordBox x:Name="PasswordInput"
Grid.Row="1"
Grid.Column="1"
Background="Transparent"
BorderBrush="{StaticResource Color.SoftContrast}"
BorderThickness="0 0 0 1"
VerticalAlignment="Center"
Padding="3"/>
<TextBox x:Name="PasswordInputVisible"
Text="{Binding ElementName=PasswordInput, Path=Password, UpdateSourceTrigger=PropertyChanged}"
Grid.Row="1"
Grid.Column="1"
Background="Transparent"
BorderBrush="{StaticResource Color.SoftContrast}"
BorderThickness="0 0 0 1"
VerticalAlignment="Center"
Padding="3"
Visibility="Collapsed" />
<ico:AdaptableIcon x:Name="ShowPasswordIcon"
Grid.Row="1"
Grid.Column="1"
Style="{DynamicResource SettingsPage.Close.Icon}"
HorizontalAlignment="Right"
IconHeight="25"
IconWidth="25"
MouseLeftButtonUp="ShowPasswordIcon_MouseLeftButtonUp"
TouchDown="ShowPasswordIcon_TouchDown"
SelectedMaterialIcon="ic_remove_red_eye" />
<StackPanel Grid.Row="2"
Grid.ColumnSpan="3"
Orientation="Horizontal"
HorizontalAlignment="Center">
<StackPanel.Resources>
<Style TargetType="ico:AdaptableIcon">
<Setter Property="Cursor"
Value="Hand" />
<Setter Property="BorderPadding"
Value="2.5" />
<Setter Property="Margin"
Value="10" />
<EventSetter Event="MouseLeftButtonUp"
Handler="DialogButton_MouseLeftButtonUp" />
<EventSetter Event="TouchDown"
Handler="DialogButton_TouchDown" />
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="BorderPadding"
Value="0" />
</Trigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<ico:AdaptableIcon Tag="Confirm"
SecondaryIconColor="{StaticResource Color.Green}"
IconHeight="40"
IconWidth="40"
SelectedInternIcon="status_good" />
<ico:AdaptableIcon Tag="Cancle"
PrimaryIconColor="{StaticResource Color.Red}"
IconHeight="35"
IconWidth="35"
SelectedInternIcon="window_close" />
</StackPanel>
</Grid>
</Border>
</Grid>
</UserControl>

View File

@@ -0,0 +1,89 @@
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;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class LoginMask : UserControl
{
#region Properties
public string UserName { get; set; }
public string Password { get; set; }
#endregion
public LoginMask()
{
InitializeComponent();
}
#region ShowPasswordIcon_Click
private void ShowPasswordIcon_Click()
{
PasswordInputVisible.Visibility = PasswordInputVisible.Visibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;
PasswordInput.Visibility = PasswordInput.Visibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;
if (PasswordInputVisible.IsVisible)
PasswordInputVisible.Text = PasswordInput.Password;
}
private void ShowPasswordIcon_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
ShowPasswordIcon_Click();
}
private void ShowPasswordIcon_TouchDown(object sender, TouchEventArgs e)
{
ShowPasswordIcon_Click();
}
#endregion
#region DialogButton_Click
private void DialogButton_Click(object sender)
{
if (!(sender is FrameworkElement FE))
return;
switch (FE.Tag.ToString().ToLower())
{
case "cancle":
Visibility = Visibility.Collapsed;
break;
case "confirm":
break;
default:
break;
}
}
private void DialogButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
DialogButton_Click(sender);
}
private void DialogButton_TouchDown(object sender, TouchEventArgs e)
{
DialogButton_Click(sender);
}
#endregion
}
}

View File

@@ -0,0 +1,70 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.MenuBar"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
mc:Ignorable="d"
d:DesignHeight="350"
d:DesignWidth="800"
Height="Auto"
MinWidth="310"
Name="MenuBarUc"
Initialized="UserControl_Initialized">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisibility" />
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter" />
</UserControl.Resources>
<StackPanel>
<StackPanel x:Name="MenuBarStackPanel" x:FieldModifier="private"
Orientation="Horizontal"
HorizontalAlignment="Right">
<ico:AdaptableIcon x:Name="SearchButton" x:FieldModifier="private"
Style="{DynamicResource Menu.MenuBar.PinnedIcon}"
MouseUp="SearchButton_MouseUp"
TouchDown="SearchButton_TouchDown"
SelectedInternIcon="menuBar_search" />
<Grid>
<Border x:Name="NotepadNotificationBorder" x:FieldModifier="private"
Background="Transparent"
Panel.ZIndex="1"
IsHitTestVisible="False"
BorderBrush="{DynamicResource Background.Menu.Icon.Hover}"
CornerRadius="5"
BorderThickness="1"
Margin="2, -3, 2, -3"
Visibility="Collapsed">
<Ellipse Fill="{DynamicResource Color.Red}"
Width="15"
Height="15"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Margin="0,-4, -4,0"
IsHitTestVisible="False"/>
</Border>
<ico:AdaptableIcon x:Name="NotepadButton" x:FieldModifier="private"
Style="{DynamicResource Menu.MenuBar.PinnedIcon}"
MouseUp="NotepadButton_MouseUp"
TouchDown="NotepadButton_TouchDown"
SelectedMaterialIcon="ic_edit"
IsHitTestVisible="True"/>
</Grid>
<ico:AdaptableIcon x:Name="MoreButton" x:FieldModifier="private"
Style="{DynamicResource Menu.MenuBar.PinnedIcon.More}"
ToolTip="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Quickaction.More}"
MouseUp="MoreButton_MouseUp"
TouchDown="MoreButton_TouchDown" />
</StackPanel>
</StackPanel>
</UserControl>

View File

@@ -0,0 +1,329 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Linq;
using System.Threading.Tasks;
using F4SD_AdaptableIcon.Enums;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.UiActions;
using FasdDesktopUi.Pages;
using FasdDesktopUi.Pages.SearchPage;
using C4IT.FASD.Base;
using static C4IT.Logging.cLogManager;
using F4SD_AdaptableIcon;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class MenuBar : UserControl
{
#region Properties
#region PopUpIsVisible
internal static readonly DependencyPropertyKey PopUpIsVisibleKey = DependencyProperty.RegisterReadOnly("PopUpIsVisible", typeof(bool), typeof(MenuBar), new PropertyMetadata(false));
public static readonly DependencyProperty PopUpIsVisibleProperty = PopUpIsVisibleKey.DependencyProperty;
public bool PopUpIsVisible => (bool)GetValue(PopUpIsVisibleProperty);
#endregion
#region SearchBarIsVisible
private static void SearchBarIsVisibleChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is MenuBar _me && e.NewValue is bool searchBarIsVisible)
_me.SetValue(PopUpIsVisibleKey, searchBarIsVisible);
}
public static readonly DependencyProperty SearchBarIsVisibleProperty =
DependencyProperty.Register("SearchBarIsVisible", typeof(bool), typeof(MenuBar), new PropertyMetadata(false, new PropertyChangedCallback(SearchBarIsVisibleChangedCallback)));
public bool SearchBarIsVisible
{
get { return (bool)GetValue(SearchBarIsVisibleProperty); }
set { SetValue(SearchBarIsVisibleProperty, value); }
}
#endregion
#region MenubarItemData DependencyProperty
public static readonly DependencyProperty MenuBarItemDataProperty =
DependencyProperty.Register("MenuBarItemData", typeof(List<cMenuDataBase>), typeof(MenuBar), new PropertyMetadata(new List<cMenuDataBase>(), new PropertyChangedCallback(MenuBarChangedCallBack)));
private static void MenuBarChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is MenuBar _me)
{
_me.MenuBarStackPanel.Children.RemoveRange(2, _me.MenuBarStackPanel.Children.Count - 3);
_me.SetUpMenuBar();
}
}
public List<cMenuDataBase> MenuBarItemData
{
get { return (List<cMenuDataBase>)GetValue(MenuBarItemDataProperty); }
set { SetValue(MenuBarItemDataProperty, value); }
}
#endregion
public void SetSlimPage()
{
Dispatcher.Invoke(new Action(() =>
{
NotepadButton.Visibility = Visibility.Collapsed;
}));
}
public Action SearchButtonClickedAction { get; set; }
public Action MoreButtonClickedAction { get; set; }
#endregion
public MenuBar()
{
InitializeComponent();
}
private void SetUpMenuBar()
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
if (MenuBarItemData == null)
return;
var sortedMenuData = MenuBarItemData.OrderBy(x => x.IconPositionIndex).ToList();
for (int i = 0; i < sortedMenuData.Count; i++)
{
AdaptableIcon.AdaptableIcon menuIcon = new AdaptableIcon.AdaptableIcon() { Style = menuPinnedIconStyle };
IconData icon = sortedMenuData[i].MenuIcon;
if (icon.Intern != null)
menuIcon.SelectedInternIcon = icon.Intern;
else if(icon.Material != null)
menuIcon.SelectedMaterialIcon = icon.Material;
menuIcon.Tag = sortedMenuData[i];
string toolTipText = sortedMenuData[i].MenuText;
if (sortedMenuData[i].UiAction?.DisplayType != Enums.enumActionDisplayType.enabled)
{
menuIcon.Opacity = 0.5;
if (string.IsNullOrEmpty(sortedMenuData[i].UiAction?.AlternativeDescription) == false)
toolTipText += "\n" + sortedMenuData[i].UiAction?.AlternativeDescription;
menuIcon.Style = menuPinnedIconNoHoverStyle;
}
else
{
if (string.IsNullOrEmpty(sortedMenuData[i].UiAction?.Description) == false)
toolTipText += "\n" + sortedMenuData[i].UiAction?.Description;
menuIcon.MouseLeftButtonUp += MenuItem_MouseUp;
menuIcon.TouchDown += MenuItem_TouchDown;
}
menuIcon.ToolTip = toolTipText;
if (sortedMenuData[i].IconPositionIndex >= 0)
MenuBarStackPanel.Children.Insert(MenuBarStackPanel.Children.Count - 1, menuIcon);
}
if (cF4SDCockpitXmlConfig.Instance?.CopyTemplateConfig?.CopyTemplates.DefaultTemplate != null)
{
var copyIcon = new AdaptableIcon.AdaptableIcon()
{
Style = menuPinnedIconStyle,
SelectedInternIcon = enumInternIcons.menuBar_copy,
ToolTip = cF4SDCockpitXmlConfig.Instance?.CopyTemplateConfig?.CopyTemplates.DefaultTemplate.Descriptions.GetValue(Default: null),
};
copyIcon.Tag = new cMenuDataBase() { IconPositionIndex = 2, MenuIcon = new F4SD_AdaptableIcon.IconData(enumInternIcons.menuBar_copy), UiAction = new cUiCopyAction(cF4SDCockpitXmlConfig.Instance?.CopyTemplateConfig?.CopyTemplates.DefaultTemplate) };
copyIcon.MouseLeftButtonUp += MenuItem_MouseUp;
copyIcon.TouchDown += MenuItem_TouchDown;
MenuBarStackPanel.Children.Insert(2, copyIcon);
}
}
catch (Exception E)
{
LogException(E);
}
finally
{
LogMethodEnd(CM);
}
}
#region Styles
private Style menuPinnedIconStyle;
private Style menuPinnedIconNoHoverStyle;
private void SetStyles()
{
menuPinnedIconStyle = (Style)FindResource("Menu.MenuBar.PinnedIcon");
menuPinnedIconNoHoverStyle = (Style)FindResource("Menu.MenuBar.PinnedIcon.Base");
}
#endregion
#region Events
#region UserControl
private void UserControl_Initialized(object sender, EventArgs e)
{
SetStyles();
SearchBarIsVisible = false;
}
#endregion
#region MenuItem Click
private async Task MenuItem_ClickAsync(object sender)
{
if (!(sender is FrameworkElement FE))
return;
if (!(FE.Tag is cMenuDataBase MenuData))
return;
if (MenuData.UiAction == null)
return;
cUiActionBase.RaiseEvent(MenuData.UiAction, this, this);
if (MenuData.UiAction is cUiCopyAction && FE is AdaptableIcon.AdaptableIcon adaptableIcon)
await cUtility.ChangeIconToCheckAsync(adaptableIcon);
}
private async void MenuItem_TouchDown(object sender, TouchEventArgs e) => await MenuItem_ClickAsync(sender);
private async void MenuItem_MouseUp(object sender, MouseButtonEventArgs e) => await MenuItem_ClickAsync(sender);
#endregion
#region MoreButton Click
private void MoreButton_Click()
{
SearchBarIsVisible = false;
RaiseMoreQuickActionsButtonWasClickedEvent();
MoreButtonClickedAction?.Invoke();
}
private void MoreButton_MouseUp(object sender, MouseButtonEventArgs e)
{
MoreButton_Click();
}
private void MoreButton_TouchDown(object sender, TouchEventArgs e)
{
MoreButton_Click();
}
#endregion
#region SearchButton Click
private void SearchButton_Click()
{
try
{
if (SearchPageView.Instance.IsVisible)
SearchPageView.Instance.Hide();
else
SearchPageView.Instance.ActivateSearchView();
}
catch (Exception E)
{
LogException(E);
}
}
private void SearchButton_MouseUp(object sender, MouseButtonEventArgs e) => SearchButton_Click();
private void SearchButton_TouchDown(object sender, TouchEventArgs e) => SearchButton_Click();
#endregion
#region ChangedMenuPopUpStatus
public static readonly RoutedEvent MoreQuickActionsButtonWasClicked = EventManager.RegisterRoutedEvent("MoreQuickActionsButtonWasClickedEventHandler", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MenuBar));
public event RoutedEventHandler MoreQuickActionsButtonWasClickedEventHandler
{
add { AddHandler(MoreQuickActionsButtonWasClicked, value); }
remove { RemoveHandler(MoreQuickActionsButtonWasClicked, value); }
}
private void RaiseMoreQuickActionsButtonWasClickedEvent()
{
RoutedEventArgs newEventArgs = new RoutedEventArgs(MoreQuickActionsButtonWasClicked);
RaiseEvent(newEventArgs);
}
#endregion
#endregion
#region NotepadButton Click
private void NotepadButton_Click()
{
try
{
if (cFasdCockpitConfig.Instance.IsNotepadVisibleDocked == true)
{
return;
}
cUiActionBase.RaiseEvent(new cUiShowNotepadQuickAction(), this, this);
}
catch (Exception E)
{
LogException(E);
}
}
private void NotepadButton_TouchDown(object sender, TouchEventArgs e)
{
NotepadButton_Click();
}
private void NotepadButton_MouseUp(object sender, MouseButtonEventArgs e)
{
NotepadButton_Click();
}
#endregion
public void ChangeNotepadNotificationVisibility(bool visible)
{
if (visible)
NotepadNotificationBorder.Visibility = Visibility.Visible;
else
NotepadNotificationBorder.Visibility = Visibility.Collapsed;
}
}
}

View File

@@ -0,0 +1,91 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.MultiButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:uc="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
x:Name="MultiButtons"
mc:Ignorable="d"
>
<StackPanel Orientation="Horizontal" x:Name="ButtonPanel" x:FieldModifier="private" Grid.IsSharedSizeScope="True">
<StackPanel.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius"
Value="5"/>
<Setter Property="BorderThickness"
Value="0"/>
<Setter Property="Background"
Value="{DynamicResource Color.AppBackground}"/>
<Setter Property="Margin"
Value="10 0 10 0"/>
<Setter Property="Cursor"
Value="Hand"/>
<EventSetter Event="MouseLeftButtonUp"
Handler="DialogButton_MouseLeftButtonUp"/>
<EventSetter Event="TouchDown"
Handler="DialogButton_TouchDown"/>
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Background"
Value="{DynamicResource BackgroundColor.Menu.MainCategory}" />
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground"
Value="{DynamicResource FontColor.Menu.Categories}"/>
<Setter Property="HorizontalAlignment"
Value="Stretch"/>
<Setter Property="VerticalAlignment"
Value="Center"/>
<Setter Property="TextAlignment"
Value="Center"/>
<Setter Property="FontWeight"
Value="Bold"/>
<Setter Property="Padding"
Value="15 10 15 10"/>
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Foreground"
Value="{DynamicResource Color.FunctionMarker}"/>
</Trigger>
<Trigger Property="IsMouseOver"
Value="False">
<Setter Property="Foreground"
Value="{DynamicResource FontColor.Menu.Categories}"/>
</Trigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="ButtonStack"/>
</Grid.ColumnDefinitions>
<Border BorderBrush="Black">
<TextBlock Text="Abschließen &amp; dokumentieren"/>
</Border>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="ButtonStack"/>
</Grid.ColumnDefinitions>
<Border>
<TextBlock Text="Beenden ohne Dokumentation" />
</Border>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="ButtonStack"/>
</Grid.ColumnDefinitions>
<Border>
<TextBlock Text="Weiter bearbeiten" />
</Border>
</Grid>
</StackPanel>
</UserControl>

View File

@@ -0,0 +1,106 @@
using System;
using System.Collections.Generic;
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.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using C4IT.Logging;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
{
/// <summary>
/// Interaction logic for MultiButton.xaml
/// </summary>
public partial class MultiButton : UserControl
{
public int ResultIndex { get; private set; } = -1;
public event EventHandler<MultiButtonEventArgs> ResultChanged;
public MultiButton()
{
InitializeComponent();
}
private void DialogButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
DialogButton_Click(sender);
}
private void DialogButton_TouchDown(object sender, TouchEventArgs e)
{
DialogButton_Click(sender);
}
private void DialogButton_Click(object sender)
{
try
{
if (!(sender is FrameworkElement senderElement))
return;
if (!(senderElement.Tag is int resultIndex))
return;
ResultIndex = resultIndex;
ResultChanged(this, new MultiButtonEventArgs(resultIndex));
}
catch (Exception E)
{
LogException(E);
}
}
public void SetButtonText(List<string> ButtonTextList)
{
ButtonPanel.Children.Clear();
if (ButtonTextList == null)
return;
var resultIndex = 0;
foreach (var buttonText in ButtonTextList)
{
var _gd = new Grid();
ButtonPanel.Children.Add(_gd);
var _cd = new ColumnDefinition();
_cd.SharedSizeGroup = "ButtonStack";
_gd.ColumnDefinitions.Add(_cd);
var _bd = new Border();
_bd.Tag = resultIndex;
_gd.Children.Add(_bd);
var _tb = new TextBlock();
_tb.Text = buttonText;
_bd.Child = _tb;
resultIndex++;
}
}
}
public class MultiButtonEventArgs : RoutedEventArgs
{
public int ResultIndex { get; private set; } = -1;
public MultiButtonEventArgs(int resultIndex)
{
ResultIndex = resultIndex;
}
}
}

View File

@@ -0,0 +1,185 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.Notepad"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800"
d:Background="White"
MinHeight="225"
MinWidth="255"
x:Name="NotepadUc">
<UserControl.Resources>
<Style TargetType="ico:AdaptableIcon"
BasedOn="{StaticResource Menu.MenuBar.PinnedIcon }">
<Setter Property="CommandTarget"
Value="{Binding ElementName=NotepadRichTextBox}" />
<Setter Property="FocusManager.FocusedElement"
Value="{Binding ElementName=NotepadRichTextBox}" />
</Style>
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter" />
</UserControl.Resources>
<Border Padding="10"
CornerRadius="10"
Background="{DynamicResource BackgroundColor.Menu.Categories}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition x:Name="TopRow"
Height="Auto" />
<RowDefinition x:Name="BottomRow"
Height="*" />
</Grid.RowDefinitions>
<DockPanel>
<!--<DockPanel.Resources>
<Style TargetType="ico:AdaptableIcon">
<Setter Property="IconWidth"
Value="20" />
<Setter Property="IconHeight"
Value="20" />
<Setter Property="BorderPadding"
Value="5" />
<Setter Property="IconBackgroundColor"
Value="Transparent" />
<Setter Property="Margin"
Value="0, 0, 10, 0" />
<Setter Property="PrimaryIconColor"
Value="{DynamicResource Color.Menu.Icon}" />
<Setter Property="Cursor"
Value="Hand" />
<Setter Property="WindowChrome.IsHitTestVisibleInChrome"
Value="True" />
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="PrimaryIconColor"
Value="{DynamicResource Color.Menu.Icon.Hover}" />
<Setter Property="IconBackgroundColor"
Value="{DynamicResource Background.Menu.Icon.Hover}" />
</Trigger>
</Style.Triggers>
</Style>
</DockPanel.Resources>-->
<ico:AdaptableIcon x:Name="CloseNotepadIcon" x:FieldModifier="private"
DockPanel.Dock="Right"
SelectedInternIcon="window_minimize"
Style="{DynamicResource SettingsPage.Close.Icon}"
WindowChrome.IsHitTestVisibleInChrome ="True"
Margin="0 8 0 0"
Tag="close" MouseUp="CloseNotepadIcon_MouseUp" TouchDown="CloseNotepadIcon_TouchDown"/>
<ico:AdaptableIcon x:Name="LockNotepadIcon" x:FieldModifier="private"
DockPanel.Dock="Right"
Style="{DynamicResource Menu.Notepad.Icon.Lock}"
MouseLeave="LockNotepadIcon_MouseLeave"
WindowChrome.IsHitTestVisibleInChrome ="True"
Tag="lock" MouseUp="LockNotepadIcon_MouseUp" TouchDown="LockNotepadIcon_TouchDown"/>
<ico:AdaptableIcon DockPanel.Dock="Left"
VerticalAlignment="Center"
SelectedMaterialIcon="ic_edit"
PrimaryIconColor="{DynamicResource Color.FunctionMarker}"
BorderPadding="0"
IconHeight="15"
IconWidth="15"
Style="{x:Null}">
</ico:AdaptableIcon>
<TextBlock DockPanel.Dock="Left"
Style="{DynamicResource DetailsPage.DataHistory.TitleColumn.OverviewTitle}"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10"
Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Notepad.Heading.Notes}">
</TextBlock>
</DockPanel>
<DockPanel Grid.Row="2">
<Border DockPanel.Dock="Top"
Margin="0 0 0 10"
Background="{DynamicResource BackgroundColor.DetailsPage.Widget.Title}"
Padding="5"
CornerRadius="7.5">
<DockPanel>
<ico:AdaptableIcon x:Name="ToggleDockButton" x:FieldModifier="private"
DockPanel.Dock="Right"
SelectedMaterialIcon="ic_zoom_out_map"
MouseLeftButtonUp="ToggleDockButton_MouseLeftButtonUp"
TouchDown="ToggleDockButton_TouchDown" />
<StackPanel Orientation="Horizontal">
<ico:AdaptableIcon x:Name="UndoIcon" x:FieldModifier="private"
SelectedMaterialIcon="ic_undo"
Command="ApplicationCommands.Undo"
Style="{DynamicResource Menu.MenuBar.PinnedIcon.Disabled}"/>
<ico:AdaptableIcon x:Name="RedoIcon" x:FieldModifier="private"
SelectedMaterialIcon="ic_redo"
Command="ApplicationCommands.Redo"
Style="{DynamicResource Menu.MenuBar.PinnedIcon.Disabled}"/>
<ico:AdaptableIcon x:Name="CopyIcon"
SelectedInternIcon="menuBar_copy"
TouchDown="CopyIcon_TouchDown"
MouseLeftButtonUp="CopyIcon_MouseLeftButtonUp" />
<ico:AdaptableIcon x:Name="BoldIcon" x:FieldModifier="private"
SelectedMaterialIcon="ic_format_bold"
Command="EditingCommands.ToggleBold"
MouseLeftButtonUp="TextBoxIcon_MouseLeftButtonUp" />
<ico:AdaptableIcon x:Name="ItalicIcon" x:FieldModifier="private"
SelectedMaterialIcon="ic_format_italic"
Command="EditingCommands.ToggleItalic"
MouseLeftButtonUp="TextBoxIcon_MouseLeftButtonUp" />
<ico:AdaptableIcon x:Name="UnderlineIcon" x:FieldModifier="private"
SelectedMaterialIcon="ic_format_underlined"
Command="EditingCommands.ToggleUnderline"
MouseLeftButtonUp="TextBoxIcon_MouseLeftButtonUp" />
<ico:AdaptableIcon x:Name="BulletsIcon" x:FieldModifier="private"
SelectedMaterialIcon="ic_format_list_bulleted"
Command="EditingCommands.ToggleBullets"
MouseLeftButtonUp="TextBoxIcon_MouseLeftButtonUp" />
<ico:AdaptableIcon x:Name="NumberingIcon" x:FieldModifier="private"
SelectedMaterialIcon="ic_format_list_numbered"
Command="EditingCommands.ToggleNumbering"
MouseLeftButtonUp="TextBoxIcon_MouseLeftButtonUp" />
</StackPanel>
</DockPanel>
</Border>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<RichTextBox x:Name="NotepadRichTextBox" x:FieldModifier="private"
VerticalAlignment="Stretch"
Padding="2.5 5"
TextChanged="NotepadRichTextBox_TextChanged"
Foreground="{DynamicResource FontColor.DetailsPage.Widget}"
Background="{DynamicResource BackgroundColor.DetailsPage.Widget.Title}"
SelectionChanged="NotepadRichTextBox_SelectionChanged"
IsVisibleChanged="NotepadRichTextBox_IsVisibleChanged"
GotKeyboardFocus="NotepadRichTextBox_GotKeyboardFocus">
<RichTextBox.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius"
Value="7.5" />
</Style>
</RichTextBox.Resources>
</RichTextBox>
</ScrollViewer>
</DockPanel>
</Grid>
</Border>
</UserControl>

View File

@@ -0,0 +1,751 @@
using F4SD_AdaptableIcon.Enums;
using FasdDesktopUi.Basics.Helper;
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Threading;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class Notepad : UserControl
{
#region Variables
private bool IsBold = false;
private bool IsItalic = false;
private bool IsUnderline = false;
private bool IsDecimal = false;
private bool IsBullet = false;
private bool CanUndo = false;
private bool CanRedo = false;
#endregion
#region Properties and Fields
private static DispatcherTimer saveTimer;
public EventHandler<bool> LockStatusChanged { get; set; }
public EventHandler<bool> NotepadVisibilityChanged { get; set; }
public EventHandler<bool> IsUndockedChanged { get; set; }
#region DataProvider
private cSupportCaseDataProvider DataProvider;
/*
{
get { return (cDataProviderBase)GetValue(DataProviderProperty); }
set {
SetValue(DataProviderProperty, value);
}
}
*/
/*
private static readonly DependencyProperty DataProviderProperty =
DependencyProperty.Register("DataProvider", typeof(cDataProviderBase), typeof(Notepad), new PropertyMetadata(null));
*/
#endregion
#region IsUndocked
public bool IsUndocked
{
get { return (bool)GetValue(IsUndockedProperty); }
set { SetValue(IsUndockedProperty, value); }
}
public static readonly DependencyProperty IsUndockedProperty =
DependencyProperty.Register("IsUndocked", typeof(bool), typeof(Notepad), new PropertyMetadata(new PropertyChangedCallback(HandleUndockedChanged)));
private static void HandleUndockedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
try
{
if (!(d is Notepad _me))
return;
_me.ToggleIconVisibility();
}
catch (Exception E)
{
LogException(E);
}
}
#endregion
#region IsLocked
public bool IsLocked
{
get { return (bool)GetValue(IsLockedProperty); }
set { SetValue(IsLockedProperty, value); }
}
public static readonly DependencyProperty IsLockedProperty =
DependencyProperty.Register("IsLocked", typeof(bool), typeof(Notepad), new PropertyMetadata(new PropertyChangedCallback(HandleLockedChanged)));
private static void HandleLockedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
try
{
if (!(d is Notepad _me))
{
return;
}
_me.LockNotepadIcon.SelectedInternIcon = _me.IsLocked ? F4SD_AdaptableIcon.Enums.enumInternIcons.lock_closed : F4SD_AdaptableIcon.Enums.enumInternIcons.lock_open;
_me.CloseNotepadIcon.IsEnabled = _me.IsLocked ? false : true;
}
catch (Exception E)
{
LogException(E);
}
}
#endregion
#region IsTicketDialog
//public bool IsTicketDialog { get; set; }
public bool IsTicketDialog
{
get { return (bool)GetValue(IsTicketDialogProperty); }
set { SetValue(IsTicketDialogProperty, value); }
}
// Using a DependencyProperty as the backing store for IsTicketDialog. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsTicketDialogProperty =
DependencyProperty.Register("IsTicketDialog", typeof(bool), typeof(Notepad), new PropertyMetadata(new PropertyChangedCallback(HandleTicketDialogChanged)));
private static void HandleTicketDialogChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
try
{
if (!(d is Notepad _me))
{
return;
}
}
catch(Exception E)
{
LogException(E);
}
}
#endregion
#endregion
#region Constructor
public Notepad(cSupportCaseDataProvider dataProvider)
{
DataProvider = dataProvider;
InitializeComponent();
saveTimer = new DispatcherTimer(TimeSpan.FromSeconds(0.75), DispatcherPriority.Render, SaveNotes, Dispatcher.CurrentDispatcher);
IsLocked = cFasdCockpitConfig.Instance.IsNotepadVisibleDocked;
}
#endregion
#region Methods
private void NotepadRichTextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
try
{
if (DataProvider is null)
return;
if (DataProvider?.CaseNotes?.Parent is RichTextBox parentBox)
parentBox.Document = new FlowDocument();
if (!(sender is RichTextBox senderElement))
return;
senderElement.Document = DataProvider.CaseNotes;
senderElement.CaretPosition = senderElement.CaretPosition.DocumentEnd;
}
catch (Exception E)
{
LogException(E);
}
}
private async void NotepadRichTextBox_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
try
{
if (!(e.NewValue is bool isVisible && isVisible))
return;
await Task.Delay(50);
NotepadRichTextBox.Focus();
Keyboard.Focus(NotepadRichTextBox);
NotepadRichTextBox_GotKeyboardFocus(sender, null);
}
catch (Exception E)
{
LogException(E);
}
}
#region CopyIcon Click
private async void CopyIcon_Click(object sender)
{
try
{
DataObject copyObject = new DataObject();
StringBuilder stringBuilderUnicode = new StringBuilder();
cRichTextBoxHelper.TraverseBlockAsUnicode(NotepadRichTextBox.Document.Blocks, stringBuilderUnicode);
copyObject.SetData(DataFormats.UnicodeText, stringBuilderUnicode.ToString());
StringBuilder stringBuilderHtml = new StringBuilder();
cRichTextBoxHelper.TraverseBlockAsHtml(NotepadRichTextBox.Document.Blocks, stringBuilderHtml);
var copyText = cUtility.GetHtmlFrame(stringBuilderHtml.ToString());
copyObject.SetData(DataFormats.Html, copyText);
TextRange tr = new TextRange(NotepadRichTextBox.Document.ContentStart, NotepadRichTextBox.Document.ContentEnd);
using (MemoryStream ms = new MemoryStream())
{
tr.Save(ms, DataFormats.Rtf);
string rtfText = ASCIIEncoding.Default.GetString(ms.ToArray());
copyObject.SetData(DataFormats.Rtf, rtfText);
}
Clipboard.SetDataObject(copyObject);
await cUtility.ChangeIconToCheckAsync(CopyIcon);
}
catch (Exception E)
{
LogException(E);
}
}
private void CopyIcon_TouchDown(object sender, TouchEventArgs e)
{
CopyIcon_Click(sender);
}
private void CopyIcon_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
CopyIcon_Click(sender);
}
#endregion
#region Popout
private void ToggleDockButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
try
{
IsUndocked = !IsUndocked;
IsUndockedChanged?.Invoke(this, IsUndocked);
}
catch (Exception E)
{
LogException(E);
}
}
private void ToggleDockButton_TouchDown(object sender, TouchEventArgs e)
{
try
{
IsUndocked = !IsUndocked;
IsUndockedChanged?.Invoke(this, IsUndocked);
}
catch (Exception E)
{
LogException(E);
}
}
#endregion
#region Save Notes
private void SaveNotes(object sender, EventArgs e)
{
try
{
saveTimer?.Stop();
if (DataProvider is null)
return;
Dispatcher.Invoke(() => DataProvider.SaveCaseNotes());
}
catch (Exception E)
{
LogException(E);
}
}
private void NotepadRichTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
saveTimer?.Stop();
saveTimer?.Start();
CheckUndo_TextChanged(sender, e);
}
#endregion
#region RichTextBox SelectionChanged
private void NotepadRichTextBox_SelectionChanged(object sender, RoutedEventArgs e)
{
try
{
var selection = NotepadRichTextBox.Selection;
if (selection != null)
{
if ((FontWeight)selection.GetPropertyValue(TextElement.FontWeightProperty) == FontWeights.Bold)
{
if (IsBold == false)
{
SelectedTextIsBold(true);
IsBold = true;
}
}
else
{
if (IsBold == true)
{
SelectedTextIsBold(false);
IsBold = false;
}
}
if ((FontStyle)selection.GetPropertyValue(TextElement.FontStyleProperty) == FontStyles.Italic)
{
if (IsItalic == false)
{
SelectedTextIsItalic(true);
IsItalic = true;
}
}
else
{
if (IsItalic == true)
{
SelectedTextIsItalic(false);
IsItalic = false;
}
}
if ((TextDecorationCollection)selection.GetPropertyValue(Inline.TextDecorationsProperty) == TextDecorations.Underline)
{
if (IsUnderline == false)
{
SelectedTextIsUnderlined(true);
IsUnderline = true;
}
}
else
{
if (IsUnderline == true)
{
SelectedTextIsUnderlined(false);
IsUnderline = false;
}
}
if (selection.Start != null && selection.Start.Paragraph != null)
{
if (selection.Start.Paragraph.Parent is ListItem listItem)
{
if (listItem.List != null && listItem.List.MarkerStyle == TextMarkerStyle.Decimal)
{
if (IsDecimal == false)
{
SelectedTextIsDecimal(true);
IsDecimal = true;
}
}
else
{
if (IsDecimal == true)
{
SelectedTextIsDecimal(false);
IsDecimal = false;
}
}
}
else
{
if (IsDecimal == true)
{
SelectedTextIsDecimal(false);
IsDecimal = false;
}
}
}
if (selection.Start != null && selection.Start.Paragraph != null)
{
if (selection.Start.Paragraph.Parent is ListItem listItem)
{
if (listItem.List != null && listItem.List.MarkerStyle == TextMarkerStyle.Disc)
{
if (IsBullet == false)
{
SelectedTextIsDisc(true);
IsBullet = true;
}
}
else
{
if (IsBullet == true)
{
SelectedTextIsDisc(false);
IsBullet = false;
}
}
}
else
{
if (IsBullet == true)
{
SelectedTextIsDisc(false);
IsBullet = false;
}
}
}
}
}
catch (Exception E)
{
LogException(E);
}
}
private void SelectedTextIsBold(bool isActive)
{
try
{
if (isActive != true)
{
BoldIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon");
return;
}
BoldIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon.Pinned");
}
catch (Exception E)
{
LogException(E);
}
}
private void SelectedTextIsItalic(bool isActive)
{
try
{
if (isActive != true)
{
ItalicIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon");
return;
}
ItalicIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon.Pinned");
}
catch (Exception E)
{
LogException(E);
}
}
private void SelectedTextIsUnderlined(bool isActive)
{
try
{
if (isActive != true)
{
UnderlineIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon");
return;
}
UnderlineIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon.Pinned");
}
catch (Exception E)
{
LogException(E);
}
}
private void SelectedTextIsDecimal(bool isActive)
{
try
{
if (isActive != true)
{
NumberingIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon");
return;
}
NumberingIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon.Pinned");
}
catch (Exception E)
{
LogException(E);
}
}
private void SelectedTextIsDisc(bool isActive)
{
try
{
if (isActive != true)
{
BulletsIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon");
return;
}
BulletsIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon.Pinned");
}
catch (Exception E)
{
LogException(E);
}
}
private void TextBoxIcon_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
NotepadRichTextBox_SelectionChanged(sender, e);
}
#endregion
#region Undo/Redo
private void CheckUndo_TextChanged(object sender, TextChangedEventArgs e)
{
if (NotepadRichTextBox.CanUndo == true && CanUndo == false)
{
UndoIcon.IsEnabled = true;
UndoIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon");
CanUndo = true;
}
else if (NotepadRichTextBox.CanUndo == false && CanUndo == true)
{
UndoIcon.IsEnabled = false;
UndoIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon.Disabled");
CanUndo = false;
}
if (NotepadRichTextBox.CanRedo == true && CanRedo == false)
{
RedoIcon.IsEnabled = true;
RedoIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon");
CanRedo = true;
}
else if (NotepadRichTextBox.CanRedo == false && CanRedo == true)
{
RedoIcon.IsEnabled = false;
RedoIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon.Disabled");
CanRedo = false;
}
}
#endregion
#region Control Icons
#region Visibility
private void ToggleIconVisibility()
{
try
{
ToggleDockButton.Visibility = IsUndocked ? Visibility.Collapsed : Visibility.Visible;
LockNotepadIcon.Visibility = IsUndocked ? Visibility.Collapsed : Visibility.Visible;
CloseNotepadIcon.IsEnabled = IsUndocked ? true : !IsLocked;
}
catch (Exception E)
{
LogException(E);
}
}
#endregion
private void NotepadIcon_Click(object sender, InputEventArgs e)
{
try
{
if (!(sender is FrameworkElement senderElement))
return;
switch (senderElement.Tag)
{
case "lock":
LockNotepad();
break;
case "close":
CloseNotepad();
break;
default:
break;
}
}
catch (Exception E)
{
LogException(E);
}
}
private void CloseNotepadIcon_MouseUp(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
CloseNotepad();
}
private void CloseNotepadIcon_TouchDown(object sender, TouchEventArgs e)
{
CloseNotepad();
}
private void LockNotepad()
{
try
{
if (IsLocked)
{
LockNotepadIcon.SetResourceReference(AdaptableIcon.AdaptableIcon.PrimaryIconColorProperty, "Color.SoftContrast");
LockNotepadIcon.SelectedInternIcon = enumInternIcons.lock_open;
}
else
{
LockNotepadIcon.SetResourceReference(AdaptableIcon.AdaptableIcon.PrimaryIconColorProperty, "Color.Menu.Icon");
LockNotepadIcon.SelectedInternIcon = enumInternIcons.lock_closed;
}
LockNotepadIcon.BorderPadding = new Thickness(5.5);
IsLocked = !IsLocked;
LockStatusChanged?.Invoke(this, IsLocked);
}
catch (Exception E)
{
LogException(E);
}
}
private void LockNotepadIcon_MouseUp(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
LockNotepad();
}
private void LockNotepadIcon_TouchDown(object sender, TouchEventArgs e)
{
LockNotepad();
}
private void LockNotepadIcon_MouseLeave(object sender, MouseEventArgs e)
{
(sender as AdaptableIcon.AdaptableIcon).ClearValue(AdaptableIcon.AdaptableIcon.PrimaryIconColorProperty);
(sender as AdaptableIcon.AdaptableIcon).ClearValue(AdaptableIcon.AdaptableIcon.SelectedInternIconProperty);
(sender as AdaptableIcon.AdaptableIcon).ClearValue(AdaptableIcon.AdaptableIcon.BorderPaddingProperty);
}
private void CloseNotepad()
{
try
{
if (IsUndocked == true)
{
IsUndocked = !IsUndocked;
IsUndockedChanged?.Invoke(this, IsUndocked);
return;
}
NotepadVisibilityChanged?.Invoke(this, true);
}
catch (Exception E)
{
LogException(E);
}
}
#endregion
#endregion
}
}

View File

@@ -0,0 +1,96 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.PauseCaseOverlay"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
xmlns:wpfanimated="http://wpfanimatedgif.codeplex.com"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
mc:Ignorable="d" IsVisibleChanged="UserControl_IsVisibleChanged"
>
<UserControl.Resources>
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter" />
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0"
VerticalAlignment="Center"
HorizontalAlignment="Center" >
<Grid>
<Image Name="HeroGif"
Width="350"
Height="250"
Source="/Resources/F4SD_logo_reverse.gif"
wpfanimated:ImageBehavior.RepeatBehavior="0:0:1"
wpfanimated:ImageBehavior.AnimateInDesignMode="false"
wpfanimated:ImageBehavior.AutoStart="true"
wpfanimated:ImageBehavior.AnimationSpeedRatio="2"/>
</Grid>
<TextBlock Margin="40 -35 0 0"
FontSize="25"
FontWeight="Bold"
Foreground="{DynamicResource Color.Menu.Icon}"
HorizontalAlignment="Center"
Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=PausePage.Paused}"/>
</StackPanel>
<StackPanel Grid.Row="1"
Orientation="Horizontal"
HorizontalAlignment="Center"
Margin="35 0 0 0"
Cursor="Hand"
MouseLeftButtonUp="PlayButton_MouseLeftButtonUp" TouchDown="StackPanel_TouchDown"
>
<ico:AdaptableIcon IconHeight="50"
IconWidth="50"
SelectedMaterialIcon="ic_play_circle_filled"
IconBackgroundColor="Transparent">
<ico:AdaptableIcon.Resources>
<Style TargetType="ico:AdaptableIcon"
BasedOn="{StaticResource Menu.MenuBar.PinnedIcon.Pinned}">
<Setter Property="PrimaryIconColor"
Value="{DynamicResource FontColor.Menu.Categories}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorLevel=1, AncestorType=StackPanel}, Path=IsMouseOver}"
Value="True">
<Setter Property="PrimaryIconColor"
Value="{DynamicResource FontColor.Menu.Categories.Hover}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ico:AdaptableIcon.Resources>
</ico:AdaptableIcon>
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=PausePage.Continue}"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<TextBlock.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize"
Value="16"/>
<Setter Property="Foreground"
Value="{DynamicResource FontColor.Menu.Categories}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorLevel=1, AncestorType=StackPanel}, Path=IsMouseOver}"
Value="True">
<Setter Property="Foreground"
Value="{DynamicResource FontColor.Menu.Categories.Hover}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Resources>
</TextBlock>
</StackPanel>
</Grid>
</UserControl>

View File

@@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
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.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using C4IT.Logging;
using WpfAnimatedGif;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class PauseCaseOverlay : UserControl
{
public event EventHandler<EventArgs> OnPauseEnd;
public PauseCaseOverlay()
{
InitializeComponent();
}
private async void EndPause()
{
try
{
var imageSource = new BitmapImage();
imageSource.BeginInit();
imageSource.UriSource = new Uri("pack://application:,,,/Resources/F4SD_logo_forward.gif");
ImageBehavior.SetAnimatedSource(HeroGif, imageSource);
await Task.Delay(900);
if (OnPauseEnd != null)
OnPauseEnd?.Invoke(this, new EventArgs());
}
catch (Exception E)
{
LogException(E);
}
}
private void PlayButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
EndPause();
}
private void StackPanel_TouchDown(object sender, TouchEventArgs e)
{
EndPause();
}
private void UserControl_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (this.Visibility == Visibility.Visible)
{
var imageSource = new BitmapImage();
imageSource.BeginInit();
imageSource.UriSource = new Uri("pack://application:,,,/Resources/F4SD_logo_reverse.gif");
ImageBehavior.SetAnimatedSource(HeroGif, imageSource);
}
}
}
}

View File

@@ -0,0 +1,85 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.QuickActionSelector"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:converter="clr-namespace:FasdDesktopUi.Basics.Converter"
Name="QuickActionSelectorUc"
Visibility="Collapsed"
IsVisibleChanged="BlurInvoker_IsActiveChanged"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800">
<UserControl.Resources>
<converter:NullValueToVisibilityConverter x:Key="NullToVisibility" />
</UserControl.Resources>
<Border Padding="10"
CornerRadius="10"
Background="{DynamicResource BackgroundColor.Menu.Categories}">
<DockPanel>
<DockPanel DockPanel.Dock="Top">
<ico:AdaptableIcon x:Name="CloseButton"
DockPanel.Dock="Right"
Style="{DynamicResource SettingsPage.Close.Icon}"
MouseUp="CloseButton_MouseUp"
TouchDown="CloseButton_TouchDown"
SelectedInternIcon="window_close" />
<ico:AdaptableIcon x:Name="LockButton"
DockPanel.Dock="Right"
Style="{DynamicResource Menu.Selector.Icon.Lock}"
MouseUp="LockButton_MouseUp"
TouchDown="LockButton_TouchDown"
MouseLeave="LockButton_MouseLeave"/>
<ico:AdaptableIcon x:Name="BackButton"
DockPanel.Dock="Left"
Style="{DynamicResource SettingsPage.Close.Icon}"
Margin="-10 0 5 0"
BorderPadding="5"
MouseLeftButtonUp="BackButton_MouseLeftButtonUp"
TouchDown="BackButton_TouchDown"
HorizontalAlignment="Left"
SelectedMaterialIcon="ic_subdirectory_arrow_right"
Visibility="{Binding ElementName=QuickActionSelectorUc, Path=TempQuickActionList, Converter={StaticResource NullToVisibility}, UpdateSourceTrigger=PropertyChanged}">
<ico:AdaptableIcon.LayoutTransform>
<RotateTransform CenterX="0.5"
CenterY="0.5"
Angle="180" />
</ico:AdaptableIcon.LayoutTransform>
</ico:AdaptableIcon>
<ico:AdaptableIcon x:Name="SelectorTypeIcon"
DockPanel.Dock="Left"
VerticalAlignment="Center"
PrimaryIconColor="{DynamicResource Color.FunctionMarker}"
BorderPadding="0"
IconHeight="15"
IconWidth="15"
SelectedInternIcon="misc_functionBolt" />
<TextBlock Text="{Binding ElementName=QuickActionSelectorUc, Path=QuickActionSelectorHeading}"
DockPanel.Dock="Left"
Style="{DynamicResource DetailsPage.DataHistory.TitleColumn.OverviewTitle}"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10" />
</DockPanel>
<local:CustomMenu x:Name="SubMenuUc"
DockPanel.Dock="Top"
MenuDataList="{Binding ElementName=QuickActionSelectorUc, Path=QuickActionList}" />
</DockPanel>
</Border>
</UserControl>

View File

@@ -0,0 +1,234 @@
using System;
using System.Collections.Generic;
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.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using C4IT.FASD.Base;
using C4IT.Logging;
using F4SD_AdaptableIcon.Enums;
using FasdDesktopUi.Basics.Models;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class QuickActionSelector : UserControl, IBlurInvoker
{
#region Properties
public Action CloseButtonClickedAction { get; set; }
public Action<bool> LockStatusChanged { get; set; }
#region IsLocked DependencyProperty
public bool IsLocked
{
get { return (bool)GetValue(IsLockedProperty); }
set { SetValue(IsLockedProperty, value); }
}
public static readonly DependencyProperty IsLockedProperty =
DependencyProperty.Register("IsLocked", typeof(bool), typeof(QuickActionSelector), new PropertyMetadata(new PropertyChangedCallback(HandleLockedChanged)));
private static void HandleLockedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
try
{
if (!(d is QuickActionSelector _me))
{
return;
}
_me.CloseButton.IsEnabled = _me.IsLocked ? false : true;
}
catch (Exception E)
{
LogException(E);
}
}
#endregion
#region QuickActionSelectorHeading DependencyProperty
public static readonly DependencyProperty QuickActionSelectorHeadingProperty =
DependencyProperty.Register("QuickActionSelectorHeading", typeof(string), typeof(QuickActionSelector), new PropertyMetadata(null));
public string QuickActionSelectorHeading
{
get { return (string)GetValue(QuickActionSelectorHeadingProperty); }
set { SetValue(QuickActionSelectorHeadingProperty, value); }
}
#endregion
#region QuickActionList DependencyProperty
public static readonly DependencyProperty QuickActionListProperty =
DependencyProperty.Register("QuickActionList", typeof(List<cMenuDataBase>), typeof(QuickActionSelector), new PropertyMetadata(null));
public List<cMenuDataBase> QuickActionList
{
get { return (List<cMenuDataBase>)GetValue(QuickActionListProperty); }
set { SetValue(QuickActionListProperty, value); }
}
#endregion
#region TempQuickActionSelectorHeading Property
public string TempQuickActionSelectorHeading { get; set; }
#endregion
#region TempQuickActionList DependencyProperty
public static readonly DependencyProperty TempQuickActionListProperty =
DependencyProperty.Register("TempQuickActionList", typeof(List<cMenuDataBase>), typeof(QuickActionSelector), new PropertyMetadata(null));
public List<cMenuDataBase> TempQuickActionList
{
get { return (List<cMenuDataBase>)GetValue(TempQuickActionListProperty); }
set { SetValue(TempQuickActionListProperty, value); }
}
#endregion
#endregion
public QuickActionSelector()
{
InitializeComponent();
}
public void BlurInvoker_IsActiveChanged(object sender, DependencyPropertyChangedEventArgs e)
{
BlurInvoker.InvokeVisibilityChanged(this, new EventArgs());
}
public bool BlurInvoker_IsActive => IsVisible;
#region LockButton_Click
private void LockButton_MouseLeave(object sender, MouseEventArgs e)
{
try
{
(sender as AdaptableIcon.AdaptableIcon).ClearValue(AdaptableIcon.AdaptableIcon.PrimaryIconColorProperty);
(sender as AdaptableIcon.AdaptableIcon).ClearValue(AdaptableIcon.AdaptableIcon.SelectedInternIconProperty);
(sender as AdaptableIcon.AdaptableIcon).ClearValue(AdaptableIcon.AdaptableIcon.BorderPaddingProperty);
}
catch (Exception E)
{
LogException(E);
}
}
private void LockButton_Click(object sender)
{
try
{
if (sender is AdaptableIcon.AdaptableIcon senderIcon)
{
if (IsLocked)
{
senderIcon.SetResourceReference(AdaptableIcon.AdaptableIcon.PrimaryIconColorProperty, "Color.SoftContrast");
senderIcon.SelectedInternIcon = enumInternIcons.lock_open;
}
else
{
senderIcon.SetResourceReference(AdaptableIcon.AdaptableIcon.PrimaryIconColorProperty, "Color.Menu.Icon");
senderIcon.SelectedInternIcon = enumInternIcons.lock_closed;
}
senderIcon.BorderPadding = new Thickness(5.5);
}
IsLocked = !IsLocked;
LockStatusChanged?.Invoke(IsLocked);
}
catch (Exception E)
{
LogException(E);
}
}
private void LockButton_TouchDown(object sender, TouchEventArgs e)
{
LockButton_Click(sender);
}
private void LockButton_MouseUp(object sender, MouseButtonEventArgs e)
{
LockButton_Click(sender);
}
#endregion
#region CloseButton
private void CloseButton_Click()
{
try
{
if (IsLocked)
return;
QuickActionList = null;
Visibility = Visibility.Collapsed;
if (CloseButtonClickedAction != null)
CloseButtonClickedAction.Invoke();
}
catch (Exception E)
{
LogException(E);
}
}
private void CloseButton_TouchDown(object sender, TouchEventArgs e)
{
CloseButton_Click();
}
private void CloseButton_MouseUp(object sender, MouseButtonEventArgs e)
{
CloseButton_Click();
}
#endregion
#region BackButton
private void BackButton_Click()
{
QuickActionSelectorHeading = TempQuickActionSelectorHeading;
TempQuickActionSelectorHeading = null;
QuickActionList = TempQuickActionList;
TempQuickActionList = null;
}
private void BackButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
BackButton_Click();
}
private void BackButton_TouchDown(object sender, TouchEventArgs e)
{
BackButton_Click();
}
#endregion
}
}

View File

@@ -0,0 +1,131 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.QuickTip.QuickTipStatusMonitor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls.QuickTip"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:gif="http://wpfanimatedgif.codeplex.com"
xmlns:converter="clr-namespace:FasdDesktopUi.Basics.Converter"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="400"
MinWidth="400"
MinHeight="200"
IsVisibleChanged="QuickTipStatusMonitorUc_IsVisibleChanged"
x:Name="QuickTipStatusMonitorUc">
<UserControl.Resources>
<converter:LanguageDefinitionsConverter x:Key="LanguageConverter" />
<Style x:Key="BorderButtonWithText" TargetType="Border">
<Setter Property="CornerRadius" Value="5"/>
<Setter Property="Background" Value="{DynamicResource Color.AppBackground}"/>
<Setter Property="Height" Value="35"/>
<EventSetter Event="MouseEnter" Handler="ButtonBorder_MouseEnter"/>
<EventSetter Event="MouseLeave" Handler="ButtonBorder_MouseLeave"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{DynamicResource BackgroundColor.Menu.MainCategory}"/>
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<Border CornerRadius="10"
Padding="10"
Margin="0 0 0 10"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
VerticalAlignment="Top">
<DockPanel>
<DockPanel LastChildFill="False" DockPanel.Dock="Top">
<ico:AdaptableIcon
x:Name="HeadingIcon"
DockPanel.Dock="Left"
Style="{DynamicResource Menu.MenuBar.PinnedIcon.Base}"
VerticalAlignment="Center"
Margin="7.5 0 0 0"
BorderPadding="0"
IconHeight="15"
IconWidth="15"
SelectedInternIcon="{Binding QuickTipIcon.Intern, ElementName=QuickTipStatusMonitorUc}"
SelectedMaterialIcon="{Binding QuickTipIcon.Material, ElementName=QuickTipStatusMonitorUc}"/>
<TextBlock
x:Name="HeadingText"
Text="{Binding QuickTipName, ElementName=QuickTipStatusMonitorUc}"
DockPanel.Dock="Left"
Style="{DynamicResource DetailsPage.DataHistory.TitleColumn.OverviewTitle}"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10" />
</DockPanel>
<Grid Margin="0,5,0,0" DockPanel.Dock="Bottom">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="1.5*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="1.5*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border
x:Name="CompleteButton"
Grid.Column="1"
Style="{DynamicResource BorderButtonWithText}"
MouseLeftButtonUp="CompleteButton_Click"
TouchDown="CompleteButton_Click">
<TextBlock
Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=QuickTips.Complete}"
Style="{DynamicResource DetailsPage.DataHistory.TitleColumn.OverviewTitle}"
VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</Border>
<Border
x:Name="CancelButton"
Grid.Column="3"
Style="{DynamicResource BorderButtonWithText}"
MouseLeftButtonUp="CancelButton_Click"
TouchDown="CancelButton_Click">
<TextBlock
Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=QuickTips.Cancel}"
Style="{DynamicResource DetailsPage.DataHistory.TitleColumn.OverviewTitle}"
VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</Border>
</Grid>
<TextBlock
x:Name="StepCountTextBlock"
TextAlignment="Center"
Text="0 von 0 Schritten abgeschlossen"
Foreground="{DynamicResource FontColor.DetailsPage.DataHistory.Value}"
DockPanel.Dock="Bottom"/>
<ScrollViewer
x:Name="QuickTipElementViewer"
VerticalScrollBarVisibility="Auto"
DockPanel.Dock="Top">
<StackPanel
x:Name="QuickTipElementPanel">
</StackPanel>
</ScrollViewer>
</DockPanel>
</Border>
</UserControl>

View File

@@ -0,0 +1,363 @@
using C4IT.FASD.Base;
using C4IT.MultiLanguage;
using F4SD_AdaptableIcon;
using F4SD_AdaptableIcon.Enums;
using FasdDesktopUi.Basics.Enums;
using FasdDesktopUi.Basics.Services.ProtocollService;
using FasdDesktopUi.Pages.CustomMessageBox;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using static C4IT.Logging.cLogManager;
using static FasdDesktopUi.Basics.UiActions.cUiQuickTipAction;
namespace FasdDesktopUi.Basics.UserControls.QuickTip
{
public partial class QuickTipStatusMonitor : UserControl
{
#region Properties
#region QuickTipName
public string QuickTipName
{
get { return (string)GetValue(QuickTipNameProperty); }
set { SetValue(QuickTipNameProperty, value); }
}
// Using a DependencyProperty as the backing store for QuickTipName. This enables animation, styling, binding, etc...
public static readonly DependencyProperty QuickTipNameProperty =
DependencyProperty.Register("QuickTipName", typeof(string), typeof(QuickTipStatusMonitor), new PropertyMetadata("Quick Tip Name"));
#endregion
#region QuickTipIcon
public IconData QuickTipIcon
{
get { return (IconData)GetValue(QuickTipIconProperty); }
set { SetValue(QuickTipIconProperty, value); }
}
// Using a DependencyProperty as the backing store for QuickTipIcon. This enables animation, styling, binding, etc...
public static readonly DependencyProperty QuickTipIconProperty =
DependencyProperty.Register("QuickTipIcon", typeof(IconData), typeof(QuickTipStatusMonitor), new PropertyMetadata(new IconData(enumInternIcons.none)));
#endregion
#region QuickTipElementData
public List<cUiQuickTipElement> QuickTipElementData
{
get { return (List<cUiQuickTipElement>)GetValue(QuickTipElementDataProperty); }
set { SetValue(QuickTipElementDataProperty, value); }
}
// Using a DependencyProperty as the backing store for QuickTipElementData. This enables animation, styling, binding, etc...
public static readonly DependencyProperty QuickTipElementDataProperty =
DependencyProperty.Register("QuickTipElementData", typeof(List<cUiQuickTipElement>), typeof(QuickTipStatusMonitor), new PropertyMetadata(new List<cUiQuickTipElement>(), HandleQuickTipElementDataChanged));
private static void HandleQuickTipElementDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is QuickTipStatusMonitor quickTip)
{
quickTip.QuickTipElementPanel.Children.Clear();
quickTip._stepList.Clear();
quickTip._indexOfStepWithFocus = -1;
quickTip.FillElements();
}
}
#endregion
private readonly List<QuickTipStep> _stepList = new List<QuickTipStep>();
private int _indexOfStepWithFocus = -1;
#region StepCount
public enum enumQuickTipCompletionStatus
{
incomplete,
requiredComplete,
complete
}
private enumQuickTipCompletionStatus completionStatus = enumQuickTipCompletionStatus.incomplete;
private int stepsCompletedCount = 0;
#endregion
#region HasFocusIndex
public int HasFocusIndex
{
get { return (int)GetValue(HasFocusIndexProperty); }
set { SetValue(HasFocusIndexProperty, value); }
}
// Using a DependencyProperty as the backing store for HasFocusIndex. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HasFocusIndexProperty =
DependencyProperty.Register("HasFocusIndex", typeof(int), typeof(QuickTipStatusMonitor), new PropertyMetadata(0));
#endregion
#endregion
public QuickTipStatusMonitor()
{
InitializeComponent();
}
public void FillElements()
{
foreach (cUiQuickTipElement element in QuickTipElementData)
{
switch (element.ElementType)
{
case enumQuickTipElementType.Text:
TextBlock textBlock = new TextBlock
{
Text = element.TextBlock,
Margin = new Thickness(0, 0, 0, 5)
};
textBlock.SetResourceReference(TextBlock.ForegroundProperty, "FontColor.DetailsPage.DataHistory.Value");
QuickTipElementPanel.Children.Add(textBlock);
break;
case enumQuickTipElementType.Automated:
case enumQuickTipElementType.Manual:
QuickTipStep step = new QuickTipStep { StepData = element };
QuickTipElementPanel.Children.Add(step);
_stepList.Add(step);
step.RequestFocus += HandleStepRequestedFocus;
step.SuccessStateChanged += HandleSuccessStateChanged;
break;
default:
break;
}
}
SetStepCount();
}
private void SetStepCount()
{
int stepCount = _stepList.Count;
int stepsCompleted = _stepList.Count(step => step.SuccessState != enumQuickActionSuccess.unknown &&
(!(step.SuccessState == enumQuickActionSuccess.error && step.StepData.IsRequired)));
string stepCountText = cMultiLanguageSupport.GetItem("QuickTips.Control.StepCount");
stepCountText = string.Format(stepCountText, stepsCompleted, stepCount);
StepCountTextBlock.Text = stepCountText;
stepsCompletedCount = stepsCompleted;
CheckCompletionStatus();
}
private void CheckCompletionStatus()
{
if (stepsCompletedCount == 0)
{
completionStatus = enumQuickTipCompletionStatus.incomplete;
return;
}
else if (stepsCompletedCount == _stepList.Count)
{
completionStatus = enumQuickTipCompletionStatus.complete;
return;
}
foreach (QuickTipStep step in _stepList)
{
if (step.StepData.IsRequired && (step.SuccessState == enumQuickActionSuccess.unknown || step.SuccessState == enumQuickActionSuccess.error))
{
completionStatus = enumQuickTipCompletionStatus.incomplete;
return;
}
}
completionStatus = enumQuickTipCompletionStatus.requiredComplete;
}
public void UpdateAutomatedStepStatus(enumQuickActionRevisionStatus status, cFasdQuickAction quickAction)
{
try
{
var stepToUpdate = _stepList.FirstOrDefault(step => step.StepData.StepUiAction.Name == quickAction.Name);
if (stepToUpdate is null)
return;
switch (status)
{
case enumQuickActionRevisionStatus.unknown:
case enumQuickActionRevisionStatus.inProgress:
case enumQuickActionRevisionStatus.canceled:
stepToUpdate.SuccessState = enumQuickActionSuccess.unknown;
break;
case enumQuickActionRevisionStatus.finishedSuccessfull:
stepToUpdate.SuccessState = enumQuickActionSuccess.finished;
break;
case enumQuickActionRevisionStatus.finishedWithError:
stepToUpdate.SuccessState = enumQuickActionSuccess.error;
break;
}
}
catch (Exception E)
{
LogException(E);
}
}
private void HandleStepRequestedFocus(object sender, RoutedEventArgs e)
{
try
{
if (!(sender is QuickTipStep step))
return;
int indexOfSender = _stepList.IndexOf(step);
if (indexOfSender == _indexOfStepWithFocus)
return;
QuickTipStep currentlySelectedStep = _stepList.ElementAtOrDefault(_indexOfStepWithFocus);
if (currentlySelectedStep != null)
currentlySelectedStep.HasFocus = false;
_indexOfStepWithFocus = indexOfSender;
step.HasFocus = true;
}
catch (Exception E)
{
LogException(E);
}
}
private void HandleSuccessStateChanged(object sender, RoutedEventArgs e)
{
try
{
SetStepCount();
if (!(sender is QuickTipStep step))
return;
if (step.SuccessState == enumQuickActionSuccess.unknown || step.StepData.ElementType != enumQuickTipElementType.Manual)
return;
bool wasSuccessfull = step.SuccessState == enumQuickActionSuccess.finished || step.SuccessState == enumQuickActionSuccess.successfull;
F4SDProtocoll.Instance.Add(new QuickTipStepProtocollEntry(step.StepData.QuickTipElementDefinition, wasSuccessfull));
}
catch (Exception ex)
{
LogException(ex);
}
}
private void ButtonBorder_MouseEnter(object sender, MouseEventArgs e)
{
if (!(sender is Border border))
return;
if (!(border.Child is TextBlock textBlock))
return;
textBlock.SetResourceReference(Control.ForegroundProperty, "Color.FunctionMarker");
}
private void ButtonBorder_MouseLeave(object sender, MouseEventArgs e)
{
if (!(sender is Border border && border.Child is TextBlock textBlock))
return;
textBlock.SetResourceReference(Control.ForegroundProperty, "FontColor.DetailsPage.DataHistory.TitleColumn.OverviewTitle");
}
private void CompleteButton_Click(object sender, InputEventArgs e)
{
int finishedStepCount = _stepList.Count(step => step.SuccessState == enumQuickActionSuccess.finished);
switch (completionStatus)
{
case enumQuickTipCompletionStatus.incomplete:
HighlightRequiredButUndoneSteps();
break;
case enumQuickTipCompletionStatus.requiredComplete:
string completeDialogText = cMultiLanguageSupport.GetItem("QuickTips.Dialog.Complete");
completeDialogText = string.Format(completeDialogText, stepsCompletedCount, _stepList.Count);
var completeDialogResult = CustomMessageBox.Show(completeDialogText, "Quick Tip", enumHealthCardStateLevel.Warning, null, true);
if (completeDialogResult != true)
break;
AddQuickTipEndToProtocoll(QuickTipName, finishedStepCount, _stepList.Count, false);
ResetQuickTip();
break;
case enumQuickTipCompletionStatus.complete:
AddQuickTipEndToProtocoll(QuickTipName, finishedStepCount, _stepList.Count, false);
ResetQuickTip();
break;
}
}
private void HighlightRequiredButUndoneSteps()
{
QuickTipStep currentlySelectedStep = _stepList.ElementAtOrDefault(_indexOfStepWithFocus);
if (currentlySelectedStep != null)
currentlySelectedStep.HasFocus = false;
_indexOfStepWithFocus = -1;
foreach (QuickTipStep step in _stepList.Where(step => step.StepData.IsRequired))
{
if (step.SuccessState != enumQuickActionSuccess.successfull && step.SuccessState != enumQuickActionSuccess.finished)
step.HighlightAsRequired();
}
}
private void ResetQuickTip()
{
Visibility = Visibility.Collapsed;
QuickTipElementData = new List<cUiQuickTipElement>();
}
private void CancelButton_Click(object sender, InputEventArgs args) => CancelQuickTip();
private void CancelQuickTip()
{
if (_stepList.Any(step => step.SuccessState != enumQuickActionSuccess.unknown))
if (CustomMessageBox.Show(cMultiLanguageSupport.GetItem("QuickTips.Dialog.Cancel"), "Quick Tip", enumHealthCardStateLevel.Warning, null, true) != true)
return;
Visibility = Visibility.Collapsed;
int finishedStepCount = _stepList.Count(step => step.SuccessState == enumQuickActionSuccess.finished);
AddQuickTipEndToProtocoll(QuickTipName, finishedStepCount, _stepList.Count, true);
QuickTipElementData = new List<cUiQuickTipElement>();
}
private void AddQuickTipEndToProtocoll(string quickTipName, int finishedStepCount, int totalStepCount, bool wasCanceled)
{
string ascii = wasCanceled ? cMultiLanguageSupport.GetItem("QuickTips.Copy.Cancel") : cMultiLanguageSupport.GetItem("QuickTips.Copy.Finish");
ascii = string.Format(ascii, quickTipName, finishedStepCount, totalStepCount);
F4SDProtocoll.Instance.Add(new TextualProtocollEntry(ascii, ascii));
}
private void QuickTipStatusMonitorUc_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (!IsVisible)
return;
string ascii = cMultiLanguageSupport.GetItem("QuickTips.Copy.Start");
ascii = string.Format(ascii, QuickTipName);
F4SDProtocoll.Instance.Add(new TextualProtocollEntry(ascii, ascii));
}
}
}

View File

@@ -0,0 +1,167 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.QuickTip.QuickTipStep"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls.QuickTip"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:gif="http://wpfanimatedgif.codeplex.com"
xmlns:converter="clr-namespace:FasdDesktopUi.Basics.Converter"
mc:Ignorable="d"
d:DesignHeight="150" d:DesignWidth="380"
Cursor="Hand"
x:Name="StepUc">
<UserControl.Resources>
<converter:LanguageDefinitionsConverter x:Key="LanguageConverter" />
<Style x:Key="StatusIcon" TargetType="ico:AdaptableIcon">
<Setter Property="BorderPadding" Value="0"/>
<Setter Property="Margin" Value="0,-2"/>
<Setter Property="IconWidth" Value="20"/>
<Setter Property="IconHeight" Value="20"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="PrimaryIconColor" Value="{DynamicResource Color.Menu.Icon}"/>
<Setter Property="Opacity" Value="0.35"/>
<EventSetter Event="MouseLeftButtonUp" Handler="SelectStatus_MouseLeftButtonUp"/>
<EventSetter Event="TouchDown" Handler="SelectStatus_TouchDown"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="StepBorder" TargetType="Border">
<Setter Property="Background" Value="{DynamicResource BackgroundColor.Menu.MainCategory}"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{DynamicResource BackgroundColor.Menu.MainCategory.Hover}"/>
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<Border
x:Name="MainBorder"
x:FieldModifier="private"
Style="{DynamicResource StepBorder}"
BorderThickness="2"
CornerRadius="10"
Padding="8"
Margin="0 0 0 2.5"
MouseLeftButtonUp="MainBorder_MouseLeftButtonUp"
TouchDown="MainBorder_TouchDown"
MouseEnter="MainBorder_MouseEnter"
MouseLeave="MainBorder_MouseLeave">
<StackPanel>
<ico:AdaptableIcon
x:Name="RequiredIcon"
Margin=" 0 -10 -10 -5 "
BorderPadding="5"
IconHeight="15"
IconWidth="15"
HorizontalAlignment="Right"
SelectedInternIcon="misc_dot"
PrimaryIconColor="{DynamicResource HighlightColor.Red}"
Visibility="Hidden"
IsHitTestVisible="False"
ToolTip="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=QuickTips.Steps.Required}"/>
<DockPanel LastChildFill="False">
<ico:AdaptableIcon
x:Name="StepTypeIcon"
DockPanel.Dock="Right"
Style="{DynamicResource Menu.MenuBar.PinnedIcon.Base}"
VerticalAlignment="Center"
Margin=" 0 0 7.5 0 "
BorderPadding="0"
IconHeight="15"
IconWidth="15"
SelectedInternIcon="{Binding StepTypeIconData.Intern, ElementName=StepUc}"/>
<ico:AdaptableIcon
x:Name="HeadingIcon"
DockPanel.Dock="Left"
PrimaryIconColor="{DynamicResource Color.Menu.Icon}"
VerticalAlignment="Center"
Margin="7.5 0 0 0"
BorderPadding="0"
IconHeight="15"
IconWidth="15"
SelectedInternIcon="{Binding StepIcon.Intern, ElementName=StepUc}"
SelectedMaterialIcon="{Binding StepIcon.Material, ElementName=StepUc}"/>
<TextBlock
x:Name="HeadingText"
Text="{Binding StepData.ElementName, ElementName=StepUc}"
DockPanel.Dock="Left"
Style="{DynamicResource DetailsPage.DataHistory.TitleColumn.OverviewTitle}"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="5" />
</DockPanel>
<TextBlock
x:Name="DescriptionTextBlock"
Text="{Binding StepData.TextBlock, ElementName=StepUc}"
Foreground="{DynamicResource FontColor.DetailsPage.DataHistory.Value}"
FontFamily="Calibri"
FontSize="14"
FontWeight="Regular"
TextWrapping="Wrap"
VerticalAlignment="Top"
HorizontalAlignment="Left"/>
<Border
x:Name="StatusControl"
HorizontalAlignment="Right"
Width="70"
Height="20"
BorderBrush="{DynamicResource FontColor.Menu.Categories}"
BorderThickness="1"
CornerRadius="10"
IsHitTestVisible="False"
Margin="0,5,0,0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ico:AdaptableIcon x:Name="ErrorIcon"
Tag="Error"
Grid.Column="0"
SelectedMaterialIcon="ic_cancel"
HorizontalAlignment="Left"
Style="{DynamicResource StatusIcon}"
ToolTip="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=QuickTips.Steps.Failed}"/>
<ico:AdaptableIcon
x:Name="UnknownIcon"
Tag="Unknown"
Grid.Column="1"
SelectedMaterialIcon="ic_do_not_disturb_on"
HorizontalAlignment="Center"
Style="{DynamicResource StatusIcon}"
Opacity="1"
ToolTip="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=QuickTips.Steps.Unknown}" />
<ico:AdaptableIcon
x:Name="FinishedIcon"
Tag="Finished"
Grid.Column="2"
SelectedMaterialIcon="ic_check_circle"
HorizontalAlignment="Right"
Style="{DynamicResource StatusIcon}"
ToolTip="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=QuickTips.Steps.Succeeded}" />
</Grid>
</Border>
</StackPanel>
</Border>
</UserControl>

View File

@@ -0,0 +1,331 @@
using C4IT.FASD.Base;
using C4IT.MultiLanguage;
using F4SD_AdaptableIcon;
using F4SD_AdaptableIcon.Enums;
using FasdDesktopUi.Basics.Converter;
using FasdDesktopUi.Basics.UiActions;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using static FasdDesktopUi.Basics.UiActions.cUiQuickTipAction;
namespace FasdDesktopUi.Basics.UserControls.QuickTip
{
public partial class QuickTipStep : UserControl, INotifyPropertyChanged
{
#region Events
public event PropertyChangedEventHandler PropertyChanged;
#region RequestFocus
public static readonly RoutedEvent RequestFocusEvent = EventManager.RegisterRoutedEvent(
name: nameof(RequestFocus),
routingStrategy: RoutingStrategy.Bubble,
handlerType: typeof(RoutedEventHandler),
ownerType: typeof(QuickTipStep));
public event RoutedEventHandler RequestFocus
{
add { AddHandler(RequestFocusEvent, value); }
remove { RemoveHandler(RequestFocusEvent, value); }
}
#endregion
#region SuccessStateChanged
public static readonly RoutedEvent SuccessStateChangedEvent = EventManager.RegisterRoutedEvent(
name: nameof(SuccessStateChanged),
routingStrategy: RoutingStrategy.Bubble,
handlerType: typeof(RoutedEventHandler),
ownerType: typeof(QuickTipStep));
public event RoutedEventHandler SuccessStateChanged
{
add { AddHandler(SuccessStateChangedEvent, value); }
remove { RemoveHandler(SuccessStateChangedEvent, value); }
}
#endregion
#endregion
#region Properties
#region StepData
public cUiQuickTipElement StepData
{
get { return (cUiQuickTipElement)GetValue(StepDataProperty); }
set { SetValue(StepDataProperty, value); }
}
public static readonly DependencyProperty StepDataProperty =
DependencyProperty.Register("StepData", typeof(cUiQuickTipElement), typeof(QuickTipStep), new PropertyMetadata(null, HandleStepDataChanged));
private static void HandleStepDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is QuickTipStep step))
return;
step.UpdateStepIcon();
step.UpdateStepTypeIcon();
step.UpdateRequiredIcon();
}
private void UpdateStepIcon()
{
if (StepData.ElementType == Enums.enumQuickTipElementType.Automated)
{
if (!(StepData.StepUiAction is cUiQuickAction quickAction))
return;
StepIcon = IconDataConverter.Convert(quickAction.QuickActionConfig.Icon);
}
else if (StepData.ElementType == Enums.enumQuickTipElementType.Manual)
StepIcon = StepData.Icon;
}
private void UpdateStepTypeIcon()
{
if (StepData.ElementType == Enums.enumQuickTipElementType.Automated)
{
StepTypeIconData = new IconData(enumInternIcons.misc_functionBolt);
StepTypeIcon.ToolTip = cMultiLanguageSupport.GetItem("QuickTips.Steps.Automated");
}
else if (StepData.ElementType == Enums.enumQuickTipElementType.Manual)
{
StepTypeIconData = new IconData(enumInternIcons.misc_tool);
StepTypeIcon.ToolTip = cMultiLanguageSupport.GetItem("QuickTips.Steps.Manual");
}
}
private void UpdateRequiredIcon()
{
if (StepData.IsRequired && (SuccessState == enumQuickActionSuccess.error || SuccessState == enumQuickActionSuccess.unknown))
{
RequiredIcon.Visibility = Visibility.Visible;
RequiredIcon.IsHitTestVisible = true;
}
else
{
RequiredIcon.Visibility = Visibility.Hidden;
RequiredIcon.IsHitTestVisible = false;
}
}
#endregion
#region StepTypeIconData
private IconData _stepTypeIconData;
public IconData StepTypeIconData
{
get => _stepTypeIconData;
set
{
_stepTypeIconData = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(StepTypeIconData)));
}
}
#endregion
#region HasFocus
public bool HasFocus
{
get { return (bool)GetValue(HasFocusProperty); }
set { SetValue(HasFocusProperty, value); }
}
public static readonly DependencyProperty HasFocusProperty =
DependencyProperty.Register("HasFocus", typeof(bool), typeof(QuickTipStep), new PropertyMetadata(false, HandleHasFocusChanged));
private static void HandleHasFocusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is QuickTipStep step)
{
step.UpdateFocusBorder();
step.Cursor = step.HasFocus ? null : Cursors.Hand;
}
}
private void RunStepUiAction()
{
if (!HasFocus)
return;
cUiActionBase.RaiseEvent(StepData.StepUiAction, this, this);
}
private void UpdateFocusBorder()
{
if (HasFocus)
{
if (StepData.ElementType == Enums.enumQuickTipElementType.Manual)
StatusControl.IsHitTestVisible = true;
MainBorder.SetResourceReference(BorderBrushProperty, "Color.FunctionMarker");
}
else
{
StatusControl.IsHitTestVisible = false;
MainBorder.SetResourceReference(BorderBrushProperty, "BackgroundColor.DetailsPage.DataHistory.TitleColumn");
}
}
public void HighlightAsRequired() => MainBorder.SetResourceReference(BorderBrushProperty, "Color.Red");
#endregion
#region StepIcon
public IconData StepIcon
{
get { return (IconData)GetValue(StepIconProperty); }
set { SetValue(StepIconProperty, value); }
}
public static readonly DependencyProperty StepIconProperty =
DependencyProperty.Register("StepIcon", typeof(IconData), typeof(QuickTipStep), new PropertyMetadata(new IconData(enumInternIcons.misc_dot)));
#endregion
#region SuccessState
public enumQuickActionSuccess SuccessState
{
get { return (enumQuickActionSuccess)GetValue(SuccessStateProperty); }
set { SetValue(SuccessStateProperty, value); }
}
public static readonly DependencyProperty SuccessStateProperty =
DependencyProperty.Register("SuccessState", typeof(enumQuickActionSuccess), typeof(QuickTipStep), new PropertyMetadata(enumQuickActionSuccess.unknown, HandleSuccessStateChanged));
private static void HandleSuccessStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is QuickTipStep step))
return;
step.UpdateStatusControl();
}
private void UpdateStatusControl()
{
ErrorIcon.SetResourceReference(AdaptableIcon.AdaptableIcon.PrimaryIconColorProperty, "Color.Menu.Icon");
UnknownIcon.SetResourceReference(AdaptableIcon.AdaptableIcon.PrimaryIconColorProperty, "Color.Menu.Icon");
FinishedIcon.SetResourceReference(AdaptableIcon.AdaptableIcon.PrimaryIconColorProperty, "Color.Menu.Icon");
ErrorIcon.Opacity = 0.35;
UnknownIcon.Opacity = 0.35;
FinishedIcon.Opacity = 0.35;
switch (SuccessState)
{
case enumQuickActionSuccess.error:
ErrorIcon.SetResourceReference(AdaptableIcon.AdaptableIcon.PrimaryIconColorProperty, "HighlightColor.Red");
ErrorIcon.Opacity = 1;
break;
case enumQuickActionSuccess.unknown:
UnknownIcon.SetResourceReference(AdaptableIcon.AdaptableIcon.PrimaryIconColorProperty, "Color.Menu.Icon");
UnknownIcon.Opacity = 1;
break;
case enumQuickActionSuccess.finished:
case enumQuickActionSuccess.successfull:
FinishedIcon.SetResourceReference(AdaptableIcon.AdaptableIcon.PrimaryIconColorProperty, "HighlightColor.Green");
FinishedIcon.Opacity = 1;
break;
default:
break;
}
UpdateStepCount();
UpdateRequiredIcon();
}
#endregion
#endregion
public QuickTipStep()
{
InitializeComponent();
}
private void MainBorder_TouchDown(object sender, TouchEventArgs e)
{
SetFocusForStep();
RunStepUiAction();
}
private void MainBorder_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
SetFocusForStep();
RunStepUiAction();
}
private void SetFocusForStep()
{
if (HasFocus)
return;
RoutedEventArgs eventArgs = new RoutedEventArgs(routedEvent: RequestFocusEvent);
RaiseEvent(eventArgs);
}
private void UpdateStepCount()
{
RoutedEventArgs eventArgs = new RoutedEventArgs(routedEvent: SuccessStateChangedEvent);
RaiseEvent(eventArgs);
}
private void SelectStatus_TouchDown(object sender, TouchEventArgs e)
{
SetSuccessState(sender);
}
private void SelectStatus_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
SetSuccessState(sender);
}
private void SetSuccessState(object sender)
{
if (!(StepData.ElementType == Enums.enumQuickTipElementType.Manual))
return;
if (!(sender is FrameworkElement frameworkElement))
return;
switch (frameworkElement.Tag)
{
case "Error":
SuccessState = enumQuickActionSuccess.error;
break;
case "Unknown":
SuccessState = enumQuickActionSuccess.unknown;
break;
case "Finished":
SuccessState = enumQuickActionSuccess.finished;
break;
default:
return;
}
}
private void MainBorder_MouseEnter(object sender, MouseEventArgs e)
{
HeadingIcon.SetResourceReference(AdaptableIcon.AdaptableIcon.PrimaryIconColorProperty, "Color.Menu.Icon.Hover");
}
private void MainBorder_MouseLeave(object sender, MouseEventArgs e)
{
HeadingIcon.SetResourceReference(AdaptableIcon.AdaptableIcon.PrimaryIconColorProperty, "Color.Menu.Icon");
}
}
}

View File

@@ -0,0 +1,133 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.SearchBar"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800"
Name="_this"
IsVisibleChanged="BlurInvoker_IsActiveChanged"
Loaded="SearchBar_Loaded">
<UserControl.Resources>
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter" />
</UserControl.Resources>
<Border Background="{DynamicResource BackgroundColor.Menu.Categories}"
CornerRadius="17.5"
Margin="-2.5"
Padding="2.5"
VerticalAlignment="Bottom"
x:Name="BackgroundBorder"
x:FieldModifier="private">
<DockPanel>
<ico:AdaptableIcon x:Name="SearchButton"
x:FieldModifier="private"
DockPanel.Dock="Left"
Style="{DynamicResource Menu.MenuBar.PinnedIcon}"
MouseUp="SearchButton_Click"
TouchDown="SearchButton_Click"
IconBackgroundColor="Transparent"
IconHeight="{Binding SearchButtonSize, RelativeSource={RelativeSource AncestorType=UserControl}}"
IconWidth="{Binding SearchButtonSize, RelativeSource={RelativeSource AncestorType=UserControl}}"
SelectedInternIcon="menuBar_search" />
<ico:AdaptableIcon x:Name="PhoneCallIndicator"
x:FieldModifier="private"
DockPanel.Dock="Left"
Style="{DynamicResource Menu.MenuBar.PinnedIcon}"
IconBackgroundColor="Transparent"
Visibility="Collapsed"
SelectedMaterialIcon="ic_phone" />
<ico:AdaptableIcon x:Name="ComputerCallIndicator"
x:FieldModifier="private"
DockPanel.Dock="Left"
Style="{DynamicResource Menu.MenuBar.PinnedIcon}"
IconBackgroundColor="Transparent"
Visibility="Collapsed"
SelectedInternIcon="misc_computer" />
<ico:AdaptableIcon x:Name="UserCallIndicator"
x:FieldModifier="private"
DockPanel.Dock="Left"
Style="{DynamicResource Menu.MenuBar.PinnedIcon}"
IconBackgroundColor="Transparent"
Visibility="Collapsed"
SelectedInternIcon="misc_user" />
<ico:AdaptableIcon x:Name="WarningIndicator"
x:FieldModifier="private"
DockPanel.Dock="Left"
Style="{DynamicResource Menu.MenuBar.PinnedIcon}"
IconBackgroundColor="Transparent"
PrimaryIconColor="#FFFF8800"
Visibility="Collapsed"
SelectedInternIcon="status_bad" />
<Grid DockPanel.Dock="Left">
<TextBlock IsHitTestVisible="False"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="9 0 0 0"
Foreground="{DynamicResource FontColor.DetailsPage.DataHistory.Date}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Text, ElementName=SearchTextBox}"
Value="">
<Setter Property="Text"
Value="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Searchbar.Placeholder.UserName}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBox x:Name="SearchTextBox"
x:FieldModifier="private"
Text="{Binding ElementName=_this, Path=SearchValue, UpdateSourceTrigger=PropertyChanged, Mode=OneWayToSource}"
Style="{DynamicResource SearchBar.TextBox}" />
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Right"
VerticalAlignment="Center">
<ico:AdaptableIcon x:Name="SearchSpinner"
x:FieldModifier="private"
Visibility="Hidden"
Margin="5 0 0 0"
Padding="0"
SelectedInternGif="loadingSpinner"
RenderTransformOrigin="0.5,0.5">
<ico:AdaptableIcon.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform Angle="90" />
<TranslateTransform />
</TransformGroup>
</ico:AdaptableIcon.RenderTransform>
</ico:AdaptableIcon>
<ico:AdaptableIcon x:Name="CloseButton"
x:FieldModifier="private"
Style="{DynamicResource SettingsPage.Close.Icon}"
IconHeight="{Binding CloseButtonSize, RelativeSource={RelativeSource AncestorType=UserControl}}"
IconWidth="{Binding CloseButtonSize, RelativeSource={RelativeSource AncestorType=UserControl}}"
Margin="-3 0 0 0"
Padding="0"
ToolTip="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Global.NavBar.Close}"
MouseUp="CloseButton_Click"
TouchDown="CloseButton_Click"
SelectedInternIcon="window_close" />
</StackPanel>
</Grid>
</DockPanel>
</Border>
</UserControl>

View File

@@ -0,0 +1,362 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;
using FasdDesktopUi.Basics.Models;
using C4IT.FASD.Cockpit.Communication;
using C4IT.Logging;
using static C4IT.Logging.cLogManager;
using C4IT.MultiLanguage;
using C4IT.FASD.Base;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class SearchBar : UserControl, IBlurInvoker
{
private const int constTimeBetweenKeystrokes = 250;
#region Propeties
public enum eSearchStatus { message, active, fixedResult };
public eSearchStatus SearchStatus { get; private set; } = eSearchStatus.message;
#region Search Value Property
private readonly DispatcherTimer _searchTimer = new DispatcherTimer();
private static CancellationTokenSource _currentSearchTaskToken = null;
private static Guid? _currentSearchTaskId = null;
private static readonly object _currentSearchTaskLock = new object();
private string _searchValue = null;
public string SearchValue
{
get => _searchValue;
set
{
if (value != _searchValue)
{
_searchValue = value;
if (SearchStatus == eSearchStatus.active)
HandleSearchValueChanged();
}
}
}
private readonly Dictionary<enumF4sdSearchResultClass, UIElement> _searchIcons = null;
#endregion
public event EventHandler<string> SearchValueChanged;
public delegate Task ChangedSearchValueDelegate(cFilteredResults results);
public ChangedSearchValueDelegate ChangedSearchValue { get; set; } = null;
public Action CancledSearchAction { get; set; }
public bool BlurInvoker_IsActive => IsVisible;
#endregion
#region Dependency Propertys
public double SearchButtonSize
{
get { return (double)GetValue(SearchButtonSizeProperty); }
set { SetValue(SearchButtonSizeProperty, value); }
}
public static readonly DependencyProperty SearchButtonSizeProperty =
DependencyProperty.Register("SearchButtonSize", typeof(double), typeof(SearchBar), new PropertyMetadata(30.0));
public double CloseButtonSize
{
get { return (double)GetValue(CloseButtonSizeProperty); }
set { SetValue(CloseButtonSizeProperty, value); }
}
public static readonly DependencyProperty CloseButtonSizeProperty =
DependencyProperty.Register("CloseButtonSize", typeof(double), typeof(SearchBar), new PropertyMetadata(30.0));
#endregion
public SearchBar()
{
InitializeComponent();
_searchIcons = new Dictionary<enumF4sdSearchResultClass, UIElement>()
{
{ enumF4sdSearchResultClass.Phone, PhoneCallIndicator },
{ enumF4sdSearchResultClass.User, UserCallIndicator },
{ enumF4sdSearchResultClass.Computer, ComputerCallIndicator }
};
}
public void BlurInvoker_IsActiveChanged(object sender, DependencyPropertyChangedEventArgs e)
{
BlurInvoker.InvokeVisibilityChanged(this, new EventArgs());
if (e.NewValue is bool newVisible)
{
if (newVisible == false)
{
SearchTextBox.IsEnabled = true;
SearchButton.Visibility = Visibility.Visible;
WarningIndicator.Visibility = Visibility.Collapsed;
TicketOverview.Instance?.ResetSelection();
foreach (var Entry in _searchIcons.Values)
Entry.Visibility = Visibility.Collapsed;
}
SetApiStatus();
}
if (Visibility == Visibility.Visible)
{
var _h = Dispatcher.BeginInvoke((Action)delegate { Keyboard.Focus(SearchTextBox); }, DispatcherPriority.Render);
}
}
public void Clear()
{
SearchStatus = eSearchStatus.message;
SearchTextBox.Text = null;
}
public void ActivateManualSearch()
{
SearchStatus = eSearchStatus.active;
SearchButton.Visibility = Visibility.Visible;
WarningIndicator.Visibility = Visibility.Collapsed;
foreach (var Entry in _searchIcons.Values)
Entry.Visibility = Visibility.Collapsed;
SearchTextBox.Text = null;
SearchTextBox.IsEnabled = true;
SearchTextBox.Focus();
Keyboard.Focus(SearchTextBox);
}
public void SetSearchText(string search)
{
SearchStatus = eSearchStatus.active;
SearchTextBox.Text = search;
SearchTextBox.CaretIndex = search.Length;
SearchTextBox.Focus();
Keyboard.Focus(SearchTextBox);
}
internal void SetSpinnerVisibility(Visibility visibility)
{
Dispatcher.Invoke(() => SearchSpinner.Visibility = visibility);
}
public async Task SetFixedSearchResultAsync(enumF4sdSearchResultClass Class, string search, cFilteredResults _result)
{
SearchStatus = eSearchStatus.fixedResult;
SearchTextBox.IsEnabled = false;
SearchButton.Visibility = Visibility.Collapsed;
WarningIndicator.Visibility = Visibility.Collapsed;
foreach (var entryIcon in _searchIcons)
{
if (Class == entryIcon.Key)
entryIcon.Value.Visibility = Visibility.Visible;
else
entryIcon.Value.Visibility = Visibility.Collapsed;
}
SearchTextBox.Text = search;
await ChangedSearchValue.Invoke(_result);
}
public void SetApiStatus()
{
try
{
var Status = cConnectionStatusHelper.Instance?.ApiConnectionStatus;
if (Status == null)
return;
bool IsEnabled = false;
string txt = null;
switch (Status)
{
case cConnectionStatusHelper.enumOnlineStatus.online:
IsEnabled = true;
break;
case cConnectionStatusHelper.enumOnlineStatus.connectionError:
txt = cMultiLanguageSupport.GetItem("Searchbar.Status.ConnectError");
break;
case cConnectionStatusHelper.enumOnlineStatus.incompatibleServerVersion:
txt = cMultiLanguageSupport.GetItem("Searchbar.Status.IncompatibleVersion");
break;
case cConnectionStatusHelper.enumOnlineStatus.serverStarting:
txt = cMultiLanguageSupport.GetItem("Searchbar.Status.ServerStarting");
break;
case cConnectionStatusHelper.enumOnlineStatus.serverNotConfigured:
txt = cMultiLanguageSupport.GetItem("Searchbar.Status.ServerNotConfigured");
break;
case cConnectionStatusHelper.enumOnlineStatus.illegalConfig:
txt = cMultiLanguageSupport.GetItem("Searchbar.Status.IllegalConfig");
break;
case cConnectionStatusHelper.enumOnlineStatus.unauthorized:
txt = cMultiLanguageSupport.GetItem("Searchbar.Status.Unauthorized");
break;
default:
txt = cMultiLanguageSupport.GetItem("Searchbar.Status.Offline");
break;
}
if (!IsEnabled)
{
SearchStatus = eSearchStatus.message;
SearchTextBox.Text = txt;
SearchTextBox.IsEnabled = false;
WarningIndicator.Visibility = Visibility.Visible;
SearchButton.Visibility = Visibility.Collapsed;
foreach (var Entry in _searchIcons.Values)
Entry.Visibility = Visibility.Collapsed;
}
}
catch (Exception E)
{
LogException(E);
}
finally
{
}
}
private async Task CancelRunningSearchTaskAsync()
{
// cancel the search task, in case of a running search task
lock (_currentSearchTaskLock)
{
if (_currentSearchTaskToken != null)
{
LogEntry("Canceling current running search...");
_currentSearchTaskToken.Cancel(true);
_currentSearchTaskToken = null;
}
}
// send a stop to the server, in case of a running search task
Guid? currentTaskId = null;
lock (_currentSearchTaskLock)
{
if (_currentSearchTaskId != null)
{
currentTaskId = _currentSearchTaskId;
_currentSearchTaskId = null;
}
}
if (currentTaskId != null)
{
LogEntry("Sending a search stop...");
await cFasdCockpitCommunicationBase.Instance.GetSearchResultsStop((Guid)currentTaskId, CancellationToken.None);
}
}
private async void UpdateSearchResultsTick(object sender, EventArgs e)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
_searchTimer.Stop();
await CancelRunningSearchTaskAsync();
lock (_currentSearchTaskLock)
{
LogEntry("Start running new search...");
SearchValueChanged?.Invoke(this, SearchValue);
}
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
}
private void HandleSearchValueChanged()
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
{
if (!SearchTextBox.IsEnabled)
return;
if (_searchTimer.IsEnabled)
_searchTimer.Stop();
_searchTimer.Start();
_ = Task.Run(async () => { await CancelRunningSearchTaskAsync(); });
}
catch (Exception E)
{
LogException(E);
}
finally
{
if (CM != null) LogMethodEnd(CM);
}
}
private void SearchButton_Click(object sender, InputEventArgs e)
{
SearchTextBox.Focus();
}
#region CancledSearch Event
public static readonly RoutedEvent CancledSearchEvent = EventManager.RegisterRoutedEvent("CancledSearch", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(SearchBar));
public event RoutedEventHandler CancledSearch
{
add { AddHandler(CancledSearchEvent, value); }
remove { RemoveHandler(CancledSearchEvent, value); }
}
private void RaiseCancledSearchEvent()
{
RoutedEventArgs newEventArgs = new RoutedEventArgs(CancledSearchEvent);
RaiseEvent(newEventArgs);
}
#endregion
private void CloseButton_Click(object sender, InputEventArgs e)
{
RaiseCancledSearchEvent();
if (cConnectionStatusHelper.Instance?.ApiConnectionStatus == cConnectionStatusHelper.enumOnlineStatus.online)
SearchTextBox.Text = null;
CancledSearchAction?.Invoke();
}
private void SearchBar_Loaded(object sender, RoutedEventArgs e)
{
_searchTimer.Stop();
_searchTimer.Interval = TimeSpan.FromMilliseconds(constTimeBetweenKeystrokes);
_searchTimer.Tick += UpdateSearchResultsTick;
BackgroundBorder.CornerRadius = new CornerRadius(BackgroundBorder.ActualHeight / 2.0);
}
}
}

View File

@@ -0,0 +1,27 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.SearchFilterBar"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Border Background="Transparent"
CornerRadius="17.5"
Padding="2.5"
VerticalAlignment="Bottom"
Margin="0 10 0 0"
>
<DockPanel x:Name="IconDockPanel" LastChildFill="False">
<DockPanel.Resources>
<Style TargetType="ico:AdaptableIcon" BasedOn="{StaticResource Menu.MenuBar.PinnedIcon.Pinned}">
<Setter Property="IconCornerRadius" Value="20"/>
<Setter Property="Margin" Value="7.5 2.5 0 0"/>
</Style>
</DockPanel.Resources>
</DockPanel>
</Border>
</UserControl>

View File

@@ -0,0 +1,161 @@
using C4IT.FASD.Base;
using F4SD_AdaptableIcon;
using F4SD_AdaptableIcon.Enums;
using FasdDesktopUi.Basics.CustomEvents;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.UserControls.AdaptableIcon;
using FasdDesktopUi.Pages.AdvancedSearchPage;
using Microsoft.Internal.VisualStudio.PlatformUI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
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;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class SearchFilterBar : UserControl
{
// New Advanced-Search-Page IN PROGRESS
// Notes for next steps in AdvancedSearchPageView-Class
public HashSet<enumFasdInformationClass> InformationClassesToFilter
{
get { return (HashSet<enumFasdInformationClass>)GetValue(InformationClassesToFilterProperty); }
set { SetValue(InformationClassesToFilterProperty, value); }
}
public static readonly DependencyProperty InformationClassesToFilterProperty =
DependencyProperty.Register("InformationClassesToFilter", typeof(HashSet<enumFasdInformationClass>), typeof(SearchFilterBar), new PropertyMetadata(new HashSet<enumFasdInformationClass>(), InformationClassesToFilterChanged));
private static void InformationClassesToFilterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is SearchFilterBar me))
return;
if (!(e.NewValue is HashSet<enumFasdInformationClass> informationClasses))
return;
IEnumerable<(IconData, enumFasdInformationClass)> iconList = informationClasses.Select(informationClass => (GetIconData(informationClass), informationClass));
me.UpdateFilterIcons(iconList);
IconData GetIconData(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.misc_ticket);
case enumFasdInformationClass.VirtualSession:
case enumFasdInformationClass.MobileDevice:
break; //cloud
default:
break;
}
return new IconData(enumInternIcons.f4sd);
}
}
public delegate void FilterChangedEventHandler(object sender, SearchFilterChangedEventArgs e);
public SearchFilterBar()
{
InitializeComponent();
}
public static readonly RoutedEvent FilterChangedEvent = EventManager.RegisterRoutedEvent(
name: nameof(FilterChanged),
routingStrategy: RoutingStrategy.Bubble,
handlerType: typeof(FilterChangedEventHandler),
ownerType: typeof(SearchFilterBar));
// Provide CLR accessors for assigning an event handler.
public event RoutedEventHandler FilterChanged
{
add { AddHandler(FilterChangedEvent, value); }
remove { RemoveHandler(FilterChangedEvent, value); }
}
private void UpdateFilterIcons(IEnumerable<(IconData, enumFasdInformationClass)> iconDataList)
{
foreach (var item in IconDockPanel.Children.OfType<UIElement>())
{
item.MouseLeftButtonUp -= FilterIcon_Clicked;
item.TouchDown -= FilterIcon_Clicked;
}
IconDockPanel.Children.Clear();
foreach ((IconData iconData, enumFasdInformationClass informationClass) in iconDataList)
{
AdaptableIcon.AdaptableIcon adaptableIcon = new AdaptableIcon.AdaptableIcon();
adaptableIcon.Tag = informationClass;
adaptableIcon.MouseLeftButtonUp += FilterIcon_Clicked;
adaptableIcon.TouchDown += FilterIcon_Clicked;
if (iconData.Intern != null)
adaptableIcon.SelectedInternIcon = iconData.Intern;
else if (iconData.Material != null)
adaptableIcon.SelectedMaterialIcon = iconData.Material;
IconDockPanel.Children.Add(adaptableIcon);
}
}
private void FilterIcon_Clicked(object sender, EventArgs e)
{
if (!(sender is FrameworkElement fe) || !(fe.Tag is enumFasdInformationClass selectedInformationClass))
return;
var prop = fe.GetType().GetProperty("IconBackgroundColor");
if (prop == null || !prop.CanWrite)
return;
var resourceColorSelected = Application.Current.TryFindResource("Color.FunctionMarker");
var resourceColorUnselect = Application.Current.TryFindResource("Background.Menu.Icon.Hover");
var currentValue = prop.GetValue(fe);
if (currentValue != null && currentValue.Equals(resourceColorSelected))
{
// Zweiter Klick: Filter entfernen
prop.SetValue(fe, resourceColorUnselect);
AdvancedSearchPage.advancedSearchPage.StoredFilterInformationClasses?.Remove(selectedInformationClass);
}
else
{
// Erster Klick: Filter hinzufügen
prop.SetValue(fe, resourceColorSelected);
if (AdvancedSearchPage.advancedSearchPage.StoredFilterInformationClasses == null)
AdvancedSearchPage.advancedSearchPage.StoredFilterInformationClasses = new HashSet<enumFasdInformationClass>();
AdvancedSearchPage.advancedSearchPage.StoredFilterInformationClasses.Add(selectedInformationClass);
}
// Event mit den aktuellen Filtern auslösen
SearchFilterChangedEventArgs routedEventArgs = new SearchFilterChangedEventArgs(FilterChangedEvent)
{
InformationClassesToShow = new HashSet<enumFasdInformationClass>(AdvancedSearchPage.advancedSearchPage.StoredFilterInformationClasses)
};
RaiseEvent(routedEventArgs);
}
}
}

View File

@@ -0,0 +1,58 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.CustomSearchResultCollection"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
x:Name="CustomSearchResultUc">
<UserControl.Resources>
<vc:NullValueToVisibilityConverter x:Key="NullToVisibility" />
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter" />
</UserControl.Resources>
<Border x:Name="MainBorder" x:FieldModifier="private">
<Grid x:Name="MainGrid" x:FieldModifier="private">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock x:Name="HeaderTextBlock" x:FieldModifier="private"
Grid.Column="0"
Style="{DynamicResource DetailsPage.DataHistory.TitleColumn.OverviewTitle}"
HorizontalAlignment="Left"
Margin="5 0 0 5"/>
<CheckBox x:Name="ShowDetailsCheckBox" x:FieldModifier="private"
Style="{DynamicResource ToggleSwitch}"
IsChecked="{Binding ElementName=CustomSearchResultUc, Path=ShowSearchResultDetails}"
Grid.Column="1"
Margin="5 0"
VerticalAlignment="Center"
ToolTip="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=SearchBar.ShowDetails}"
Cursor="Hand"
Checked="ShowDetailsCheckBox_Checked"
Unchecked="ShowDetailsCheckBox_Checked"/>
<ScrollViewer x:Name="MainScrollViewer" x:FieldModifier="private"
VerticalScrollBarVisibility="Auto"
Grid.Row="1"
Grid.ColumnSpan="2">
<StackPanel x:Name="MainStackPanel" x:FieldModifier="private"
Grid.IsSharedSizeScope="True"/>
</ScrollViewer>
</Grid>
</Border>
</UserControl>

View File

@@ -0,0 +1,496 @@
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);
}
}
}
}

View File

@@ -0,0 +1,48 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.SearchResult.SearchResultCategory"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls.SearchResult"
xmlns:uc="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
mc:Ignorable="d"
d:DesignHeight="80"
d:DesignWidth="450"
x:Name="SearchResultCategoryUc">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisibility" />
</UserControl.Resources>
<StackPanel>
<Border Background="{DynamicResource BackgroundColor.Menu.SubCategory}"
CornerRadius="7.5"
Visibility="{Binding ElementName=SearchResultCategoryUc, Path=IsPending, Converter={StaticResource BoolToVisibility}}">
<DockPanel>
<ico:AdaptableIcon SelectedInternIcon="{Binding ElementName=SearchResultCategoryUc, Path=TitleIcon.Intern}"
SelectedMaterialIcon="{Binding ElementName=SearchResultCategoryUc, Path=TitleIcon.Material}"
Style="{DynamicResource Menu.CategoryBase.Icon.NoHover}"
IconHeight="22.5"
IconWidth="22.5"
Margin="10 2.5"
DockPanel.Dock="Left" />
<ico:AdaptableIcon SelectedInternGif="loadingPoints"
IconHeight="40"
IconWidth="40"
Margin="10 2.5"
DockPanel.Dock="Right" />
<TextBlock Text="{Binding ElementName=SearchResultCategoryUc, Path=Title}"
Style="{DynamicResource Menu.CategoryBase.TextBlock.NoHover}"
DockPanel.Dock="Left" />
</DockPanel>
</Border>
<uc:CustomMenu x:Name="ResultMenu"
x:FieldModifier="private" />
</StackPanel>
</UserControl>

View File

@@ -0,0 +1,91 @@
using C4IT.FASD.Base;
using C4IT.MultiLanguage;
using F4SD_AdaptableIcon;
using F4SD_AdaptableIcon.Enums;
using FasdDesktopUi.Basics.CustomEvents;
using FasdDesktopUi.Basics.Helper;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.UiActions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
namespace FasdDesktopUi.Basics.UserControls.SearchResult
{
public partial class SearchResultCategory : UserControl
{
public string Title
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(string), typeof(SearchResultCategory), new PropertyMetadata(string.Empty));
public bool IsPending
{
get { return (bool)GetValue(IsPendingProperty); }
set { SetValue(IsPendingProperty, value); }
}
public static readonly DependencyProperty IsPendingProperty =
DependencyProperty.Register("IsPending", typeof(bool), typeof(SearchResultCategory), new PropertyMetadata(false));
public IconData TitleIcon
{
get { return (IconData)GetValue(TitleIconProperty); }
set { SetValue(TitleIconProperty, value); }
}
public static readonly DependencyProperty TitleIconProperty =
DependencyProperty.Register("TitleIcon", typeof(IconData), typeof(SearchResultCategory), new PropertyMetadata(new IconData(enumInternIcons.f4sd)));
public SearchResultCategory()
{
InitializeComponent();
}
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
AddHandler(CustomEventManager.IndexChangedEvent, new CustomEventManager.IndexChangedHandlerDelegate(HandleSelectedIndexChanged));
}
private void HandleSelectedIndexChanged(object sender, IndexEventArgs args)
{
if (args.OriginalSource == this)
return;
CustomEventManager.RaiseIndexChangedEvent(this, args.OldValue, args.NewValue);
}
public void UpdateSearchResults(cFasdApiSearchResultCollection results, ISearchUiProvider uiSearchProvider)
{
ResultMenu.MenuDataList = results.Select(searchResult =>
{
var requiredInformationClasses = new List<enumFasdInformationClass>() { cF4sdIdentityEntry.GetFromSearchResult(searchResult.Value.First().Type) };
bool isEnabled = cHealthCardDataHelper.HasAvailableHealthCard(requiredInformationClasses);
var menuData = new cMenuDataSearchResult(searchResult.Key, uiSearchProvider, searchResult.Value) as cMenuDataBase;
menuData.UiAction.DisplayType = isEnabled ? Enums.enumActionDisplayType.enabled : Enums.enumActionDisplayType.disabled;
menuData.UiAction.Description = isEnabled ? string.Empty : cMultiLanguageSupport.GetItem("Searchbar.NoValidHealthcard");
menuData.UiAction.AlternativeDescription = isEnabled ? string.Empty : cMultiLanguageSupport.GetItem("Searchbar.NoValidHealthcard");
return menuData;
}).ToList();
}
public void UpdateSearchRelations(IEnumerable<cMenuDataBase> relations) => ResultMenu.MenuDataList = relations.ToList();
internal void ShowDetailHeadings(bool showDetailHeadings) => ResultMenu.ShowDetailHeading(showDetailHeadings);
internal int GetItemCount() => ResultMenu.MenuDataList.Count;
internal void HiglightItemAt(int index) => ResultMenu.HightlightItemAt(index);
internal void SelectItemAt(int index) => ResultMenu.SelectItemAt(index);
}
}

View File

@@ -0,0 +1,142 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.SelectionPill"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800"
d:Background="White"
x:Name="SelectionPillUc">
<Grid>
<Grid.Resources>
<Style x:Key="PillBorder"
TargetType="Border">
<Setter Property="Opacity"
Value="1" />
<Setter Property="HorizontalAlignment"
Value="Left" />
<Setter Property="VerticalAlignment"
Value="Top" />
<Setter Property="Margin"
Value="0 0 7.5 7.5" />
<Setter Property="Padding"
Value="10 5" />
<Setter Property="CornerRadius"
Value="15" />
<Setter Property="BorderThickness"
Value="3" />
<Setter Property="Background"
Value="#01010101" />
<Setter Property="BorderBrush"
Value="{DynamicResource Color.FunctionMarker}" />
<Setter Property="Cursor"
Value="Hand" />
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="False">
<Setter Property="Opacity"
Value="1" />
</Trigger>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Opacity"
Value="0.85" />
<Setter Property="Background"
Value="{DynamicResource Color.FunctionMarker}" />
<Setter Property="BorderThickness"
Value="0" />
<Setter Property="Padding"
Value="13 8" />
</Trigger>
<DataTrigger Binding="{Binding ElementName=SelectionPillUc, Path=IsSelected}"
Value="true">
<Setter Property="Background"
Value="{DynamicResource Color.FunctionMarker}" />
<Setter Property="BorderThickness"
Value="0" />
<Setter Property="Padding"
Value="13 8" />
</DataTrigger>
</Style.Triggers>
<Style.Resources>
<Style TargetType="ico:AdaptableIcon">
<Setter Property="PrimaryIconColor"
Value="{DynamicResource Color.Menu.Icon}" />
<Setter Property="BorderBrush"
Value="Transparent" />
<Setter Property="BorderThickness"
Value="0" />
<Setter Property="Margin"
Value="0 0 7.5 0" />
<Setter Property="BorderPadding"
Value="0" />
<Setter Property="IconHeight"
Value="15" />
<Setter Property="IconWidth"
Value="15" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorLevel=1, AncestorType=Border}, Path=IsMouseOver}"
Value="True">
<Setter Property="PrimaryIconColor"
Value="{DynamicResource Color.AppBackground}" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=SelectionPillUc, Path=IsSelected}"
Value="true">
<Setter Property="PrimaryIconColor"
Value="{DynamicResource Color.AppBackground}" />
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="TextBlock">
<Setter Property="FontSize"
Value="10" />
<Setter Property="Foreground"
Value="{DynamicResource Color.Menu.Icon}" />
<Setter Property="VerticalAlignment"
Value="Center" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorLevel=1, AncestorType=Border}, Path=IsMouseOver}"
Value="True">
<Setter Property="Foreground"
Value="{DynamicResource Color.AppBackground}" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=SelectionPillUc, Path=IsSelected}"
Value="true">
<Setter Property="Foreground"
Value="{DynamicResource Color.AppBackground}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Style.Resources>
</Style>
</Grid.Resources>
<Border x:Name="PillBorder"
Style="{DynamicResource PillBorder}"
MouseLeftButtonUp="PillBorder_MouseLeftButtonUp"
TouchDown="PillBorder_TouchDown">
<StackPanel Orientation="Horizontal">
<ico:AdaptableIcon x:Name="PillIcon"
Visibility="Collapsed"
SelectedInternIcon="{Binding ElementName=SelectionPillUc, Path=SelectedInternIcon}"
SelectedMaterialIcon="{Binding ElementName=SelectionPillUc, Path=SelectedMaterialIcon}"
SelectedInternGif="{Binding ElementName=SelectionPillUc, Path=SelectedGif}" />
<TextBlock x:Name="PillTextBlock"
Text="{Binding ElementName=SelectionPillUc, Path=PillText}" />
</StackPanel>
</Border>
</Grid>
</UserControl>

View File

@@ -0,0 +1,222 @@
using C4IT.FASD.Base;
using F4SD_AdaptableIcon.Enums;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices.WindowsRuntime;
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.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class SelectionPill : UserControl
{
#region PillText
public string PillText
{
get { return (string)GetValue(PillTextProperty); }
set { SetValue(PillTextProperty, value); }
}
public static readonly DependencyProperty PillTextProperty =
DependencyProperty.Register("PillText", typeof(string), typeof(SelectionPill), new PropertyMetadata(string.Empty));
#endregion
#region Icons
private static void SelectedIconChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
try
{
if (!(d is SelectionPill me))
return;
if (e.NewValue is null)
return;
switch (e.NewValue)
{
case enumInternIcons _:
me.SelectedMaterialIcon = null;
me.SelectedGif = null;
break;
case MaterialIcons.MaterialIconType _:
me.SelectedInternIcon = null;
me.SelectedGif = null;
break;
case enumInternGif _:
me.SelectedInternIcon = null;
me.SelectedMaterialIcon = null;
break;
}
if (me.SelectedInternIcon is null && me.SelectedMaterialIcon is null && me.SelectedGif is null)
me.PillIcon.Visibility = Visibility.Collapsed;
else
me.PillIcon.Visibility = Visibility.Visible;
}
catch (Exception E)
{
LogException(E);
}
}
public enumInternIcons? SelectedInternIcon
{
get { return (enumInternIcons?)GetValue(SelectedInternIconProperty); }
set { SetValue(SelectedInternIconProperty, value); }
}
public static readonly DependencyProperty SelectedInternIconProperty =
DependencyProperty.Register("SelectedInternIcon", typeof(enumInternIcons?), typeof(SelectionPill), new PropertyMetadata(null, new PropertyChangedCallback(SelectedIconChanged)));
public MaterialIcons.MaterialIconType? SelectedMaterialIcon
{
get { return (MaterialIcons.MaterialIconType?)GetValue(SelectedMaterialIconProperty); }
set { SetValue(SelectedMaterialIconProperty, value); }
}
public static readonly DependencyProperty SelectedMaterialIconProperty =
DependencyProperty.Register("SelectedMaterialIcon", typeof(MaterialIcons.MaterialIconType?), typeof(SelectionPill), new PropertyMetadata(null, new PropertyChangedCallback(SelectedIconChanged)));
public enumInternGif? SelectedGif
{
get { return (enumInternGif?)GetValue(SelectedGifProperty); }
set { SetValue(SelectedGifProperty, value); }
}
public static readonly DependencyProperty SelectedGifProperty =
DependencyProperty.Register("SelectedGif", typeof(enumInternGif?), typeof(SelectionPill), new PropertyMetadata(null, new PropertyChangedCallback(SelectedIconChanged)));
#endregion
private static List<SelectionPill> allPills = new List<SelectionPill>();
// Dependency Property für die Gruppenzugehörigkeit
public static readonly DependencyProperty GroupNameProperty =
DependencyProperty.Register("GroupName", typeof(string), typeof(SelectionPill), new PropertyMetadata(""));
public string GroupName
{
get { return (string)GetValue(GroupNameProperty); }
set { SetValue(GroupNameProperty, value); }
}
// Dependency Property für den Schalter "selectOne"
public static readonly DependencyProperty SelectOneProperty =
DependencyProperty.Register("SelectOne", typeof(bool), typeof(SelectionPill), new PropertyMetadata(false));
public bool SelectOne
{
get { return (bool)GetValue(SelectOneProperty); }
set { SetValue(SelectOneProperty, value); }
}
#region IsSelected
public event EventHandler IsSelectedChanged;
private static void OnIsSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
try
{
if (d is SelectionPill pill)
{
pill.IsSelectedChanged?.Invoke(pill, EventArgs.Empty);
}
}
catch (Exception E)
{
LogException(E);
}
}
public bool IsSelected
{
get { return (bool)GetValue(IsSelectedProperty); }
set { SetValue(IsSelectedProperty, value); }
}
public static readonly DependencyProperty IsSelectedProperty =
DependencyProperty.Register("IsSelected", typeof(bool), typeof(SelectionPill), new PropertyMetadata(false, new PropertyChangedCallback(OnIsSelectedChanged)));
#endregion
public SelectionPill()
{
InitializeComponent();
allPills.Add(this);
}
public static void RemovePill(SelectionPill pill)
{
if (allPills.Contains(pill))
{
allPills.Remove(pill);
}
}
private void DeselectOtherPillsInGroup()
{
if (!string.IsNullOrEmpty(GroupName) && SelectOne && IsSelected)
{
var pillsInGroup = allPills.Where(pill => pill.GroupName == this.GroupName && pill != this);
foreach (var pill in pillsInGroup)
{
pill.IsSelected = false;
}
}
}
#region PillBorder_Click
private void PillBorder_Click()
{
if (!SelectOne || string.IsNullOrEmpty(GroupName))
{
IsSelected = !IsSelected;
}
else if (!IsSelected) // Nur den Zustand ändern und andere deselektieren, wenn nicht bereits ausgewählt
{
IsSelected = true;
DeselectOtherPillsInGroup(); // Deselect other pills in the group
}
var _h = Dispatcher.Invoke(async () =>
{
DoubleAnimation doubleAnimation = new DoubleAnimation(0.7, TimeSpan.FromSeconds(0.1)) { AutoReverse = true };
PillBorder.BeginAnimation(OpacityProperty, doubleAnimation);
await Task.Delay(205);
PillBorder.BeginAnimation(OpacityProperty, null);
});
}
private void PillBorder_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
PillBorder_Click();
}
private void PillBorder_TouchDown(object sender, TouchEventArgs e)
{
PillBorder_Click();
}
#endregion
}
}

View File

@@ -0,0 +1,14 @@
<ToolTip x:Class="FasdDesktopUi.Basics.UserControls.StatusTreshholdTooltip"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<StackPanel Orientation="Vertical">
<TextBlock x:Name="rawValue" Text="Akteuller Wert" FontSize="11" Foreground="Blue"/>
<TextBlock x:Name="tresholdWarning" Text="Schwellwert Warnung" FontSize="11" Foreground="Orange"/>
<TextBlock x:Name="tresholdError" Text="Schwellwert Fehler" FontSize="11" Foreground="Red"/>
</StackPanel>
</ToolTip>

View File

@@ -0,0 +1,28 @@
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;
namespace FasdDesktopUi.Basics.UserControls
{
/// <summary>
/// Interaction logic for StatusTreshholdTooltip.xaml
/// </summary>
public partial class StatusTreshholdTooltip : ToolTip
{
public StatusTreshholdTooltip()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,440 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.CloseCaseDialogWithTicket"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
mc:Ignorable="d"
x:Name="CloseCaseDialogUc"
IsVisibleChanged="CloseCaseDialogUc_IsVisibleChanged"
d:DesignWidth="350"
d:Background="LightBlue"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<UserControl.Resources>
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter" />
<BooleanToVisibilityConverter x:Key="BooleanToVisibility" />
<Style x:Key="SwapIconStyleBase"
x:Name="SwapIconStyleBase"
TargetType="ico:AdaptableIcon"
BasedOn="{StaticResource Menu.MenuBar.PinnedIcon.Base}">
<Setter Property="Visibility"
Value="Hidden" />
<Setter Property="Opacity"
Value="0.7" />
<Setter Property="Cursor"
Value="{x:Null}" />
<Setter Property="SelectedInternIcon"
Value="misc_chevron_down" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorLevel=1, AncestorType=Border}, Path=IsMouseOver}"
Value="True">
<Setter Property="Visibility"
Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="SwapIconStyle"
TargetType="ico:AdaptableIcon"
BasedOn="{StaticResource SwapIconStyleBase}">
<Setter Property="Opacity"
Value="1" />
<Setter Property="Cursor"
Value="Hand" />
<Setter Property="IconBackgroundColor"
Value="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorLevel=1, AncestorType=Border}, Path=IsMouseOver}"
Value="True">
<Setter Property="IconBackgroundColor"
Value="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}" />
<Setter Property="PrimaryIconColor"
Value="{DynamicResource Color.Menu.Icon.Hover}" />
</DataTrigger>
</Style.Triggers>
</Style>
<ControlTemplate x:Key="ValidationErrorTemplate">
<Border BorderBrush="Red"
BorderThickness="1"
CornerRadius="7.5">
<TextBlock Text="{Binding ErrorContent}"
Foreground="White"
Padding="2" />
</Border>
</ControlTemplate>
</UserControl.Resources>
<ScrollViewer Height="570"
Padding="0 0 5 0"
VerticalScrollBarVisibility="Auto">
<StackPanel>
<Border x:Name="NewOrExistingOrNoneTicketSelectionBorder">
<WrapPanel x:Name="NewOrExistingOrNoneTicketWrap"
Margin="7.5 12.5 0 0"
Grid.Column="0"
Grid.ColumnSpan="2"
Grid.Row="3"
Width="{Binding ElementName=NewOrExistingOrNoneTicketSelectionBorder, Path=ActualWidth}">
</WrapPanel>
</Border>
<Border x:Name="TicketSelectionCategory"
CornerRadius="7.5"
Padding="10"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.TitleColumn}">
<StackPanel>
<StackPanel x:Name="TicketSelectionStack">
<Border x:Name="TicketSelectionBorder"
Margin="0 5 0 0"
MouseLeftButtonUp="TicketSelectionBorder_MouseLeftButtonUp"
TouchDown="TicketSelectionBorder_TouchDown">
<Border.Resources>
<Style TargetType="Border"
BasedOn="{StaticResource DetailsPage.TitleSection.Border.NotSelected}">
<Setter Property="Opacity"
Value="1.0" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsMouseOver}"
Value="True">
<Setter Property="Background"
Value="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}" />
</DataTrigger>
<Trigger Property="IsEnabled"
Value="False">
<Setter Property="Opacity"
Value="0.5" />
</Trigger>
</Style.Triggers>
</Style>
</Border.Resources>
<DockPanel>
<ico:AdaptableIcon x:Name="TicketIcon"
DockPanel.Dock="Left"
IconHeight="28"
IconWidth="28"
BorderPadding="0"
PrimaryIconColor="{DynamicResource Color.Menu.Icon}"
SelectedMaterialIcon="ic_mail"
Margin="10 0 7.5 0" />
<ico:AdaptableIcon x:Name="TicketSwapIcon"
Style="{DynamicResource SwapIconStyle}"
DockPanel.Dock="Right"
Visibility="Visible"
Height="28"
BorderBrush="{DynamicResource Color.SoftContrast}"
BorderThickness="2 0 0 0"
BorderPadding="7.5 2.5 2.5 2.5"
Margin="5 0" />
<TextBlock x:Name="TicketTextBlock"
Style="{DynamicResource DetailsPage.TitleSection.Header}" />
</DockPanel>
</Border>
<Popup x:Name="TicketSelectionPopUp"
VerticalOffset="5"
IsOpen="False"
Closed="TicketSelectionPopUp_Closed"
StaysOpen="False"
AllowsTransparency="True"
Width="{Binding ElementName=TicketSelectionBorder, Path=ActualWidth}">
<Border Background="{DynamicResource BackgroundColor.DetailsPage.Widget.Title}"
CornerRadius="7.5"
Width="{Binding ElementName=TicketSelectionBorder, Path=ActualWidth}">
<StackPanel x:Name="TicketSelectionContainer" />
</Border>
</Popup>
</StackPanel>
<StackPanel x:Name="MainStack">
<StackPanel x:Name="CategoryLabelPanel">
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.Category}"
FontWeight="Bold"
Margin="0 10 0 0"
Foreground="{DynamicResource FontColor.Menu.Categories}" />
</StackPanel>
<local:ComboBoxPageable x:Name="CategorySelectionControl"
Margin="0 5 0 0"
SelectedItem="{Binding SelectedCategory, ElementName=CloseCaseDialogUc, Mode=TwoWay}"
ComboBoxBackground="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
BorderBrush="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}"
PreviewKeyDown="Combobox_PreviewKeyDown"
/>
<StackPanel>
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.Template}"
FontWeight="Bold"
Margin="0 10 0 0"
Foreground="{DynamicResource FontColor.Menu.Categories}" />
<ComboBox x:Name="QuickTicketSelection"
Margin="0 5 0 0"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
BorderBrush="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}"
SelectedIndex="0"
PreviewKeyDown="Combobox_PreviewKeyDown"
DropDownOpened="DropDownOpened"
DropDownClosed="DropDownClosed">
</ComboBox>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="SetOrUpdateComputerInTicketLabel"
Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.SetAffectedAssetLabel}"
FontWeight="Bold"
Margin="0 10 0 0"
Foreground="{DynamicResource FontColor.Menu.Categories}" />
<CheckBox x:Name="SetOrUpdateComputerInTicketCheckbox"
Style="{DynamicResource ToggleSwitch}"
Margin="10 0 0 -10"
HorizontalAlignment="Left"
IsChecked="{Binding SetOrUpdateComputerInTicket, ElementName=CloseCaseDialogUc}"
VerticalAlignment="Center"
Cursor="Hand" />
<ico:AdaptableIcon x:Name="WarningAssetHasBeenChanged"
Visibility="{Binding ShowAssetHasBeenChangedWarning, ElementName=CloseCaseDialogUc, Converter={StaticResource BooleanToVisibility}}"
ToolTip="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.WarningNewAffectedAsset}"
IconBackgroundColor="Transparent"
Margin="0 0 0 -7"
PrimaryIconColor="#FFFF8800"
SelectedInternIcon="status_bad"
VerticalAlignment="Bottom" />
</StackPanel>
<ComboBox x:Name="ComputerSelection"
Margin="0 5 0 0"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
BorderBrush="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}"
SelectedIndex="0"
SelectionChanged="ComputerSelection_SelectionChanged"
SelectedItem="{Binding SelectedComputer, ElementName=CloseCaseDialogUc, Mode=TwoWay}"
ItemsSource="{Binding ComputerRelations, ElementName=CloseCaseDialogUc}"
DisplayMemberPath="Name"
IsEnabled="{Binding SetOrUpdateComputerInTicket, ElementName=CloseCaseDialogUc}"
PreviewKeyDown="Combobox_PreviewKeyDown"
DropDownOpened="DropDownOpened"
DropDownClosed="DropDownClosed">
</ComboBox>
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="SetOrUpdateServiceInTicketLabel"
Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.SetAffectedServiceLabel}"
FontWeight="Bold"
Margin="0 10 0 0"
Foreground="{DynamicResource FontColor.Menu.Categories}" />
<CheckBox x:Name="SetOrUpdateServiceInTicketCheckbox"
Style="{DynamicResource ToggleSwitch}"
Margin="10 0 0 -10"
HorizontalAlignment="Left"
IsChecked="{Binding SetOrUpdateServiceInTicket, ElementName=CloseCaseDialogUc}"
VerticalAlignment="Center"
Cursor="Hand" />
<ico:AdaptableIcon x:Name="WarningServiceHasBeenChanged"
Visibility="{Binding ShowServiceHasBeenChangedWarning, ElementName=CloseCaseDialogUc, Converter={StaticResource BooleanToVisibility}}"
ToolTip="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.WarningNewAffectedService}"
IconBackgroundColor="Transparent"
Margin="0 0 0 -7"
PrimaryIconColor="#FFFF8800"
SelectedInternIcon="status_bad"
VerticalAlignment="Bottom" />
</StackPanel>
<local:ComboBoxPageable x:Name="ServiceSelectionControl"
Margin="0 5 0 0"
ResetFilterLabel="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.ResetFilter.Services}"
SelectedItem="{Binding SelectedService, ElementName=CloseCaseDialogUc, Mode=TwoWay}"
IsEnabled="{Binding SetOrUpdateServiceInTicket, ElementName=CloseCaseDialogUc}"
ComboBoxBackground="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
BorderBrush="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}"
PreviewKeyDown="Combobox_PreviewKeyDown" />
</StackPanel>
<StackPanel>
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.Summary}"
FontWeight="Bold"
Margin="0 10 0 0"
Foreground="{DynamicResource FontColor.Menu.Categories}" />
<TextBox x:Name="TicketSummaryTextBox"
Margin="0 5 0 10"
Style="{DynamicResource Customizable.Editable.TextBox.EditOnly}"
Padding="7.5 5"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
TextChanged="TicketSummaryTextBox_TextChanged" />
</StackPanel>
</StackPanel>
</Border>
<Border x:Name="StatusSelectionBorder"
CornerRadius="7.5"
Margin="0 10 0 0"
Padding="10"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.TitleColumn}">
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.Status}"
FontWeight="Bold"
Foreground="{DynamicResource FontColor.Menu.Categories}" />
<ico:AdaptableIcon x:Name="WarningTicketAction"
Visibility="{Binding ShowAssetWarningTicketAction, ElementName=CloseCaseDialogUc, Converter={StaticResource BooleanToVisibility}}"
ToolTip=""
IconBackgroundColor="Transparent"
Margin="0,-7,0,-7"
PrimaryIconColor="#FFFF8800"
SelectedInternIcon="status_bad"
VerticalAlignment="Bottom" />
</StackPanel>
<ComboBox x:Name="TicketStatusCombobox"
Margin="0 5 0 0"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
BorderBrush="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}"
DropDownOpened="DropDownOpened"
DropDownClosed="DropDownClosed"
PreviewKeyDown="Combobox_PreviewKeyDown"
SelectionChanged="TicketStatusCombobox_SelectionChanged"
SelectedIndex="0">
<ComboBoxItem Content="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.Status.Select}" />
<ComboBoxItem Content="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.Status.Close}"
Visibility="{Binding EnableCloseTicketAction, ElementName=CloseCaseDialogUc, Converter={StaticResource BooleanToVisibility}}"
Tag="Close" />
<ComboBoxItem Content="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.Status.Save}"
Visibility="{Binding EnableSaveTicketAction, ElementName=CloseCaseDialogUc, Converter={StaticResource BooleanToVisibility}}"
Tag="Save" />
<ComboBoxItem Content="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.Status.OnHold}"
Visibility="{Binding EnableHoldTicketAction, ElementName=CloseCaseDialogUc, Converter={StaticResource BooleanToVisibility}}"
Tag="OnHold" />
<ComboBoxItem Content="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.Status.Forward}"
Visibility="{Binding EnableForwardTicketAction, ElementName=CloseCaseDialogUc, Converter={StaticResource BooleanToVisibility}}"
Tag="Forward" />
</ComboBox>
</StackPanel>
</Border>
<Border x:Name="DynamicStatusAdditionBorder"
Visibility="Collapsed"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.TitleColumn}"
CornerRadius="7.5"
Padding="10"
Margin="0 10 0 0" />
<Border x:Name="SelectionBorder"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.TitleColumn}"
CornerRadius="7.5"
Padding="10"
Margin="0 10 0 0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.Transfer.QuickActionHistory}"
FontWeight="Bold"
Foreground="{DynamicResource FontColor.Menu.Categories}" />
<CheckBox x:Name="TransferQuickActionHistoryCheck"
Style="{DynamicResource ToggleSwitch}"
Margin="15 0 0 0"
HorizontalAlignment="Left"
IsChecked="True"
Grid.Column="1" />
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.Transfer.Notes}"
Foreground="{DynamicResource FontColor.Menu.Categories}"
FontWeight="Bold"
VerticalAlignment="Center"
Margin="0 5 0 0"
Grid.Row="1" />
<!--<ico:AdaptableIcon x:Name="EditCaseNotesButton"
SelectedMaterialIcon="ic_edit"
Style="{DynamicResource SettingsPage.Close.Icon}"
BorderPadding="7.5 10 7.5 5"
VerticalAlignment="Center"
MouseLeftButtonUp="EditCaseNotesButton_MouseLeftButtonUp"
TouchDown="EditCaseNotesButton_TouchDown" />-->
<CheckBox x:Name="TransferCaseNotesCheck"
Style="{DynamicResource ToggleSwitch}"
Margin="15 5 0 0"
HorizontalAlignment="Left"
IsChecked="True"
Grid.Column="1"
Grid.Row="1"
Checked="TransferCaseNotesCheck_Checked"
Unchecked="TransferCaseNotesCheck_Unchecked" />
<Border x:Name="CaseNotesPreviewBorder"
Margin="0 10 0 0"
Padding="15 5 5 0"
CornerRadius="7.5"
Grid.Column="0"
Grid.ColumnSpan="2"
Grid.Row="2"
BorderThickness="0.9"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
MaxHeight="45">
<TextBlock x:Name="CaseNotesPreview"
MaxWidth="420"
MaxHeight="20"
Margin="-35 -5 -25 5"
Padding="5 3 0 0"
Foreground="{DynamicResource FontColor.Menu.Categories}"
FontSize="13"
Cursor="Pen"
MouseLeftButtonUp="EditCaseNotesButton_MouseLeftButtonUp"
TouchDown="EditCaseNotesButton_TouchDown"/>
</Border>
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.Transfer.CopyTemplates}"
Foreground="{DynamicResource FontColor.Menu.Categories}"
FontWeight="Bold"
Margin="0 10 0 0"
Grid.Row="3" />
<Border Margin="0 10 0 0"
Padding="2.5 0 2.5 2.5"
CornerRadius="7.5"
Grid.Column="0"
Grid.ColumnSpan="2"
Grid.Row="4"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}">
<Border x:Name="CopyTemplateSelectionBorder">
<WrapPanel x:Name="CopyTemplateWrap"
Margin="7.5 12.5 0 0"
Grid.Column="0"
Grid.ColumnSpan="2"
Grid.Row="3"
Width="{Binding ElementName=CopyTemplateSelectionBorder, Path=ActualWidth}" />
</Border>
</Border>
</Grid>
</Border>
<TextBlock x:Name="CopyDisclaimerTextBox"
Visibility="Collapsed"
Margin="5 15 5 10"
FontSize="16"
TextWrapping="Wrap"
Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.CopyDisclaimer}"
Foreground="{DynamicResource FontColor.Menu.Categories}" />
</StackPanel>
</ScrollViewer>
</UserControl>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,45 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.CloseTicketDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800"
d:Background="White"
x:Name="CloseTicketDialogUc"
>
<UserControl.Resources>
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter" />
</UserControl.Resources>
<StackPanel>
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.CloseTicket.ErrorType}"
FontWeight="Bold"
Foreground="{DynamicResource FontColor.Menu.Categories}" />
<ComboBox x:Name="ErrorTypeComboBox"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
BorderBrush="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}"
SelectedItem="{Binding ElementName=CloseTicketDialogUc, Path=SelectedErrorType, Mode=TwoWay}"
Margin="0 5 0 0"
DropDownOpened="DropDownOpened"
DropDownClosed="DropDownClosed"
PreviewKeyDown="ErrorTypeComboBox_PreviewKeyDown"
/>
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.CloseTicket.Solution}"
FontWeight="Bold"
Foreground="{DynamicResource FontColor.Menu.Categories}"
Margin="0 7.5 0 0"/>
<TextBox
x:Name="SolutionTextbox"
Text="{Binding ElementName=CloseTicketDialogUc, Path=Solution, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Margin="0 5 0 0"
Style="{DynamicResource Customizable.Editable.TextBox.EditOnly}"
MinLines="3"
TextWrapping="Wrap"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}" />
</StackPanel>
</UserControl>

View File

@@ -0,0 +1,180 @@
using FasdDesktopUi.Basics.Helper;
using FasdDesktopUi.Basics.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
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 static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class CloseTicketDialog : UserControl
{
#region Properties
public event EventHandler ErrorTypeValueChanged;
public event EventHandler SolutionValueChanged;
private cSupportCaseDataProvider dataProvider;
public cSupportCaseDataProvider DataProvider
{
get => dataProvider; set
{
dataProvider = value;
UpdateErrorTypeComboBox();
}
}
#region Solution
public string Solution
{
get { return (string)GetValue(SolutionProperty); }
set {
SetValue(SolutionProperty, value);
}
}
public static readonly DependencyProperty SolutionProperty =
DependencyProperty.Register("Solution", typeof(string), typeof(CloseTicketDialog), new PropertyMetadata(string.Empty, OnSolutionPropertyChanged));
private static void OnSolutionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (CloseTicketDialog)d;
control.SolutionValueChanged?.Invoke(control, EventArgs.Empty);
}
#endregion
public ComboBoxItem SelectedErrorType
{
get { return (ComboBoxItem)GetValue(SelectedErrorTypeProperty); }
set { SetValue(SelectedErrorTypeProperty, value); }
}
// Using a DependencyProperty as the backing store for SelectedErrorType. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SelectedErrorTypeProperty =
DependencyProperty.Register("SelectedErrorType", typeof(ComboBoxItem), typeof(CloseTicketDialog), new PropertyMetadata(null, OnSelectedErrorTypeChanged));
private static void OnSelectedErrorTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (CloseTicketDialog)d;
control.ErrorTypeValueChanged?.Invoke(control, EventArgs.Empty);
}
#endregion
public CloseTicketDialog()
{
InitializeComponent();
}
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
}
private void UpdateErrorTypeComboBox()
{
try
{
if (DataProvider == null) return;
var activityErrorTable = DataProvider.HealthCardDataHelper.HealthCardRawData.GetTableByName("M42Wpm-Pickup-ActivityErrorType", false);
if (activityErrorTable == null) return;
if (!activityErrorTable.Columns.TryGetValue("name", out var namesColumn) ||
!activityErrorTable.Columns.TryGetValue("position", out var positionsColumn) ||
!activityErrorTable.Columns.TryGetValue("hidden", out var hiddensColumn) ||
!activityErrorTable.Columns.TryGetValue("id", out var idsColumn)) return;
var errorTypeListe = new List<Dictionary<string, object>>();
for (int i = 0; i < idsColumn.Values.Count; i++)
{
if (int.TryParse(positionsColumn.Values[i].ToString(), out int positionValue))
{
var eintrag = new Dictionary<string, object>
{
{ "ID", idsColumn.Values[i] },
{ "DisplayName", namesColumn.Values[i] },
{ "Hidden", Convert.ToBoolean(hiddensColumn.Values[i])},
{ "Position", positionValue }
};
errorTypeListe.Add(eintrag);
}
}
// Filtere die Liste, um nur nicht versteckte Elemente zu behalten
errorTypeListe = errorTypeListe.Where(eintrag => !(bool)eintrag["Hidden"]).OrderBy(eintrag => (int)eintrag["Position"]).ToList();
var editComboBox = ErrorTypeComboBox;
editComboBox.Items.Clear();
foreach (var listValue in errorTypeListe)
{
editComboBox.Items.Add(new ComboBoxItem { Content = listValue["DisplayName"], Tag = listValue["ID"] });
}
}
catch (Exception e)
{
LogException(e);
}
}
private void DropDownOpened(object sender, EventArgs e)
{
try
{
if (!(sender is FrameworkElement senderElement))
return;
var parentBorder = cUiElementHelper.GetFirstParentOfType<Border>(senderElement);
cFocusInvoker.InvokeGotFocus(parentBorder, e);
}
catch (Exception E)
{
LogException(E);
}
}
private void DropDownClosed(object sender, EventArgs e)
{
try
{
if (!(sender is FrameworkElement senderElement))
return;
ErrorTypeValueChanged?.Invoke(this, EventArgs.Empty);
var parentBorder = cUiElementHelper.GetFirstParentOfType<Border>(senderElement);
cFocusInvoker.InvokeLostFocus(parentBorder, e);
}
catch (Exception E)
{
LogException(E);
}
}
private void ErrorTypeComboBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
if(e.Key == Key.Escape) {
DropDownClosed(sender, e);
}
}
}
}

View File

@@ -0,0 +1,50 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.ForwardTicketDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800"
d:Background="White"
x:Name="ForwardTicketDialogUc">
<UserControl.Resources>
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter" />
</UserControl.Resources>
<StackPanel x:Name="MainStack">
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.ForwardTicket.ResponsibleRole}"
FontWeight="Bold"
Foreground="{DynamicResource FontColor.Menu.Categories}" />
<local:ComboBoxPageable x:Name="RoleSelectionControl"
SelectedItem="{Binding ElementName=ForwardTicketDialogUc, Path=SelectedRole, Mode=TwoWay}"
Margin="0 5 0 10"
ComboBoxBackground="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
BorderBrush="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}" />
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.ForwardTicket.ResponsiblePerson}"
FontWeight="Bold"
Foreground="{DynamicResource FontColor.Menu.Categories}" />
<local:ComboBoxPageable x:Name="PersonSelectionControl"
Margin="0 5 0 10"
SelectedItem="{Binding ElementName=ForwardTicketDialogUc, Path=SelectedPerson, Mode=TwoWay}"
ComboBoxBackground="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
BorderBrush="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}" />
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.ForwardTicket.Comment}"
FontWeight="Bold"
Foreground="{DynamicResource FontColor.Menu.Categories}" />
<TextBox x:Name="CommentTextbox"
Text="{Binding ElementName=ForwardTicketDialogUc, Path=Comment, Mode=TwoWay}"
Margin="0 5 0 0"
Style="{DynamicResource Customizable.Editable.TextBox.EditOnly}"
MinLines="3"
TextWrapping="Wrap"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}" />
</StackPanel>
</UserControl>

View File

@@ -0,0 +1,196 @@
using C4IT.FASD.Base;
using C4IT.FASD.Cockpit.Communication;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class ForwardTicketDialog : UserControl
{
private readonly cSupportCaseDataProvider _dataProvider;
string lastPersonSearch = string.Empty;
string lastRoleSearch = string.Empty;
public event EventHandler SelectedRoleChanged;
public event EventHandler SelectedPersonChanged;
public event EventHandler CommentChanged;
public string Comment
{
get { return (string)GetValue(CommentProperty); }
set { SetValue(CommentProperty, value); }
}
// Using a DependencyProperty as the backing store for Comment. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CommentProperty =
DependencyProperty.Register("Comment", typeof(string), typeof(ForwardTicketDialog), new PropertyMetadata(string.Empty, OnCommentChanged));
private static void OnCommentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (ForwardTicketDialog)d;
control.CommentChanged?.Invoke(control, EventArgs.Empty);
}
public KeyValuePair<string, object> SelectedRole
{
get { return (KeyValuePair<string, object>)GetValue(SelectedRoleProperty); }
set { SetValue(SelectedRoleProperty, value); }
}
// Using a DependencyProperty as the backing store for SelectedRole. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SelectedRoleProperty =
DependencyProperty.Register("SelectedRole", typeof(KeyValuePair<string, object>), typeof(ForwardTicketDialog), new PropertyMetadata(default(KeyValuePair<string, object>), OnSelectedRoleChanged));
private static void OnSelectedRoleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (ForwardTicketDialog)d;
control.SelectedRoleChanged?.Invoke(control, EventArgs.Empty);
}
public KeyValuePair<string, object> SelectedPerson
{
get { return (KeyValuePair<string, object>)GetValue(SelectedPersonProperty); }
set { SetValue(SelectedPersonProperty, value); }
}
// Using a DependencyProperty as the backing store for SelectedPerson. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SelectedPersonProperty =
DependencyProperty.Register("SelectedPerson", typeof(KeyValuePair<string, object>), typeof(ForwardTicketDialog), new PropertyMetadata(default(KeyValuePair<string, object>), OnSelectedPersonChanged));
private static void OnSelectedPersonChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (ForwardTicketDialog)d;
control.SelectedPersonChanged?.Invoke(control, EventArgs.Empty);
}
public ForwardTicketDialog(cSupportCaseDataProvider dataProvider)
{
InitializeComponent();
_dataProvider = dataProvider;
}
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
PersonSelectionControl.SearchDataChanged = HandlePersonSearchDataChanged;
PersonSelectionControl.ParentElement = MainStack;
PersonSelectionControl.ParentIndex = MainStack.Children.IndexOf(PersonSelectionControl);
RoleSelectionControl.SearchDataChanged = HandleRoleSearchDataChanged;
RoleSelectionControl.ParentElement = MainStack;
RoleSelectionControl.ParentIndex = MainStack.Children.IndexOf(RoleSelectionControl);
}
private async void HandlePersonSearchDataChanged(object sender, cF4sdHealthSelectionDataRequest e) => await UpdatePersonSelectionControlAsync(e);
private async Task UpdatePersonSelectionControlAsync(cF4sdHealthSelectionDataRequest requestData)
{
try
{
requestData.Identities = _dataProvider?.Identities;
requestData.Table = "M42Wpm-Ticket-Persons";
if (string.IsNullOrEmpty(lastPersonSearch) || !lastPersonSearch.Equals(requestData.Search, StringComparison.CurrentCultureIgnoreCase))
{
var peopleCount = await cFasdCockpitCommunicationBase.Instance.GetPagedDataCount(requestData);
PersonSelectionControl.TotalItemCount = peopleCount;
}
lastPersonSearch = requestData.Search;
var peopleData = await cFasdCockpitCommunicationBase.Instance.GetPagedData(requestData);
PersonSelectionControl.ItemData = GetPeopleSelectionData(peopleData);
}
catch (Exception E)
{
LogException(E);
}
}
private ObservableCollection<KeyValuePair<string, object>> GetPeopleSelectionData(cF4SDHealthCardRawData.cHealthCardTable dataTable)
{
try
{
if (dataTable is null || dataTable.Name != "M42Wpm-Ticket-Persons")
return null;
if (!dataTable.Columns.TryGetValue("id", out var idColumn))
return null;
dataTable.Columns.TryGetValue("LastName", out var lastNameColumn);
dataTable.Columns.TryGetValue("FirstName", out var firstNameColumn);
dataTable.Columns.TryGetValue("Position", out var positionColumn);
var zippedNames = lastNameColumn.Values.Zip(firstNameColumn.Values, (lastName, firstName) => $"{lastName}, {firstName}");
var zippedKeyValuePairs = idColumn.Values.Zip(zippedNames, (id, display) => new KeyValuePair<string, object>(display, id));
return new ObservableCollection<KeyValuePair<string, object>>(zippedKeyValuePairs);
}
catch (Exception E)
{
LogException(E);
}
return null;
}
private async void HandleRoleSearchDataChanged(object sender, cF4sdHealthSelectionDataRequest e) => await UpdateRoleSelectionControlAsync(e);
private async Task UpdateRoleSelectionControlAsync(cF4sdHealthSelectionDataRequest requestData)
{
try
{
requestData.Identities = _dataProvider?.Identities;
requestData.Table = "M42Wpm-Ticket-Roles";
if (string.IsNullOrEmpty(lastRoleSearch) || !lastRoleSearch.Equals(requestData.Search, StringComparison.CurrentCultureIgnoreCase))
{
var roleCount = await cFasdCockpitCommunicationBase.Instance.GetPagedDataCount(requestData);
RoleSelectionControl.TotalItemCount = roleCount;
}
lastRoleSearch = requestData.Search;
var roleData = await cFasdCockpitCommunicationBase.Instance.GetPagedData(requestData);
RoleSelectionControl.ItemData = GetRoleSelectionData(roleData);
}
catch (Exception E)
{
LogException(E);
}
}
private ObservableCollection<KeyValuePair<string, object>> GetRoleSelectionData(cF4SDHealthCardRawData.cHealthCardTable dataTable)
{
try
{
if (dataTable is null || dataTable.Name != "M42Wpm-Ticket-Roles")
return null;
if (!dataTable.Columns.TryGetValue("id", out var idColumn))
return null;
dataTable.Columns.TryGetValue("Name", out var nameColumn);
var zippedKeyValuePairs = idColumn.Values.Zip(nameColumn.Values, (id, display) => new KeyValuePair<string, object>(display.ToString(), id));
return new ObservableCollection<KeyValuePair<string, object>>(zippedKeyValuePairs);
}
catch (Exception E)
{
LogException(E);
}
return null;
}
}
}

View File

@@ -0,0 +1,454 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.HoldTicketDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800"
d:Background="White"
x:Name="HoldTicketDialogUc">
<UserControl.Resources>
<DataTemplate x:Key="TwoDigitHourTemplate">
<TextBlock Text="{Binding Path=., StringFormat={}{0:00}}" />
</DataTemplate>
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter"/>
<Style x:Key="DatePickerStyle1" TargetType="{x:Type DatePicker}">
<Style.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius"
Value="7.5" />
<Setter Property="BorderBrush"
Value="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}" />
</Style>
</Style.Resources>
<Setter Property="Foreground" Value="{DynamicResource FontColor.Menu.Categories}"/>
<Setter Property="IsTodayHighlighted" Value="True"/>
<Setter Property="SelectedDateFormat" Value="Short"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DatePicker}">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0" Storyboard.TargetName="PART_DisabledVisual" To="1" Storyboard.TargetProperty="Opacity"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="PART_Root" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<Grid.Resources>
<ControlTemplate x:Key="DropDownButtonTemplate" TargetType="{x:Type Button}">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0"/>
<VisualTransition GeneratedDuration="0:0:0.1" To="MouseOver"/>
<VisualTransition GeneratedDuration="0:0:0.1" To="Pressed"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0" Storyboard.TargetName="Background" To="#FF448DCA" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"/>
<ColorAnimationUsingKeyFrames BeginTime="0" Duration="00:00:00.001" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Border.Background).(GradientBrush.GradientStops)[3].(GradientStop.Color)">
<SplineColorKeyFrame KeyTime="0" Value="#7FFFFFFF"/>
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames BeginTime="0" Duration="00:00:00.001" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Border.Background).(GradientBrush.GradientStops)[2].(GradientStop.Color)">
<SplineColorKeyFrame KeyTime="0" Value="#CCFFFFFF"/>
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames BeginTime="0" Duration="00:00:00.001" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Border.Background).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
<SplineColorKeyFrame KeyTime="0" Value="#F2FFFFFF"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimationUsingKeyFrames BeginTime="0" Duration="00:00:00.001" Storyboard.TargetName="Background" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)">
<SplineColorKeyFrame KeyTime="0" Value="#FF448DCA"/>
</ColorAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="0" Duration="00:00:00.001" Storyboard.TargetName="Highlight" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames BeginTime="0" Duration="00:00:00.001" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Border.Background).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
<SplineColorKeyFrame KeyTime="0" Value="#EAFFFFFF"/>
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames BeginTime="0" Duration="00:00:00.001" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Border.Background).(GradientBrush.GradientStops)[2].(GradientStop.Color)">
<SplineColorKeyFrame KeyTime="0" Value="#C6FFFFFF"/>
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames BeginTime="0" Duration="00:00:00.001" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Border.Background).(GradientBrush.GradientStops)[3].(GradientStop.Color)">
<SplineColorKeyFrame KeyTime="0" Value="#6BFFFFFF"/>
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames BeginTime="0" Duration="00:00:00.001" Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Border.Background).(GradientBrush.GradientStops)[0].(GradientStop.Color)">
<SplineColorKeyFrame KeyTime="0" Value="#F4FFFFFF"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid FlowDirection="LeftToRight" HorizontalAlignment="Center" Height="15" Margin="0" VerticalAlignment="Center" Width="19">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="20*"/>
<ColumnDefinition Width="20*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20*"/>
<RowDefinition Height="16*"/>
<RowDefinition Height="16*"/>
<RowDefinition Height="16*"/>
</Grid.RowDefinitions>
<Border x:Name="Highlight" BorderBrush="#FF45D6FA" BorderThickness="1" CornerRadius="0,0,1,1" Grid.ColumnSpan="4" Margin="-1" Opacity="0" Grid.RowSpan="4" Grid.Row="0"/>
<Border x:Name="Background" Background="#FF1F3B53" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1" CornerRadius=".5" Grid.ColumnSpan="4" Margin="0,-1,0,0" Opacity="1" Grid.RowSpan="3" Grid.Row="1"/>
<Border x:Name="BackgroundGradient" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1" CornerRadius=".5" Grid.ColumnSpan="4" Margin="0,-1,0,0" Opacity="1" Grid.RowSpan="3" Grid.Row="1">
</Border>
<Rectangle Grid.ColumnSpan="4" Grid.RowSpan="1" StrokeThickness="1">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.3,-1.1" StartPoint="0.46,1.6">
<GradientStop Color="#FF4084BD"/>
<GradientStop Color="#FFAFCFEA" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
<Rectangle.Stroke>
<LinearGradientBrush EndPoint="0.48,-1" StartPoint="0.48,1.25">
<GradientStop Color="#FF494949"/>
<GradientStop Color="#FF9F9F9F" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Stroke>
</Rectangle>
<Path Grid.Column="0" Grid.ColumnSpan="4" Data="M11.426758,8.4305077 L11.749023,8.4305077 L11.749023,16.331387 L10.674805,16.331387 L10.674805,10.299648 L9.0742188,11.298672 L9.0742188,10.294277 C9.4788408,10.090176 9.9094238,9.8090878 10.365967,9.4510155 C10.82251,9.0929432 11.176106,8.7527733 11.426758,8.4305077 z M14.65086,8.4305077 L18.566387,8.4305077 L18.566387,9.3435936 L15.671368,9.3435936 L15.671368,11.255703 C15.936341,11.058764 16.27293,10.960293 16.681133,10.960293 C17.411602,10.960293 17.969301,11.178717 18.354229,11.615566 C18.739157,12.052416 18.931622,12.673672 18.931622,13.479336 C18.931622,15.452317 18.052553,16.438808 16.294415,16.438808 C15.560365,16.438808 14.951641,16.234707 14.468243,15.826504 L14.881817,14.929531 C15.368796,15.326992 15.837872,15.525723 16.289043,15.525723 C17.298809,15.525723 17.803692,14.895514 17.803692,13.635098 C17.803692,12.460618 17.305971,11.873379 16.310528,11.873379 C15.83071,11.873379 15.399232,12.079271 15.016094,12.491055 L14.65086,12.238613 z" Fill="#FF2F2F2F" HorizontalAlignment="Center" Margin="4,3,4,3" RenderTransformOrigin="0.5,0.5" Grid.RowSpan="3" Grid.Row="1" Stretch="Fill" VerticalAlignment="Center"/>
<Ellipse Grid.ColumnSpan="4" Fill="#FFFFFFFF" HorizontalAlignment="Center" Height="3" StrokeThickness="0" VerticalAlignment="Center" Width="3"/>
</Grid>
</Grid>
</ControlTemplate>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ToggleButton x:Name="PART_Button"
Grid.Column="1"
Grid.Row="0"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="0"
Grid.ColumnSpan="2"
IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
Style="{StaticResource ComboBoxToggleButton}">
</ToggleButton>
<Border
VerticalAlignment="Center"
HorizontalAlignment="Center"
CornerRadius="5">
<DatePickerTextBox
x:Name="PART_TextBox"
Height="18"
Width="80"
TextWrapping="Wrap"
Text="DatePickerTextBox"
Background="Transparent"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Style="{DynamicResource DatePickerTextBoxStyle1}"/>
</Border>
<Grid x:Name="PART_DisabledVisual" Grid.Column="0" Grid.ColumnSpan="2" IsHitTestVisible="False" Opacity="0" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Popup x:Name="PART_Popup" AllowsTransparency="True" Placement="Bottom" PlacementTarget="{Binding ElementName=PART_TextBox}" StaysOpen="False"/>
</Grid>
</Grid>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding Source={x:Static SystemParameters.HighContrast}}" Value="false">
<Setter Property="Foreground" TargetName="PART_TextBox" Value="{Binding Foreground, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="DatePickerTextBoxStyle1" TargetType="{x:Type DatePickerTextBox}">
<Setter Property="Foreground" Value="{DynamicResource FontColor.Menu.Categories}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DatePickerTextBox}">
<Grid>
<Grid.Resources>
<SolidColorBrush x:Key="WatermarkBrush" Color="#FFAAAAAA"/>
</Grid.Resources>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0"/>
<VisualTransition GeneratedDuration="0:0:0.1" To="MouseOver"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0" To="#FF99C1E2" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="ContentElement"/>
<ColorAnimation Duration="0" To="#FF99C1E2" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="watermark_decorator"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="WatermarkStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Unwatermarked"/>
<VisualState x:Name="Watermarked">
<Storyboard>
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ContentElement"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_Watermark"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Unfocused"/>
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="FocusVisual"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="1" Opacity="1" Padding="{TemplateBinding Padding}">
<Grid x:Name="WatermarkContent" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<Border x:Name="ContentElement" BorderBrush="#FFFFFFFF" BorderThickness="1" Visibility="Hidden"/>
<Border x:Name="watermark_decorator" BorderBrush="#FFFFFFFF" BorderThickness="1" Visibility="Hidden">
<ContentControl x:Name="PART_Watermark" Focusable="False" IsHitTestVisible="False" Opacity="0" Padding="0"/>
</Border>
<ScrollViewer x:Name="PART_ContentHost" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="0" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
<Border x:Name="FocusVisual" BorderBrush="#FF45D6FA" CornerRadius="1" IsHitTestVisible="False" Opacity="0"/>
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="CalenderToggleButton"
TargetType="{x:Type ToggleButton}">
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="IsTabStop"
Value="false" />
<Setter Property="Focusable"
Value="false" />
<Setter Property="ClickMode"
Value="Press" />
<Setter Property="Border.CornerRadius"
Value="7.5" />
<Setter Property="Border.BorderThickness"
Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border x:Name="templateRoot"
Background="{TemplateBinding Background}"
BorderBrush="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding Border.CornerRadius}"
SnapsToDevicePixels="true"
Height="28">
<Border x:Name="splitBorder"
BorderBrush="Transparent"
BorderThickness="1"
HorizontalAlignment="Right"
Margin="5"
SnapsToDevicePixels="true"
Width="15">
<Viewbox HorizontalAlignment="Center"
VerticalAlignment="Center">
<Path x:Name="arrow"
Data="F1 M 2.89067,4.99467C 2.89067,4.22933 3.724,3.74533 4.39067,4.13067L 10.8227,7.844L 17.26,4.13067C 18.412,3.48 19.4013,5.19333 18.26,5.86533L 11.3227,9.86533C 11.016,10.0413 10.636,10.0413 10.3227,9.86533L 3.39067,5.86533C 3.07867,5.688 2.89067,5.35467 2.89067,4.99467 Z"
Fill="{DynamicResource Color.Menu.Icon}" />
</Viewbox>
</Border>
</Border>
<ControlTemplate.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type TextBox}}}"
Value="true" />
<Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}"
Value="false" />
<Condition Binding="{Binding IsPressed, RelativeSource={RelativeSource Self}}"
Value="false" />
<Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}"
Value="true" />
</MultiDataTrigger.Conditions>
</MultiDataTrigger>
<Trigger Property="IsMouseOver"
Value="true">
<Setter Property="Fill"
TargetName="arrow"
Value="{DynamicResource Color.Menu.Icon.Hover}" />
</Trigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}"
Value="true" />
<Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type TextBox}}}"
Value="false" />
</MultiDataTrigger.Conditions>
<Setter Property="Background"
TargetName="templateRoot"
Value="{Binding BorderBrush, RelativeSource={RelativeSource AncestorLevel=1, AncestorType=TextBox}}" />
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}"
Value="true" />
<Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type TextBox}}}"
Value="true" />
</MultiDataTrigger.Conditions>
<Setter Property="Background"
TargetName="templateRoot"
Value="{Binding BorderBrush, RelativeSource={RelativeSource AncestorLevel=1, AncestorType=TextBox}}" />
</MultiDataTrigger>
<Trigger Property="IsPressed"
Value="true">
<Setter Property="Fill"
TargetName="arrow"
Value="{DynamicResource Color.Menu.Icon.Hover}" />
</Trigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsPressed, RelativeSource={RelativeSource Self}}"
Value="true" />
<Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type TextBox}}}"
Value="false" />
</MultiDataTrigger.Conditions>
<Setter Property="Background"
TargetName="templateRoot"
Value="{Binding BorderBrush, RelativeSource={RelativeSource AncestorLevel=1, AncestorType=TextBox}}" />
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsPressed, RelativeSource={RelativeSource Self}}"
Value="true" />
<Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type TextBox}}}"
Value="true" />
</MultiDataTrigger.Conditions>
<Setter Property="Background"
TargetName="templateRoot"
Value="{Binding BorderBrush, RelativeSource={RelativeSource AncestorLevel=1, AncestorType=TextBox}}" />
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}"
Value="false" />
<Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type TextBox}}}"
Value="false" />
</MultiDataTrigger.Conditions>
<Setter Property="Background"
TargetName="templateRoot"
Value="{DynamicResource BackgroundColor.Menu.SubCategory}" />
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}"
Value="false" />
<Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type TextBox}}}"
Value="true" />
</MultiDataTrigger.Conditions>
</MultiDataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<StackPanel>
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.HoldTicket.Reason}"
FontWeight="Bold"
Foreground="{DynamicResource FontColor.Menu.Categories}"/>
<ComboBox x:Name="ReasonSelection"
Margin="0 5 0 10"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
BorderBrush="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}"
DropDownClosed="DropDownClosed"
DropDownOpened="DropDownOpened"
SelectedIndex="0">
</ComboBox>
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.HoldTicket.NoEscalation}"
FontWeight="Bold"
Foreground="{DynamicResource FontColor.Menu.Categories}"/>
<CheckBox x:Name="DoNotEscalate"
Style="{DynamicResource ToggleSwitch}"
HorizontalAlignment="Left"
Margin="0 5 0 10"/>
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.HoldTicket.ReminderDate}"
FontWeight="Bold"
Foreground="{DynamicResource FontColor.Menu.Categories}"/>
<StackPanel Orientation="Horizontal">
<DatePicker x:Name="SelectedReminderDateDatePicker"
Style="{DynamicResource DatePickerStyle1}"
CalendarStyle="{DynamicResource DatePickerCalendarStyle1}"
Height="28"
Margin="0 5 10 10"
Padding="0"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
BorderBrush="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}"
SelectedDate="{Binding SelectedDate}"
/>
<ComboBox x:Name="Hour"
Margin="0 5 0 10"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
BorderBrush="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}"
ItemsSource="{Binding HoursRange}"
SelectedItem="{Binding SelectedHour}"
ItemTemplate="{StaticResource TwoDigitHourTemplate}"
DropDownOpened="DropDownOpened"
DropDownClosed="DropDownClosed"
/>
<TextBlock Text=":" Margin="0 5 0 10"
FontWeight="Bold"
Padding="7"
VerticalAlignment="Center"
/>
<ComboBox x:Name="Minute"
Margin="0 5 0 10"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"
BorderBrush="{DynamicResource BackgroundColor.Menu.SubCategory.Hover}"
ItemsSource="{Binding MinutesRange}"
SelectedItem="{Binding SelectedMinute}"
ItemTemplate="{StaticResource TwoDigitHourTemplate}"
DropDownOpened="DropDownOpened"
DropDownClosed="DropDownClosed"
/>
</StackPanel>
<TextBlock Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Dialog.CloseCase.HoldTicket.Comment}"
FontWeight="Bold"
Foreground="{DynamicResource FontColor.Menu.Categories}"/>
<TextBox x:Name="CommentTextBox"
Margin="0 5 0 0"
Style="{DynamicResource Customizable.Editable.TextBox.EditOnly}"
Text="{Binding ElementName=HoldTicketDialogUc, Path=Comment, Mode=TwoWay}"
MinLines="3"
TextWrapping="Wrap"
Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.ValueColumn}"/>
</StackPanel>
</UserControl>

View File

@@ -0,0 +1,278 @@
using C4IT.FASD.Base;
using C4IT.FASD.Cockpit.Communication;
using FasdDesktopUi.Basics.Helper;
using FasdDesktopUi.Basics.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
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 static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
{
/// <summary>
/// Interaction logic for HoldTicketDialog.xaml
/// </summary>
public partial class HoldTicketDialog : UserControl, INotifyPropertyChanged
{
#region DataProvider
public cSupportCaseDataProvider DataProvider
{
get { return (cSupportCaseDataProvider)GetValue(DataProviderProperty); }
set
{
SetValue(DataProviderProperty, value);
}
}
public static readonly DependencyProperty DataProviderProperty =
DependencyProperty.Register("DataProvider", typeof(cSupportCaseDataProvider), typeof(HoldTicketDialog), new PropertyMetadata(null, DataProviderChanged));
private static void DataProviderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is HoldTicketDialog me))
return;
//me.UpdateReasonsComboBoxAsync();
}
#endregion
public event EventHandler CommentChanged;
public string Comment
{
get { return (string)GetValue(CommentProperty); }
set { SetValue(CommentProperty, value); }
}
// Using a DependencyProperty as the backing store for Comment. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CommentProperty =
DependencyProperty.Register("Comment", typeof(string), typeof(HoldTicketDialog), new PropertyMetadata(string.Empty, OnCommentChanged));
private static void OnCommentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (HoldTicketDialog)d;
control.CommentChanged?.Invoke(control, EventArgs.Empty);
}
public event EventHandler SelectedReminderDateChanged;
public DateTime SelectedReminderDate
{
get { return (DateTime)GetValue(SelectedReminderDateProperty); }
set { SetValue(SelectedReminderDateProperty, value); }
}
// Using a DependencyProperty as the backing store for SelectedReminderDate. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SelectedReminderDateProperty =
DependencyProperty.Register("SelectedReminderDate", typeof(DateTime), typeof(HoldTicketDialog), new PropertyMetadata(DateTime.MinValue, OnSelectedReminderDateChanged));
private static void OnSelectedReminderDateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (HoldTicketDialog)d;
control.SelectedReminderDateChanged?.Invoke(control, EventArgs.Empty);
}
private int _selectedHour;
public int SelectedHour
{
get { return _selectedHour; }
set
{
if (_selectedHour != value)
{
_selectedHour = value;
OnPropertyChanged(nameof(SelectedHour));
setReminderDate();
}
}
}
private int _selectedMinute;
public int SelectedMinute
{
get { return _selectedMinute; }
set
{
if (_selectedMinute != value)
{
_selectedMinute = value;
OnPropertyChanged(nameof(SelectedMinute));
setReminderDate();
}
}
}
private DateTime _selectedDate;
public DateTime SelectedDate
{
get { return _selectedDate; }
set
{
if (_selectedDate != value)
{
_selectedDate = value;
OnPropertyChanged(nameof(SelectedDate));
setReminderDate();
}
}
}
public ObservableCollection<int> HoursRange { get; set; }
public ObservableCollection<int> MinutesRange { get; set; }
public HoldTicketDialog(cSupportCaseDataProvider cDataProviderBase)
{
DataProvider = cDataProviderBase;
InitializeComponent();
HoursRange = new ObservableCollection<int>(Enumerable.Range(0, 24).ToList());
MinutesRange = new ObservableCollection<int>(Enumerable.Range(0, 60).ToList());
this.DataContext = this;
SelectedReminderDateDatePicker.DisplayDateStart = DateTime.Now;
SelectedDate = DateTime.Now.AddDays(1).Date;
SelectedHour = DateTime.Now.Hour;
SelectedMinute = DateTime.Now.Minute;
}
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
UpdateReasonsComboBox();
}
private void setReminderDate()
{
SelectedReminderDate = new DateTime(
SelectedDate.Year,
SelectedDate.Month,
SelectedDate.Day,
SelectedHour,
SelectedMinute,
0);
}
private void UpdateReasonsComboBox()
{
try
{
if (DataProvider == null) return;
var resTable = DataProvider.HealthCardDataHelper.HealthCardRawData.GetTableByName("M42Wpm-Pickup-ObjectStateReason", false);
if (resTable == null) return;
if (!resTable.Columns.TryGetValue("name", out var namesColumn) ||
!resTable.Columns.TryGetValue("position", out var positionsColumn) ||
!resTable.Columns.TryGetValue("hidden", out var hiddensColumn) ||
!resTable.Columns.TryGetValue("state", out var statesColumn) ||
!resTable.Columns.TryGetValue("stategroup", out var stateGroupsColumn) ||
!resTable.Columns.TryGetValue("id", out var idsColumn)) return;
var resList = new List<Dictionary<string, object>>();
for (int i = 0; i < idsColumn.Values.Count; i++)
{
if (statesColumn.Values[i] == null || stateGroupsColumn.Values[i] == null) continue;
int? positionValue = null; // Nullabel int für den Fall, dass die Position null ist
int stateValue, stateGroupValue;
// Überprüft, ob positionsColumn.Values[i] null ist
if (positionsColumn.Values[i] != null && int.TryParse(positionsColumn.Values[i].ToString(), out int posVal))
{
positionValue = posVal;
}
if (int.TryParse(statesColumn.Values[i].ToString(), out stateValue) && int.TryParse(stateGroupsColumn.Values[i].ToString(), out stateGroupValue))
{
var eintrag = new Dictionary<string, object>
{
{ "ID", idsColumn.Values[i] },
{ "DisplayName", namesColumn.Values[i] },
{ "Hidden", Convert.ToBoolean(hiddensColumn.Values[i])},
{ "State", stateValue },
{ "StateGroup", stateGroupValue },
{ "Position", positionValue ?? Int32.MaxValue } // Verwende Int32.MaxValue für null Positionen
};
resList.Add(eintrag);
}
}
// Filtern und Sortieren, wobei Einträge ohne Position zuletzt erscheinen
resList = resList.Where(eintrag => !(bool)eintrag["Hidden"] && (int)eintrag["State"] == 203 && (int)eintrag["StateGroup"] == 7)
.OrderBy(eintrag => eintrag["Position"] != null)
.ThenBy(eintrag => (int)eintrag["Position"])
.ToList();
var targetComboBox = ReasonSelection;
targetComboBox.Items.Clear();
foreach (var listValue in resList)
{
targetComboBox.Items.Add(new ComboBoxItem { Content = listValue["DisplayName"], Tag = listValue["ID"] });
}
}
catch (Exception e)
{
LogException(e);
}
}
private void DropDownOpened(object sender, EventArgs e)
{
try
{
if (!(sender is FrameworkElement senderElement))
return;
var parentBorder = cUiElementHelper.GetFirstParentOfType<Border>(senderElement);
cFocusInvoker.InvokeGotFocus(parentBorder, e);
}
catch (Exception E)
{
LogException(E);
}
}
private void DropDownClosed(object sender, EventArgs e)
{
try
{
if (!(sender is FrameworkElement senderElement))
return;
var parentBorder = cUiElementHelper.GetFirstParentOfType<Border>(senderElement);
cFocusInvoker.InvokeLostFocus(parentBorder, e);
}
catch (Exception E)
{
LogException(E);
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

View File

@@ -0,0 +1,313 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.TicketOverview"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
xmlns:models="clr-namespace:FasdDesktopUi.Basics.Models"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
d:DataContext="{d:DesignInstance Type=models:TicketOverviewModel}"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800"
x:Name="_ticketOverview">
<UserControl.Resources>
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter" />
<!-- Style für Labels mit Auswahlzustand -->
<Style x:Key="RoundedSelectedLabelStyle"
TargetType="Label">
<Setter Property="Padding"
Value="5 2 5 4" />
<Setter Property="HorizontalContentAlignment"
Value="Center" />
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Label">
<Grid>
<Border x:Name="BorderElement"
CornerRadius="1.5"
Background="Transparent"
BorderBrush="Transparent"
BorderThickness="0"
Padding="{TemplateBinding Padding}">
<ContentPresenter x:Name="contentPresenter"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
TextElement.Foreground="{TemplateBinding Foreground}" />
</Border>
<Border x:Name="HighlightDot"
Width="8"
Height="8"
Background="{DynamicResource Color.Red}"
BorderBrush="{DynamicResource BackgroundColor.DetailsPage.DataHistory.TitleColumn}"
BorderThickness="1"
CornerRadius="4"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Margin="0,-3,-3,0"
Visibility="Collapsed" />
</Grid>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},Path=(local:TicketOverview.IsSelected)}"
Value="True">
<Setter TargetName="BorderElement"
Property="Background"
Value="{DynamicResource Color.Menu.Icon.Hover}" />
<Setter TargetName="contentPresenter"
Property="TextElement.Foreground"
Value="{DynamicResource BackgroundColor.Menu.MainCategory}" />
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},Path=(local:TicketOverview.IsHighlighted)}"
Value="True">
<Setter TargetName="HighlightDot"
Property="Visibility"
Value="Visible" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Border Background="{DynamicResource BackgroundColor.DetailsPage.DataHistory.TitleColumn}"
CornerRadius="8.5"
Margin="0 19 0 1"
Padding="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- TicketOverview Headers -->
<Label Grid.Row="0"
Grid.Column="1"
HorizontalContentAlignment="Center"
Foreground="{DynamicResource FontColor.DetailsPage.TitleSection.Header}"
Content="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=TicketOverview.Column.Heading.New}"
FontWeight="Bold"
FontSize="12" />
<Label Grid.Row="0"
Grid.Column="2"
HorizontalContentAlignment="Center"
Foreground="{DynamicResource FontColor.DetailsPage.TitleSection.Header}"
Content="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=TicketOverview.Column.Heading.Active}"
FontWeight="Bold"
FontSize="12" />
<Label Grid.Row="0"
Grid.Column="3"
HorizontalContentAlignment="Center"
Foreground="{DynamicResource FontColor.DetailsPage.TitleSection.Header}"
Content="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=TicketOverview.Column.Heading.Critical}"
FontWeight="Bold"
FontSize="12" />
<Label Grid.Row="0"
Grid.Column="4"
HorizontalContentAlignment="Center"
Foreground="{DynamicResource FontColor.DetailsPage.TitleSection.Header}"
Content="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=TicketOverview.Column.Heading.NewInfo}"
FontWeight="Bold"
FontSize="12" />
<!-- Tickets -->
<Label Grid.Row="2"
Grid.Column="0"
Foreground="{DynamicResource FontColor.DetailsPage.TitleSection.Header}"
Content="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=TicketOverview.Row.Heading.Tickets}"
FontWeight="Bold"
FontSize="12" />
<Label Grid.Row="2"
Grid.Column="1"
Content="{Binding TicketsNew}"
Style="{StaticResource RoundedSelectedLabelStyle}"
local:TicketOverview.IsSelected="{Binding TicketsNewSelected, Mode=TwoWay}"
local:TicketOverview.IsHighlighted="{Binding TicketsNewHighlighted}"
ToolTip="{Binding TicketsNewChangeHint}"
Tag="TicketsNewSelected"
MouseLeftButtonUp="Label_MouseLeftButtonUp"
FontWeight="Medium"
Foreground="{DynamicResource Color.Green}"
FontSize="12"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Cursor="Hand" />
<Label Grid.Row="2"
Grid.Column="2"
Content="{Binding TicketsActive}"
Style="{StaticResource RoundedSelectedLabelStyle}"
local:TicketOverview.IsSelected="{Binding TicketsActiveSelected, Mode=TwoWay}"
local:TicketOverview.IsHighlighted="{Binding TicketsActiveHighlighted}"
ToolTip="{Binding TicketsActiveChangeHint}"
Tag="TicketsActiveSelected"
MouseLeftButtonUp="Label_MouseLeftButtonUp"
FontWeight="Medium"
Foreground="{DynamicResource Color.Green}"
FontSize="12"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Cursor="Hand" />
<Label Grid.Row="2"
Grid.Column="3"
Content="{Binding TicketsCritical}"
Style="{StaticResource RoundedSelectedLabelStyle}"
local:TicketOverview.IsSelected="{Binding TicketsCriticalSelected, Mode=TwoWay}"
local:TicketOverview.IsHighlighted="{Binding TicketsCriticalHighlighted}"
ToolTip="{Binding TicketsCriticalChangeHint}"
Tag="TicketsCriticalSelected"
MouseLeftButtonUp="Label_MouseLeftButtonUp"
FontWeight="Medium"
Foreground="{DynamicResource Color.Red}"
FontSize="12"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Cursor="Hand" />
<Label Grid.Row="2"
Grid.Column="4"
Content="{Binding TicketsNewInfo}"
Style="{StaticResource RoundedSelectedLabelStyle}"
local:TicketOverview.IsSelected="{Binding TicketsNewInfoSelected, Mode=TwoWay}"
local:TicketOverview.IsHighlighted="{Binding TicketsNewInfoHighlighted}"
ToolTip="{Binding TicketsNewInfoChangeHint}"
Tag="TicketsNewInfoSelected"
MouseLeftButtonUp="Label_MouseLeftButtonUp"
FontWeight="Medium"
Foreground="{DynamicResource Color.Orange}"
FontSize="12"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Cursor="Hand" />
<!-- Incidents -->
<Label Grid.Row="3"
Grid.Column="0"
Foreground="{DynamicResource FontColor.DetailsPage.TitleSection.Header}"
Content="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=TicketOverview.Row.Heading.Incidents}"
FontWeight="Bold"
FontSize="12" />
<Label Grid.Row="3"
Grid.Column="1"
Content="{Binding IncidentNew}"
Style="{StaticResource RoundedSelectedLabelStyle}"
local:TicketOverview.IsSelected="{Binding IncidentNewSelected, Mode=TwoWay}"
local:TicketOverview.IsHighlighted="{Binding IncidentNewHighlighted}"
ToolTip="{Binding IncidentNewChangeHint}"
Tag="IncidentNewSelected"
MouseLeftButtonUp="Label_MouseLeftButtonUp"
FontWeight="Medium"
Foreground="{DynamicResource Color.Green}"
FontSize="12"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Cursor="Hand" />
<Label Grid.Row="3"
Grid.Column="2"
Content="{Binding IncidentActive}"
Style="{StaticResource RoundedSelectedLabelStyle}"
local:TicketOverview.IsSelected="{Binding IncidentActiveSelected, Mode=TwoWay}"
local:TicketOverview.IsHighlighted="{Binding IncidentActiveHighlighted}"
ToolTip="{Binding IncidentActiveChangeHint}"
Tag="IncidentActiveSelected"
MouseLeftButtonUp="Label_MouseLeftButtonUp"
FontWeight="Medium"
Foreground="{DynamicResource Color.Green}"
FontSize="12"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Cursor="Hand" />
<Label Grid.Row="3"
Grid.Column="3"
Content="{Binding IncidentCritical}"
Style="{StaticResource RoundedSelectedLabelStyle}"
local:TicketOverview.IsSelected="{Binding IncidentCriticalSelected, Mode=TwoWay}"
local:TicketOverview.IsHighlighted="{Binding IncidentCriticalHighlighted}"
ToolTip="{Binding IncidentCriticalChangeHint}"
Tag="IncidentCriticalSelected"
MouseLeftButtonUp="Label_MouseLeftButtonUp"
FontWeight="Medium"
Foreground="{DynamicResource Color.Red}"
FontSize="12"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Cursor="Hand" />
<Label Grid.Row="3"
Grid.Column="4"
Content="{Binding IncidentNewInfo}"
Style="{StaticResource RoundedSelectedLabelStyle}"
local:TicketOverview.IsSelected="{Binding IncidentNewInfoSelected, Mode=TwoWay}"
local:TicketOverview.IsHighlighted="{Binding IncidentNewInfoHighlighted}"
ToolTip="{Binding IncidentNewInfoChangeHint}"
Tag="IncidentNewInfoSelected"
MouseLeftButtonUp="Label_MouseLeftButtonUp"
FontWeight="Medium"
Foreground="{DynamicResource Color.Orange}"
FontSize="12"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Cursor="Hand" />
<!-- Unassigned -->
<Label Grid.Row="4"
Grid.Column="0"
Foreground="{DynamicResource FontColor.DetailsPage.TitleSection.Header}"
Content="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=TicketOverview.Row.Heading.UnassignedTickets}"
FontWeight="Bold"
FontSize="12" />
<Label Grid.Row="4"
Grid.Column="1"
Content="{Binding UnassignedTickets}"
Style="{StaticResource RoundedSelectedLabelStyle}"
local:TicketOverview.IsSelected="{Binding UnassignedTicketsSelected, Mode=TwoWay}"
local:TicketOverview.IsHighlighted="{Binding UnassignedTicketsHighlighted}"
ToolTip="{Binding UnassignedTicketsChangeHint}"
Tag="UnassignedTicketsSelected"
MouseLeftButtonUp="Label_MouseLeftButtonUp"
FontWeight="Medium"
Foreground="{DynamicResource Color.Orange}"
FontSize="12"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Cursor="Hand" />
<Label Grid.Row="4"
Grid.Column="3"
Content="{Binding UnassignedTicketsCritical}"
Style="{StaticResource RoundedSelectedLabelStyle}"
local:TicketOverview.IsSelected="{Binding UnassignedTicketsCriticalSelected, Mode=TwoWay}"
local:TicketOverview.IsHighlighted="{Binding UnassignedTicketsCriticalHighlighted}"
ToolTip="{Binding UnassignedTicketsCriticalChangeHint}"
Tag="UnassignedTicketsCriticalSelected"
MouseLeftButtonUp="Label_MouseLeftButtonUp"
FontWeight="Medium"
Foreground="{DynamicResource Color.Red}"
FontSize="12"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Cursor="Hand" />
</Grid>
</Border>
</UserControl>

View File

@@ -0,0 +1,362 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;
using C4IT.FASD.Cockpit.Communication;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.Services.Models;
using FasdDesktopUi.Pages.SearchPage;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class TicketOverview : UserControl
{
private readonly TicketOverviewModel _viewModel = new TicketOverviewModel();
private bool _isInitialized;
private static readonly (string Key, Action<TicketOverviewModel, int> Setter)[] CategorySetters = new[]
{
("TicketsNew", new Action<TicketOverviewModel, int>((vm, value) => { vm.TicketsNew = value; })),
("TicketsActive", new Action<TicketOverviewModel, int>((vm, value) => { vm.TicketsActive = value; })),
("TicketsCritical", new Action<TicketOverviewModel, int>((vm, value) => { vm.TicketsCritical = value; })),
("TicketsNewInfo", new Action<TicketOverviewModel, int>((vm, value) => { vm.TicketsNewInfo = value; })),
("IncidentNew", new Action<TicketOverviewModel, int>((vm, value) => { vm.IncidentNew = value; })),
("IncidentActive", new Action<TicketOverviewModel, int>((vm, value) => { vm.IncidentActive = value; })),
("IncidentCritical", new Action<TicketOverviewModel, int>((vm, value) => { vm.IncidentCritical = value; })),
("IncidentNewInfo", new Action<TicketOverviewModel, int>((vm, value) => { vm.IncidentNewInfo = value; })),
("UnassignedTickets", new Action<TicketOverviewModel, int>((vm, value) => { vm.UnassignedTickets = value; })),
("UnassignedTicketsCritical", new Action<TicketOverviewModel, int>((vm, value) => { vm.UnassignedTicketsCritical = value; }))
};
private static readonly (string Key, Action<TicketOverviewModel, bool> Setter)[] HighlightSetters = new[]
{
("TicketsNew", new Action<TicketOverviewModel, bool>((vm, value) => { vm.TicketsNewHighlighted = value; })),
("TicketsActive", new Action<TicketOverviewModel, bool>((vm, value) => { vm.TicketsActiveHighlighted = value; })),
("TicketsCritical", new Action<TicketOverviewModel, bool>((vm, value) => { vm.TicketsCriticalHighlighted = value; })),
("TicketsNewInfo", new Action<TicketOverviewModel, bool>((vm, value) => { vm.TicketsNewInfoHighlighted = value; })),
("IncidentNew", new Action<TicketOverviewModel, bool>((vm, value) => { vm.IncidentNewHighlighted = value; })),
("IncidentActive", new Action<TicketOverviewModel, bool>((vm, value) => { vm.IncidentActiveHighlighted = value; })),
("IncidentCritical", new Action<TicketOverviewModel, bool>((vm, value) => { vm.IncidentCriticalHighlighted = value; })),
("IncidentNewInfo", new Action<TicketOverviewModel, bool>((vm, value) => { vm.IncidentNewInfoHighlighted = value; })),
("UnassignedTickets", new Action<TicketOverviewModel, bool>((vm, value) => { vm.UnassignedTicketsHighlighted = value; })),
("UnassignedTicketsCritical", new Action<TicketOverviewModel, bool>((vm, value) => { vm.UnassignedTicketsCriticalHighlighted = value; }))
};
private static readonly (string Key, Action<TicketOverviewModel, string> Setter)[] ChangeHintSetters = new[]
{
("TicketsNew", new Action<TicketOverviewModel, string>((vm, value) => { vm.TicketsNewChangeHint = value; })),
("TicketsActive", new Action<TicketOverviewModel, string>((vm, value) => { vm.TicketsActiveChangeHint = value; })),
("TicketsCritical", new Action<TicketOverviewModel, string>((vm, value) => { vm.TicketsCriticalChangeHint = value; })),
("TicketsNewInfo", new Action<TicketOverviewModel, string>((vm, value) => { vm.TicketsNewInfoChangeHint = value; })),
("IncidentNew", new Action<TicketOverviewModel, string>((vm, value) => { vm.IncidentNewChangeHint = value; })),
("IncidentActive", new Action<TicketOverviewModel, string>((vm, value) => { vm.IncidentActiveChangeHint = value; })),
("IncidentCritical", new Action<TicketOverviewModel, string>((vm, value) => { vm.IncidentCriticalChangeHint = value; })),
("IncidentNewInfo", new Action<TicketOverviewModel, string>((vm, value) => { vm.IncidentNewInfoChangeHint = value; })),
("UnassignedTickets", new Action<TicketOverviewModel, string>((vm, value) => { vm.UnassignedTicketsChangeHint = value; })),
("UnassignedTicketsCritical", new Action<TicketOverviewModel, string>((vm, value) => { vm.UnassignedTicketsCriticalChangeHint = value; }))
};
private readonly Dictionary<string, HighlightInfo> _personalHighlightStates = new Dictionary<string, HighlightInfo>(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<string, HighlightInfo> _roleHighlightStates = new Dictionary<string, HighlightInfo>(StringComparer.OrdinalIgnoreCase);
#region Properties
public static TicketOverview Instance { get; private set; }
public static readonly DependencyProperty IsSelectedProperty =
DependencyProperty.RegisterAttached(
"IsSelected",
typeof(bool),
typeof(TicketOverview),
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public static void SetIsSelected(UIElement element, bool value) =>
element.SetValue(IsSelectedProperty, value);
public static bool GetIsSelected(UIElement element) =>
(bool)element.GetValue(IsSelectedProperty);
public static readonly DependencyProperty IsHighlightedProperty =
DependencyProperty.RegisterAttached(
"IsHighlighted",
typeof(bool),
typeof(TicketOverview),
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public static void SetIsHighlighted(UIElement element, bool value) =>
element.SetValue(IsHighlightedProperty, value);
public static bool GetIsHighlighted(UIElement element) =>
(bool)element.GetValue(IsHighlightedProperty);
#endregion
public delegate void TicketOverviewSelectionRequestedEventHandler(object sender, TicketOverviewSelectionRequestedEventArgs e);
public static readonly RoutedEvent SelectionRequestedEvent =
EventManager.RegisterRoutedEvent(
"SelectionRequested",
RoutingStrategy.Bubble,
typeof(TicketOverviewSelectionRequestedEventHandler),
typeof(TicketOverview));
public event TicketOverviewSelectionRequestedEventHandler SelectionRequested
{
add { AddHandler(SelectionRequestedEvent, value); }
remove { RemoveHandler(SelectionRequestedEvent, value); }
}
#region Initial
public TicketOverview()
{
InitializeComponent();
DataContext = _viewModel;
Loaded += TicketOverview_Loaded;
Instance = this;
}
#endregion
#region Click-Events
private void Label_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (!(sender is Label lbl) || !(lbl.Tag is string propName) || !(DataContext is TicketOverviewModel vm))
return;
var vmType = vm.GetType();
var boolProp = vmType.GetProperty(propName);
if (boolProp?.PropertyType != typeof(bool))
return;
var wasSelected = (bool)(boolProp.GetValue(vm) ?? false);
var keyBase = propName.EndsWith("Selected", StringComparison.Ordinal)
? propName.Substring(0, propName.Length - "Selected".Length)
: propName;
int count = 0;
var countProp = vmType.GetProperty(keyBase) ?? vmType.GetProperty(keyBase + "Count");
if (countProp?.PropertyType == typeof(int))
count = (int)(countProp.GetValue(vm) ?? 0);
if (count <= 0)
{
boolProp.SetValue(vm, false);
ClearHighlight(keyBase, SearchPageView.Instance?.IsFilterChecked == true);
SearchPageView.Instance?.CloseTicketOverviewResults();
return;
}
if (wasSelected)
{
boolProp.SetValue(vm, false);
ClearHighlight(keyBase, SearchPageView.Instance?.IsFilterChecked == true);
SearchPageView.Instance?.CloseTicketOverviewResults();
return;
}
vm.ResetSelection(); // setzt alle ...Selected auf false
boolProp.SetValue(vm, true);
bool useRoleScope = false;
try { useRoleScope = SearchPageView.Instance?.IsFilterChecked == true; } catch { }
ClearHighlight(keyBase, useRoleScope);
var args = new TicketOverviewSelectionRequestedEventArgs(
SelectionRequestedEvent,
this,
keyBase,
useRoleScope,
count
);
RaiseEvent(args);
}
#endregion
#region Methods
private async void TicketOverview_Loaded(object sender, RoutedEventArgs e)
{
if (_isInitialized)
return;
_isInitialized = true;
bool filter = SearchPageView.Instance?.IsFilterChecked == true;
await UpdateDataContextAsync(filter);
if (SearchPageView.Instance != null)
{
SearchPageView.Instance.FilterToggleCheckedChanged += async (s, isChecked) =>
{
try
{
await UpdateDataContextAsync(isChecked);
}
catch (Exception ex)
{
Debug.WriteLine($"[TicketOverview] Refresh after toggle failed: {ex}");
}
};
}
}
public void ResetSelection()
{
if (DataContext is TicketOverviewModel vm)
vm.ResetSelection();
}
/// <summary>
/// Prüft welche Daten für die Ansicht geladen werden sollen
/// Wenn UseRoledTickets = true dann Rolebased Tickets und Incidents laden
/// Wenn UseRoledTickets = false dann meine Eigenen Tickets und Incidents laden
/// </summary>
/// <param name="useRoleTickets"></param>
private Task UpdateDataContextAsync(bool useRoleTickets)
{
return RefreshCountsAsync(useRoleTickets);
}
private async Task RefreshCountsAsync(bool useRoleTickets)
{
var communication = cFasdCockpitCommunicationBase.Instance;
var counts = CategorySetters.ToDictionary(item => item.Key, _ => 0);
if (communication != null)
{
var tasks = CategorySetters.ToDictionary(
item => item.Key,
item => communication.GetTicketOverviewRelations(item.Key, useRoleTickets, 0));
foreach (var kvp in tasks)
{
try
{
var relations = await kvp.Value.ConfigureAwait(false);
counts[kvp.Key] = relations?.Count ?? 0;
}
catch (Exception ex)
{
Debug.WriteLine($"[TicketOverview] Failed to load count for '{kvp.Key}': {ex}");
counts[kvp.Key] = 0;
}
}
}
await Dispatcher.InvokeAsync(() =>
{
foreach (var (key, setter) in CategorySetters)
{
setter(_viewModel, counts[key]);
}
_viewModel.ResetSelection();
SearchPageView.Instance?.CloseTicketOverviewResults();
UpdateHighlightState(useRoleTickets);
}, DispatcherPriority.Background);
}
public void UpdateCounts(IDictionary<string, int> counts, bool useRoleTickets)
{
if (counts == null)
return;
Dispatcher.Invoke(() =>
{
foreach (var (key, setter) in CategorySetters)
{
counts.TryGetValue(key, out var value);
setter(_viewModel, value);
}
UpdateHighlightState(useRoleTickets);
}, DispatcherPriority.Background);
}
public void SetHighlights(IEnumerable<TileCountChange> changes, bool useRoleTickets)
{
if (changes != null)
{
foreach (var change in changes)
{
if (change.Delta <= 0)
continue;
var target = change.Scope == TileScope.Personal ? _personalHighlightStates : _roleHighlightStates;
if (!target.TryGetValue(change.Key, out var info))
{
info = new HighlightInfo(change.OldCount);
target[change.Key] = info;
}
info.Current = change.NewCount;
if (info.Current == info.Baseline)
target.Remove(change.Key);
}
}
UpdateHighlightState(useRoleTickets);
}
public void RefreshHighlightState(bool useRoleTickets)
{
UpdateHighlightState(useRoleTickets);
}
private void UpdateHighlightState(bool useRoleTickets)
{
Dispatcher.Invoke(() =>
{
var highlightStates = useRoleTickets ? _roleHighlightStates : _personalHighlightStates;
foreach (var (key, setter) in HighlightSetters)
{
setter(_viewModel, highlightStates.ContainsKey(key));
}
foreach (var (key, setter) in ChangeHintSetters)
{
if (highlightStates.TryGetValue(key, out var info))
setter(_viewModel, FormatDelta(info.Current - info.Baseline));
else
setter(_viewModel, null);
}
}, DispatcherPriority.Background);
}
private void ClearHighlight(string key, bool useRoleScope)
{
var highlightStates = useRoleScope ? _roleHighlightStates : _personalHighlightStates;
if (!highlightStates.Remove(key))
return;
UpdateHighlightState(useRoleScope);
}
#endregion
private static string FormatDelta(int delta)
{
if (delta == 0)
return null;
var prefix = delta > 0 ? "+" : string.Empty;
return prefix + delta.ToString();
}
private sealed class HighlightInfo
{
public HighlightInfo(int baseline)
{
Baseline = baseline;
Current = baseline;
}
public int Baseline { get; }
public int Current { get; set; }
}
}
}

View File

@@ -0,0 +1,121 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.TimerView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:config="clr-namespace:C4IT.FASD.Base;assembly=F4SD-Cockpit-Client-Base"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:vd="clr-namespace:FasdDesktopUi.Basics.Converter"
xmlns:vc="clr-namespace:C4IT.MultiLanguage;assembly=F4SD-Cockpit-Client-Base"
mc:Ignorable="d"
Initialized="UserControl_Initialized">
<UserControl.Resources>
<vd:LanguageDefinitionsConverter x:Key="LanguageConverter"/>
<!-- Style für den Hovereffekt -->
<Style x:Key="PauseButtonHoverStyle" TargetType="Border">
<Setter Property="Background" Value="Transparent"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{DynamicResource Background.Menu.Icon.Hover}"/>
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Border Padding="8"
Grid.Column="0"
CornerRadius="10"
Background="Transparent">
<TextBlock x:Name="TimerControl"
VerticalAlignment="Center"
FontFamily="Calibri"
FontSize="16"
Margin="0 -10 10 -10"
ToolTip="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=TimerView.Time.ToolTip}"
Foreground="{DynamicResource Color.Menu.Icon}" />
</Border>
<Border Padding="20 5 5 5"
Grid.Column="1"
Width="Auto"
Height="33"
Cursor="Hand"
HorizontalAlignment="Center"
VerticalAlignment="Center"
CornerRadius="5"
Margin="-5 0 0 0"
ToolTip="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=TimerView.Pausebutton.ToolTip}"
Style="{DynamicResource PauseButtonHoverStyle}"
MouseLeftButtonUp="Border_MouseLeftButtonUp" TouchDown="Border_TouchDown"
>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<ico:AdaptableIcon Grid.Column="1"
x:Name="PauseButton"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="-15 0 5 0"
Panel.ZIndex="2"
BorderPadding="0"
IconHeight="22"
IconWidth="22"
SelectedMaterialIcon="ic_pause_circle_outline"
IconBackgroundColor="Transparent">
<ico:AdaptableIcon.Resources>
<Style TargetType="ico:AdaptableIcon"
BasedOn="{StaticResource Menu.MenuBar.PinnedIcon.Pinned}">
<Setter Property="PrimaryIconColor"
Value="{DynamicResource FontColor.Menu.Categories}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorLevel=1, AncestorType=Border}, Path=IsMouseOver}"
Value="True">
<Setter Property="PrimaryIconColor"
Value="{DynamicResource FontColor.Menu.Categories.Hover}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ico:AdaptableIcon.Resources>
</ico:AdaptableIcon>
<TextBlock Grid.Column="2" Text="Pause">
<TextBlock.Resources>
<Style TargetType="TextBlock">
<Setter Property="VerticalAlignment"
Value="Center"/>
<Setter Property="HorizontalAlignment"
Value="Center"/>
<Setter Property="FontSize"
Value="16"/>
<Setter Property="Foreground"
Value="{DynamicResource FontColor.Menu.Categories}"/>
<Setter Property="Margin"
Value="0 0 0 2"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorLevel=1, AncestorType=Border}, Path=IsMouseOver}"
Value="True">
<Setter Property="Foreground"
Value="{DynamicResource FontColor.Menu.Categories.Hover}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Resources>
</TextBlock>
</StackPanel>
</Border>
</Grid>
</UserControl>

View File

@@ -0,0 +1,225 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;
using C4IT.FASD.Base;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class TimerView : UserControl
{
#region Fields
public event EventHandler<EventArgs> OnPauseStarted;
private static List<DateTime> startTimes = new List<DateTime>();
private static List<DateTime> endTimes = new List<DateTime>();
private static List<DateTime> pausedTimesStart = new List<DateTime>();
private static List<DateTime> pausedTimesEnd = new List<DateTime>();
public static List<cF4SDCaseTime> caseTimes = new List<cF4SDCaseTime>();
private static Dictionary<string, object> finalWorkingTimes = new Dictionary<string, object>();
private static DispatcherTimer timer;
private static TimeSpan elapsedTime;
private static TimeSpan totalPausedTime = TimeSpan.Zero;
private static TimeSpan pauseDuration;
#endregion
#region
public TimerView()
{
InitializeComponent();
}
public static void ResetTimer()
{
startTimes.Clear();
endTimes.Clear();
pausedTimesEnd.Clear();
pausedTimesStart.Clear();
finalWorkingTimes.Clear();
elapsedTime = TimeSpan.Zero;
caseTimes.Clear();
StartTimer();
}
public static void StartTimer()
{
try
{
startTimes?.Add(DateTime.UtcNow);
timer?.Start();
}
catch (Exception E)
{
LogException(E);
}
}
public void StopTimer()
{
try
{
endTimes?.Add(DateTime.UtcNow);
timer?.Stop();
UpdateTimerControl();
}
catch (Exception E)
{
LogException(E);
}
}
private void UserControl_Initialized(object sender, EventArgs e)
{
try
{
ResetTimer();
timer = new DispatcherTimer(TimeSpan.FromSeconds(1.0), DispatcherPriority.Loaded, new EventHandler((s, args) =>
{
try { UpdateTimerControl(); }
catch { }
}),
Dispatcher.CurrentDispatcher);
}
catch (Exception E)
{
LogException(E);
}
}
private void UpdateTimerControl()
{
try
{
TimerControl.Text = elapsedTime.ToString(@"hh\:mm\:ss");
elapsedTime = elapsedTime.Add(TimeSpan.FromSeconds(1.0));
}
catch (Exception E)
{
LogException(E);
}
}
public static Dictionary<string, object> GetWorkTimes()
{
try
{
var currentDate = DateTime.Now.Date.ToString("d");
var startDateTime = startTimes.First();
var endDateTime = DateTime.UtcNow;
var bruttoWorkingTime = TimeSpan.Zero;
var nettoWorkingTime = TimeSpan.Zero;
if (pausedTimesStart.Count == 0)
{
totalPausedTime = TimeSpan.Zero;
}
if (pausedTimesEnd.Count > 0)
{
totalPausedTime = TimeSpan.Zero;
for (int i = 0; i < pausedTimesStart.Count; i++)
{
var start = pausedTimesStart[i];
var end = pausedTimesEnd[i];
pauseDuration = end - start;
totalPausedTime += pauseDuration;
}
}
bruttoWorkingTime = endDateTime - startDateTime;
nettoWorkingTime = bruttoWorkingTime - totalPausedTime;
finalWorkingTimes = new Dictionary<string, object>()
{
{"CurrentDate", currentDate},
{"StartTime", startTimes.First()},
{"EndTime", endDateTime },
{"BruttoWorkingTime", bruttoWorkingTime },
{"NettoWorkingTime", nettoWorkingTime.TotalSeconds },
{"TotalPausedTime", totalPausedTime }
};
}
catch (Exception E)
{
LogException(E);
}
return finalWorkingTimes;
}
#endregion
#region Click-Events
public void EndPause()
{
try
{
if (timer?.IsEnabled == true)
return;
timer?.Start();
pausedTimesEnd?.Add(DateTime.UtcNow);
caseTimes.Add(new cF4SDCaseTime()
{
StatusId = CaseStatus.InProgress,
CaseTime = DateTime.UtcNow
});
}
catch (Exception E)
{
LogException(E);
}
}
private void PauseButton_Click()
{
try
{
timer?.Stop();
pausedTimesStart?.Add(DateTime.UtcNow);
caseTimes.Add(new cF4SDCaseTime()
{
StatusId = CaseStatus.OnHold,
CaseTime = DateTime.UtcNow
});
if (OnPauseStarted != null)
OnPauseStarted?.Invoke(this, new EventArgs());
}
catch (Exception E)
{
LogException(E);
}
}
private void Border_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
PauseButton_Click();
}
#endregion
private void Border_TouchDown(object sender, TouchEventArgs e)
{
PauseButton_Click();
}
}
}

View File

@@ -0,0 +1,12 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.TimerViewStartStop"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,28 @@
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;
namespace FasdDesktopUi.Basics.UserControls
{
/// <summary>
/// Interaction logic for TimerViewStartStop.xaml
/// </summary>
public partial class TimerViewStartStop : UserControl
{
public TimerViewStartStop()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,186 @@
<UserControl x:Class="FasdDesktopUi.Basics.UserControls.YesNoButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:uc="clr-namespace:FasdDesktopUi.Basics.UserControls"
xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
xmlns:vc="clr-namespace:FasdDesktopUi.Basics.Converter"
x:Name="YesNoButtons"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisibility"/>
</UserControl.Resources>
<Grid>
<Grid.Resources>
<vc:LanguageDefinitionsConverter x:Key="LanguageConverter"/>
<Style TargetType="ico:AdaptableIcon">
<Setter Property="IconWidth"
Value="125"/>
<Setter Property="PrimaryIconColor"
Value="{DynamicResource Color.Menu.Icon}"/>
<Setter Property="HorizontalAlignment"
Value="Center"/>
</Style>
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment"
Value="Left"/>
<Setter Property="VerticalAlignment"
Value="Center"/>
</Style>
<Style TargetType="StackPanel">
<Setter Property="Cursor"
Value="Hand"/>
<EventSetter Event="MouseLeftButtonUp"
Handler="DialogButton_MouseLeftButtonUp"/>
<EventSetter Event="TouchDown"
Handler="DialogButton_TouchDown"/>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border>
<StackPanel x:Name="StackPanelConfirm"
Grid.Column="0"
Orientation="Horizontal"
Margin="0 10 0 0"
HorizontalAlignment="Center">
<StackPanel.Tag>
<sys:Boolean>True</sys:Boolean>
</StackPanel.Tag>
<StackPanel.Style>
<Style TargetType="StackPanel"
BasedOn="{StaticResource {x:Type StackPanel}}"/>
</StackPanel.Style>
<ico:AdaptableIcon x:Name="ConfirmButton"
SelectedMaterialIcon="ic_check"
Visibility="{Binding ElementName=YesNoButtons, Path=YesNoButtonsVisible, Converter={StaticResource BoolToVisibility}}">
<ico:AdaptableIcon.Resources>
<Style TargetType="ico:AdaptableIcon"
BasedOn="{StaticResource {x:Type ico:AdaptableIcon}}">
<Setter Property="PrimaryIconColor"
Value="{DynamicResource Color.Menu.Icon}"/>
<Setter Property="BorderPadding"
Value="2.5"/>
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="PrimaryIconColor"
Value="{DynamicResource Color.Green}"/>
<Setter Property="IconBackgroundColor"
Value="{DynamicResource BackgroundColor.Menu.MainCategory}"/>
</Trigger>
</Style.Triggers>
</Style>
</ico:AdaptableIcon.Resources>
</ico:AdaptableIcon>
<TextBlock x:Name="ConfirmText"
Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Global.Yes}"
Margin="5 0 0 0"
Padding="30 10 30 10"
FontWeight="Bold"
VerticalAlignment="Center"
Visibility="{Binding ElementName=YesNoButtons, Path=YesNoTextVisible, Converter={StaticResource BoolToVisibility}}">
<TextBlock.Style>
<Style TargetType="TextBlock"
BasedOn="{StaticResource {x:Type TextBlock}}">
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Foreground"
Value="{DynamicResource Color.Green}"/>
<Setter Property="Background"
Value="{DynamicResource BackgroundColor.Menu.MainCategory}"/>
</Trigger>
<Trigger Property="IsMouseOver"
Value="False">
<Setter Property="Foreground"
Value="{DynamicResource FontColor.Menu.Categories}"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
</Border>
<StackPanel x:Name="StackPanelCancel"
Grid.Column="1"
Margin="0 10 0 0"
Orientation="Horizontal"
HorizontalAlignment="Center">
<StackPanel.Tag>
<sys:Boolean>False</sys:Boolean>
</StackPanel.Tag>
<StackPanel.Style>
<Style TargetType="StackPanel"
BasedOn="{StaticResource {x:Type StackPanel}}"/>
</StackPanel.Style>
<ico:AdaptableIcon x:Name="CancelButton"
SelectedMaterialIcon="ic_close"
Visibility="{Binding ElementName=YesNoButtons, Path=YesNoButtonsVisible, Converter={StaticResource BoolToVisibility}}">
<ico:AdaptableIcon.Resources>
<Style TargetType="ico:AdaptableIcon"
BasedOn="{StaticResource {x:Type ico:AdaptableIcon}}">
<Setter Property="PrimaryIconColor"
Value="{DynamicResource Color.Menu.Icon}"/>
<Setter Property="BorderPadding"
Value="2.5"/>
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="PrimaryIconColor"
Value="{DynamicResource Color.Red}"/>
<Setter Property="IconBackgroundColor"
Value="{DynamicResource BackgroundColor.Menu.MainCategory}"/>
</Trigger>
</Style.Triggers>
</Style>
</ico:AdaptableIcon.Resources>
</ico:AdaptableIcon>
<TextBlock x:Name="CancelText"
Text="{Binding Converter={StaticResource LanguageConverter}, ConverterParameter=Global.No}"
Margin="5 0 0 0"
Padding="30 10 30 10"
FontWeight="Bold"
VerticalAlignment="Center"
Visibility="{Binding ElementName=YesNoButtons, Path=YesNoTextVisible, Converter={StaticResource BoolToVisibility}}">
<TextBlock.Style>
<Style TargetType="TextBlock"
BasedOn="{StaticResource {x:Type TextBlock}}">
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Foreground"
Value="{DynamicResource Color.Red}"/>
<Setter Property="Background"
Value="{DynamicResource BackgroundColor.Menu.MainCategory}"/>
</Trigger>
<Trigger Property="IsMouseOver"
Value="False">
<Setter Property="Foreground"
Value="{DynamicResource FontColor.Menu.Categories}"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
<ico:AdaptableIcon
Grid.ColumnSpan="999"
BorderPadding="0"
VerticalAlignment="Center"
HorizontalAlignment="Center"
IconHeight="20"
IconWidth="20"
SelectedInternGif="loadingSpinner"
Margin="0,10,0,0"
Visibility="{Binding ElementName=YesNoButtons, Path=IsClosingBusy, Converter={StaticResource BoolToVisibility}}"
/>
</Grid>
</UserControl>

View File

@@ -0,0 +1,226 @@
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using FasdDesktopUi.Basics.CustomEvents;
using static C4IT.Logging.cLogManager;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class YesNoButton : UserControl, INotifyPropertyChanged
{
#region HasYesNoButtons
public bool HasYesNoButtons
{
get { return (bool)GetValue(HasYesNoButtonsProperty); }
set { SetValue(HasYesNoButtonsProperty, value); }
}
public static readonly DependencyProperty HasYesNoButtonsProperty =
DependencyProperty.Register("HasYesNoButtons", typeof(bool), typeof(YesNoButton), new PropertyMetadata(false, new PropertyChangedCallback(HasYesNoButtonsChangedCallback)));
public static void HasYesNoButtonsChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is YesNoButton _this))
return;
_this.YesNoButtonsVisible = _this.HasYesNoButtons && !_this.IsClosingBusy;
return;
}
#endregion
#region HasYesNoText
public bool HasYesNoText
{
get { return (bool)GetValue(HasYesNoTextProperty); }
set { SetValue(HasYesNoTextProperty, value); }
}
public static readonly DependencyProperty HasYesNoTextProperty =
DependencyProperty.Register("HasYesNoText", typeof(bool), typeof(YesNoButton), new PropertyMetadata(false, new PropertyChangedCallback(HasYesNoTextChangedCallback)));
public static void HasYesNoTextChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is YesNoButton _this))
return;
_this.YesNoTextVisible = _this.HasYesNoText && !_this.IsClosingBusy;
return;
}
#endregion
#region ClosingBusy
public bool IsClosingBusy
{
get { return (bool)GetValue(IsClosingBusyProperty); }
set { SetValue(IsClosingBusyProperty, value); }
}
public static readonly DependencyProperty IsClosingBusyProperty =
DependencyProperty.Register("IsClosingBusy", typeof(bool), typeof(YesNoButton), new PropertyMetadata(false, new PropertyChangedCallback(IsClosingBusyChangedCallback)));
public static void IsClosingBusyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is YesNoButton _this))
return;
_this.YesNoTextVisible = _this.HasYesNoText && !_this.IsClosingBusy;
_this.YesNoButtonsVisible = _this.HasYesNoButtons && !_this.IsClosingBusy;
return;
}
#endregion
#region internal bindings
private bool _YesNoButtonsVisible = false;
public bool YesNoButtonsVisible
{
get { return _YesNoButtonsVisible; }
set
{
if (value != _YesNoButtonsVisible)
{
_YesNoButtonsVisible = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("YesNoButtonsVisible"));
}
}
}
private bool _YesNoTextVisible = false;
public bool YesNoTextVisible
{
get { return _YesNoTextVisible; }
set
{
if (value != _YesNoTextVisible)
{
_YesNoTextVisible = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("YesNoTextVisible"));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
private bool ButtonOkEnabled = true;
private bool ButtonCancelEnabled = true;
public delegate void BooleanEventHandlerDelegate(object sender, BooleanEventArgs e);
public static readonly RoutedEvent ButtonHasBeenClickedEvent = EventManager.RegisterRoutedEvent("ButtonHasBeenClicked", RoutingStrategy.Bubble, typeof(BooleanEventHandlerDelegate), typeof(YesNoButton));
public event BooleanEventHandlerDelegate ButtonHasBeenClicked
{
add { AddHandler(ButtonHasBeenClickedEvent, value); }
remove { RemoveHandler(ButtonHasBeenClickedEvent, value); }
}
public YesNoButton()
{
InitializeComponent();
}
private void DialogButton_Click(object sender)
{
try
{
if (!(sender is FrameworkElement senderElement))
return;
if (!(senderElement.Tag is bool tagValue))
return;
if (tagValue && !ButtonOkEnabled || !tagValue && !ButtonCancelEnabled)
return;
RaiseEvent(new BooleanEventArgs(ButtonHasBeenClickedEvent, tagValue));
}
catch (Exception E)
{
LogException(E);
}
}
private void DialogButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
DialogButton_Click(sender);
}
private void DialogButton_TouchDown(object sender, TouchEventArgs e)
{
DialogButton_Click(sender);
}
public void SetButtonStateYes(bool Enabled, string MouseOverMessage)
{
var _h = this.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
ToolTip _tt = null;
if (!string.IsNullOrEmpty(MouseOverMessage))
{
_tt = new ToolTip();
_tt.Content = MouseOverMessage;
}
if (YesNoButtonsVisible)
ConfirmButton.IsEnabled = Enabled;
if (YesNoTextVisible)
ConfirmText.IsEnabled = Enabled;
StackPanelConfirm.ToolTip = _tt;
ButtonOkEnabled = Enabled;
}
catch (Exception E)
{
LogException(E);
}
}));
}
public void SetButtonStateNo(bool Enabled, string MouseOverMessage)
{
var _h = this.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
ToolTip _tt = null;
if (!string.IsNullOrEmpty(MouseOverMessage))
{
_tt = new ToolTip();
_tt.Content = MouseOverMessage;
}
if (YesNoButtonsVisible)
CancelButton.IsEnabled = Enabled;
if (YesNoTextVisible)
CancelText.IsEnabled = Enabled;
StackPanelCancel.ToolTip = _tt;
ButtonCancelEnabled = Enabled;
}
catch (Exception E)
{
LogException(E);
}
}));
}
}
}