diff options
| author | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2020-02-21 17:45:40 +0200 |
|---|---|---|
| committer | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2020-02-21 17:45:40 +0200 |
| commit | a0820b3cde386b4b59c2eb3141493b5e02277485 (patch) | |
| tree | b221e729cb42eeb6e1e3fffd7434dd21e4215d48 /Software/Visual_Studio | |
| parent | 229a982d232b818ec0260d25b86451b7726f6061 (diff) | |
| download | Tango-a0820b3cde386b4b59c2eb3141493b5e02277485.tar.gz Tango-a0820b3cde386b4b59c2eb3141493b5e02277485.zip | |
FSE..
Diffstat (limited to 'Software/Visual_Studio')
24 files changed, 934 insertions, 112 deletions
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/AutoComplete/AutoCompleteSource.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/AutoComplete/AutoCompleteSource.cs new file mode 100644 index 000000000..99dab1a25 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/AutoComplete/AutoCompleteSource.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.AutoComplete.Editors; + +namespace Tango.FSE.Common.AutoComplete +{ + public class AutoCompleteSource<T> : ISuggestionProvider + { + private Func<String, List<T>> _filter; + + public AutoCompleteSource(Func<String, List<T>> filter) + { + _filter = filter; + } + + public IEnumerable GetSuggestions(string filter) + { + return _filter(filter); + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/EventTriggerActions/SetterAction.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/EventTriggerActions/SetterAction.cs new file mode 100644 index 000000000..a0704e2bf --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/EventTriggerActions/SetterAction.cs @@ -0,0 +1,101 @@ +using System; +using System.ComponentModel; +using System.Reflection; +using System.Windows; +using System.Windows.Interactivity; + + +namespace Tango.FSE.Common.EventTriggerActions +{ + /// <summary> + /// Sets a specified property to a value when invoked. + /// </summary> + public class SetterAction : TargetedTriggerAction<FrameworkElement> + { + #region Properties + + #region PropertyName + + /// <summary> + /// Property that is being set by this setter. + /// </summary> + public string PropertyName + { + get { return (string)GetValue(PropertyNameProperty); } + set { SetValue(PropertyNameProperty, value); } + } + + public static readonly DependencyProperty PropertyNameProperty = + DependencyProperty.Register("PropertyName", typeof(string), typeof(SetterAction), + new PropertyMetadata(String.Empty)); + + #endregion + + #region Value + + /// <summary> + /// Property value that is being set by this setter. + /// </summary> + public object Value + { + get { return (object)GetValue(ValueProperty); } + set { SetValue(ValueProperty, value); } + } + + public static readonly DependencyProperty ValueProperty = + DependencyProperty.Register("Value", typeof(object), typeof(SetterAction), + new PropertyMetadata(null)); + + #endregion + + #endregion + + #region Overrides + + protected override void Invoke(object parameter) + { + var target = TargetObject ?? AssociatedObject; + + var targetType = target.GetType(); + + var property = targetType.GetProperty(PropertyName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance); + if (property == null) + throw new ArgumentException(String.Format("Property not found: {0}", PropertyName)); + + if (property.CanWrite == false) + throw new ArgumentException(String.Format("Property is not settable: {0}", PropertyName)); + + object convertedValue; + + if (Value == null) + convertedValue = null; + + else + { + var valueType = Value.GetType(); + var propertyType = property.PropertyType; + + if (valueType == propertyType) + convertedValue = Value; + + else + { + var propertyConverter = TypeDescriptor.GetConverter(propertyType); + + if (propertyConverter.CanConvertFrom(valueType)) + convertedValue = propertyConverter.ConvertFrom(Value); + + else if (valueType.IsSubclassOf(propertyType)) + convertedValue = Value; + + else + throw new ArgumentException(String.Format("Cannot convert type '{0}' to '{1}'.", valueType, propertyType)); + } + } + + property.SetValue(target, convertedValue); + } + + #endregion + } +}
\ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEDialogViewVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEDialogViewVM.cs index a5137b9b5..e5bc8f8e8 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEDialogViewVM.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEDialogViewVM.cs @@ -3,12 +3,15 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using Tango.Settings; using Tango.SharedUI; namespace Tango.FSE.Common { public class FSEDialogViewVM : DialogViewVM { + protected FSESettings Settings { get; set; } + private bool _autoMode; /// <summary> /// Will apply the default cancel and OK buttons. @@ -19,6 +22,16 @@ namespace Tango.FSE.Common set { _autoMode = value; RaisePropertyChangedAuto(); } } + private bool _hasDefault; + /// <summary> + /// Makes the OK button press by default. + /// </summary> + public bool HasDefault + { + get { return _hasDefault; } + set { _hasDefault = value; RaisePropertyChangedAuto(); } + } + private String _okText; /// <summary> /// Gets or sets the OK button text. @@ -45,6 +58,7 @@ namespace Tango.FSE.Common public FSEDialogViewVM() : base() { AutoMode = true; + Settings = SettingsManager.Default.GetOrCreate<FSESettings>(); } } } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSESettings.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSESettings.cs index 24a08c55e..7f3754200 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSESettings.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSESettings.cs @@ -46,6 +46,16 @@ namespace Tango.FSE.Common public String LastEnvironmentId { get; set; } /// <summary> + /// Gets or sets the last selected machine on the connection pane. + /// </summary> + public String LastSelectedMachine { get; set; } + + /// <summary> + /// Gets or sets the last virtualized machine serial number. + /// </summary> + public String LastVirtualizedMachineSerialNumber { get; set; } + + /// <summary> /// Initializes a new instance of the <see cref="FSESettings"/> class. /// </summary> public FSESettings() diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Colors.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Colors.xaml index cd7c03cf4..6334577cc 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Colors.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Colors.xaml @@ -9,7 +9,7 @@ <Color x:Key="FSE_PrimaryBackgroundLighterColor">#505050</Color> <Color x:Key="FSE_PrimaryForegroundColor">#EEEEEE</Color> <Color x:Key="FSE_GrayColor">#A0A0A0</Color> - <Color x:Key="FSE_SemiTransparentColor">#45000000</Color> + <Color x:Key="FSE_SemiTransparentColor">#76000000</Color> <Color x:Key="FSE_BorderColor">#707070</Color> <Color x:Key="FSE_PrimaryAccentColor">#03A9F4</Color> @@ -18,6 +18,11 @@ <Color x:Key="FSE_SuccessColor">#6DFF72</Color> <Color x:Key="FSE_MessageBoxTitleHeaderBackgroundColor">#404040</Color> + <Color x:Key="FSE_UsbColor">#FF6F6F</Color> + <Color x:Key="FSE_WifiColor">#78E959</Color> + <Color x:Key="FSE_SignalRColor">#6DDAFF</Color> + <Color x:Key="FSE_EmulatorColor">#F3FF6D</Color> + <!--BRUSHES--> <SolidColorBrush x:Key="FSE_PrimaryBackgroundDarkBrush" Color="{StaticResource FSE_PrimaryBackgroundDarkColor}"></SolidColorBrush> <SolidColorBrush x:Key="FSE_PrimaryBackgroundBrush" Color="{StaticResource FSE_PrimaryBackgroundColor}"></SolidColorBrush> @@ -35,6 +40,11 @@ <SolidColorBrush x:Key="FSE_InfoBrush" Color="{StaticResource FSE_PrimaryForegroundColor}"></SolidColorBrush> <SolidColorBrush x:Key="FSE_MessageBoxTitleHeaderBackgroundBrush" Color="{StaticResource FSE_MessageBoxTitleHeaderBackgroundColor}"></SolidColorBrush> + <SolidColorBrush x:Key="FSE_UsbBrush" Color="{StaticResource FSE_UsbColor}"></SolidColorBrush> + <SolidColorBrush x:Key="FSE_WifiBrush" Color="{StaticResource FSE_WifiColor}"></SolidColorBrush> + <SolidColorBrush x:Key="FSE_SignalRBrush" Color="{StaticResource FSE_SignalRColor}"></SolidColorBrush> + <SolidColorBrush x:Key="FSE_EmulatorBrush" Color="{StaticResource FSE_EmulatorColor}"></SolidColorBrush> + <!--BRUSHES OVERRIDES--> <SolidColorBrush x:Key="MaterialDesignPaper" Color="{StaticResource FSE_PrimaryBackgroundColor}"></SolidColorBrush> <SolidColorBrush x:Key="MaterialDesignBody" Color="{StaticResource FSE_PrimaryForegroundColor}"></SolidColorBrush> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Styles.xaml b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Styles.xaml index 9c6652efc..b3a028a68 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Styles.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Resources/Styles.xaml @@ -1,5 +1,10 @@ <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:editors="clr-namespace:Tango.AutoComplete.Editors;assembly=Tango.AutoComplete" + xmlns:actions="clr-namespace:Tango.FSE.Common.EventTriggerActions" + xmlns:material="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:wpf="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:local="clr-namespace:Tango.FSE.Common.Resources"> <Style x:Key="FSE_FlatButton_OpacityHover" TargetType="Button" BasedOn="{StaticResource MaterialDesignToolForegroundButton}"> @@ -27,4 +32,312 @@ </Style.Triggers> </Style> + <Style TargetType="editors:AutoCompleteTextBox" > + <Setter Property="Focusable" Value="True" /> + <Setter Property="BorderThickness" Value="0 0 0 1"/> + <Setter Property="BorderBrush" Value="{DynamicResource MaterialDesignTextBoxBorder}" /> + <Setter Property="Background" Value="Transparent"/> + <!--<Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>--> + <Setter Property="HorizontalContentAlignment" Value="Left"/> + <Setter Property="VerticalContentAlignment" Value="Top"/> + <Setter Property="FocusVisualStyle" Value="{x:Null}"/> + <Setter Property="AllowDrop" Value="true"/> + <Setter Property="FontSize" Value="{StaticResource FSE_LargerFontSize}"></Setter> + <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/> + <Setter Property="Stylus.IsFlicksEnabled" Value="False"/> + <Setter Property="Validation.ErrorTemplate" Value="{DynamicResource MaterialDesignValidationErrorTemplate}"/> + <Setter Property="SelectedItemTemplate"> + <Setter.Value> + <DataTemplate> + <TextBlock Text="{Binding ElementName=PART_Editor,Path=Text}" VerticalAlignment="Center"></TextBlock> + </DataTemplate> + </Setter.Value> + </Setter> + <Setter Property="Icon"> + <Setter.Value> + <material:PackIcon Kind="Search" Margin="0 0 5 0" Height="20" Width="20" VerticalAlignment="Center" /> + </Setter.Value> + </Setter> + <Setter Property="LoadingContent"> + <Setter.Value> + <ProgressBar IsIndeterminate="True" HorizontalAlignment="Stretch" Height="5" /> + </Setter.Value> + </Setter> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type editors:AutoCompleteTextBox}"> + <Grid> + <DockPanel> + <ContentPresenter ContentSource="Icon" + x:Name="PART_Icon" + Visibility="{TemplateBinding IconVisibility}" /> + <Grid> + <TextBlock x:Name="PART_Watermark" + Text="{TemplateBinding Watermark}" + Visibility="Collapsed" + VerticalAlignment="Center" + HorizontalAlignment="Left" + Focusable="False" + Foreground="Gray" + Margin="3,0" /> + <TextBox x:Name="PART_Editor" + Focusable="True" + HorizontalAlignment="Stretch" + VerticalAlignment="Center" + Style="{StaticResource ResourceKey=MaterialDesignTextBox}" + MaxLength="{Binding Path=MaxLength, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay}" + CharacterCasing="{Binding Path=CharacterCasing, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay}" + Text="{Binding Path=Text, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay}"> + <i:Interaction.Triggers> + <i:EventTrigger EventName="GotKeyboardFocus"> + <actions:SetterAction TargetObject="{Binding ElementName=PART_SelectedContent}" PropertyName="Visibility" Value="Collapsed" /> + <actions:SetterAction PropertyName="Foreground" Value="{StaticResource FSE_PrimaryForegroundBrush}" /> + </i:EventTrigger> + <!--<i:EventTrigger EventName="LostKeyboardFocus"> + <actions:SetterAction TargetObject="{Binding ElementName=PART_SelectedContent}" PropertyName="Visibility" Value="Visible" /> + <actions:SetterAction PropertyName="Foreground" Value="Transparent" /> + </i:EventTrigger>--> + </i:Interaction.Triggers> + </TextBox> + <ContentControl x:Name="PART_SelectedContent" IsHitTestVisible="False" Content="{TemplateBinding SelectedItem}" ContentTemplate="{TemplateBinding SelectedItemTemplate}"> + <ContentControl.Style> + <Style TargetType="ContentControl"> + <Setter Property="Visibility" Value="Collapsed"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=editors:AutoCompleteTextBox},Path=SelectedItem,Converter={StaticResource NullObjectToBooleanConverter}}" Value="True" > + <Setter Property="Visibility" Value="Visible"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </ContentControl.Style> + </ContentControl> + </Grid> + </DockPanel> + <Popup x:Name="PART_Popup" + IsOpen="{Binding Path=IsDropDownOpen, RelativeSource={RelativeSource Mode=TemplatedParent},Mode=TwoWay}" + Width="{TemplateBinding ActualWidth}" + HorizontalOffset="0" + MinHeight="25" + MaxHeight="600" + AllowsTransparency="True" + PopupAnimation="Slide" + Focusable="False"> + <Border Margin="5" Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}" x:Name="PopupBorder" + BorderThickness="1" + BorderBrush="{DynamicResource AutoCompleteTextBox.Popup.BorderBrush}" + CornerRadius="5" + Padding="2"> + <Border.Effect> + <DropShadowEffect/> + </Border.Effect> + <Grid> + <ListBox x:Name="PART_Selector" + ItemTemplate="{TemplateBinding ItemTemplate}" + ItemTemplateSelector="{TemplateBinding ItemTemplateSelector}" + DisplayMemberPath="{TemplateBinding DisplayMember}" + Focusable="False" + BorderThickness="0" + MaxHeight="{Binding Path=MaxPopupHeight, RelativeSource={RelativeSource Mode=TemplatedParent},Mode=TwoWay}" + ScrollViewer.HorizontalScrollBarVisibility="Auto" + ScrollViewer.VerticalScrollBarVisibility="Auto" + > + </ListBox> + <Border Visibility="{Binding Path=IsLoading, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource ResourceKey=BooleanToVisibilityConverter}}"> + <ContentPresenter ContentSource="LoadingContent"/> + </Border> + </Grid> + </Border> + </Popup> + </Grid> + <ControlTemplate.Triggers> + <Trigger Property="Text" + Value="" + SourceName="PART_Editor"> + <Setter Property="Visibility" + Value="Visible" + TargetName="PART_Watermark" /> + </Trigger> + <Trigger Property="IconPlacement" + Value="Left"> + <Setter Property="DockPanel.Dock" + Value="Left" + TargetName="PART_Icon" /> + </Trigger> + <Trigger Property="IconPlacement" + Value="Right"> + <Setter Property="DockPanel.Dock" + Value="Right" + TargetName="PART_Icon" /> + </Trigger> + <Trigger Property="Validation.HasError" Value="True"> + <Setter Property="BorderBrush" + Value="Red"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <Style TargetType="{x:Type ListBoxItem}"> + <Setter Property="Background" Value="Transparent"/> + <Setter Property="BorderThickness" Value="0"/> + <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> + <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> + <Setter Property="Padding" Value="8"/> + <Setter Property="SnapsToDevicePixels" Value="True"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type ListBoxItem}"> + <Border Background="{TemplateBinding Background}" + BorderBrush="{TemplateBinding BorderBrush}" + BorderThickness="{TemplateBinding BorderThickness}" + Margin="{TemplateBinding Margin}" + ClipToBounds="{TemplateBinding ClipToBounds}"> + <VisualStateManager.VisualStateGroups> + <VisualStateGroup Name="CommonStates"> + <VisualStateGroup.Transitions> + <VisualTransition GeneratedDuration="0:0:0.3" To="Normal"> + <VisualTransition.GeneratedEasingFunction> + <CircleEase EasingMode="EaseOut"/> + </VisualTransition.GeneratedEasingFunction> + </VisualTransition> + </VisualStateGroup.Transitions> + <VisualState Name="Normal"/> + <VisualState Name="MouseOver"> + <Storyboard> + <DoubleAnimation Storyboard.TargetName="MouseOverBorder" Storyboard.TargetProperty="Opacity" + To="0.1" Duration="0"/> + </Storyboard> + </VisualState> + <VisualState Name="Disabled"/> + </VisualStateGroup> + <VisualStateGroup Name="SelectionStates"> + <VisualStateGroup.Transitions> + <VisualTransition GeneratedDuration="0:0:0.6"/> + </VisualStateGroup.Transitions> + <VisualState Name="Selected"> + <Storyboard> + <DoubleAnimation Storyboard.TargetName="SelectedBorder" + Storyboard.TargetProperty="Opacity" + To="0.18" Duration="0"/> + </Storyboard> + </VisualState> + <VisualState Name="Unselected"/> + <VisualState Name="SelectedUnfocused"> + <Storyboard> + <DoubleAnimation Storyboard.TargetName="SelectedBorder" + Storyboard.TargetProperty="Opacity" + To="0.18" Duration="0"/> + </Storyboard> + </VisualState> + </VisualStateGroup> + </VisualStateManager.VisualStateGroups> + <Grid> + <Border x:Name="MouseOverBorder" + Opacity="0" + Background="{TemplateBinding Foreground, Converter={StaticResource BrushRoundConverter}}"/> + + <Border x:Name="SelectedBorder" + Opacity="0" + Background="{TemplateBinding Foreground, Converter={StaticResource BrushRoundConverter}}" + RenderTransformOrigin="0.5,0.5"> + <Border.RenderTransform> + <ScaleTransform ScaleX="1"/> + </Border.RenderTransform> + </Border> + <wpf:Ripple Feedback="{TemplateBinding Foreground, Converter={StaticResource BrushRoundConverter}}" + Focusable="False" + Content="{TemplateBinding Content}" + ContentTemplate="{TemplateBinding ContentTemplate}" + ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}" + SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" + HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" + VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" + Padding="{TemplateBinding Padding}"/> + </Grid> + </Border> + <ControlTemplate.Triggers> + <Trigger Property="IsEnabled" Value="False"> + <Setter Property="Opacity" Value=".56" /> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + + <Style x:Key="FSE_UsbMachineIcon" TargetType="ContentControl"> + <Setter Property="Height" Value="35"></Setter> + <Setter Property="ContentTemplate"> + <Setter.Value> + <DataTemplate> + <Viewbox Stretch="Uniform"> + <Grid RenderOptions.BitmapScalingMode="Fant"> + <Image Margin="0 10 0 0" Height="35" Source="{StaticResource FSE_Machine_Small}"></Image> + <Canvas HorizontalAlignment="Right" VerticalAlignment="Top"> + <material:PackIcon Kind="Usb" Foreground="{StaticResource FSE_UsbBrush}" Width="24" Height="24" Canvas.Left="-14" Canvas.Top="0" /> + </Canvas> + </Grid> + </Viewbox> + </DataTemplate> + </Setter.Value> + </Setter> + </Style> + + <Style x:Key="FSE_WifiMachineIcon" TargetType="ContentControl"> + <Setter Property="Height" Value="35"></Setter> + <Setter Property="ContentTemplate"> + <Setter.Value> + <DataTemplate> + <Viewbox Stretch="Uniform"> + <Grid RenderOptions.BitmapScalingMode="Fant"> + <Image Margin="0 10 0 0" Height="35" Source="{StaticResource FSE_Machine_Small}"></Image> + <Canvas HorizontalAlignment="Right" VerticalAlignment="Top"> + <material:PackIcon Kind="Wifi" Foreground="{StaticResource FSE_WifiBrush}" Width="20" Height="20" Canvas.Left="-14" Canvas.Top="0" /> + </Canvas> + </Grid> + </Viewbox> + </DataTemplate> + </Setter.Value> + </Setter> + </Style> + + <Style x:Key="FSE_SignalRMachineIcon" TargetType="ContentControl"> + <Setter Property="Height" Value="35"></Setter> + <Setter Property="ContentTemplate"> + <Setter.Value> + <DataTemplate> + <Viewbox Stretch="Uniform"> + <Grid RenderOptions.BitmapScalingMode="Fant"> + <Image Margin="0 10 0 0" Height="35" Source="{StaticResource FSE_Machine_Small}"></Image> + <Canvas HorizontalAlignment="Right" VerticalAlignment="Top"> + <material:PackIcon Kind="Cloud" Foreground="{StaticResource FSE_SignalRBrush}" Width="18" Height="18" Canvas.Left="-14" Canvas.Top="0" /> + </Canvas> + </Grid> + </Viewbox> + </DataTemplate> + </Setter.Value> + </Setter> + </Style> + + <Style x:Key="FSE_EmulatorMachineIcon" TargetType="ContentControl"> + <Setter Property="Height" Value="35"></Setter> + <Setter Property="ContentTemplate"> + <Setter.Value> + <DataTemplate> + <Viewbox Stretch="Uniform"> + <Grid RenderOptions.BitmapScalingMode="Fant"> + <Image Margin="0 10 0 0" Height="35" Source="{StaticResource FSE_Machine_Small}"></Image> + <Canvas HorizontalAlignment="Right" VerticalAlignment="Top"> + <material:PackIcon Kind="SdCard" Foreground="{StaticResource FSE_EmulatorBrush}" Width="18" Height="18" Canvas.Left="-14" Canvas.Top="0" /> + </Canvas> + </Grid> + </Viewbox> + </DataTemplate> + </Setter.Value> + </Setter> + </Style> + </ResourceDictionary>
\ No newline at end of file diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj b/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj index 7eaac67c8..2c878cc19 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj +++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj @@ -78,8 +78,10 @@ <ItemGroup> <Compile Include="Authentication\AuthenticationResult.cs" /> <Compile Include="Authentication\IAuthenticationProvider.cs" /> + <Compile Include="AutoComplete\AutoCompleteSource.cs" /> <Compile Include="Connection\IMachineProvider.cs" /> <Compile Include="Controls\IconButton.cs" /> + <Compile Include="EventTriggerActions\SetterAction.cs" /> <Compile Include="FSEApplication\IFSEApplicationManager.cs" /> <Compile Include="FSEDialogViewVM.cs" /> <Compile Include="FSEModuleAttribute.cs" /> @@ -184,6 +186,10 @@ </None> </ItemGroup> <ItemGroup> + <ProjectReference Include="..\..\SideChains\Tango.AutoComplete\Tango.AutoComplete.csproj"> + <Project>{bb2abb74-ba58-4812-83aa-ec8171f42df4}</Project> + <Name>Tango.AutoComplete</Name> + </ProjectReference> <ProjectReference Include="..\..\Tango.BL\Tango.BL.csproj"> <Project>{f441feee-322a-4943-b566-110e12fd3b72}</Project> <Name>Tango.BL</Name> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs index 66482e476..8fc7c7c85 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs @@ -7,11 +7,13 @@ using System.Threading.Tasks; using Tango.BL.Entities; using Tango.Core; using Tango.Core.DI; +using Tango.Emulations.ExternalBridge; using Tango.FSE.Common.Connection; using Tango.FSE.Common.Notifications; using Tango.FSE.UI.Dialogs; using Tango.Integration.ExternalBridge; using Tango.Integration.Operation; +using Tango.SharedUI; namespace Tango.FSE.UI.Connection { @@ -70,12 +72,26 @@ namespace Tango.FSE.UI.Connection await DisconnectMachine(); } - await NotificationProvider.ShowDialog<MachineConnectionSerialViewVM>(); + DialogViewVM vm = null; - ReassignEventHandlers(MachineOperator, machine); - MachineOperator = machine; + if (machine.GetType() == typeof(ExternalBridgeUsbClient)) + { + vm = await NotificationProvider.ShowDialog<MachineConnectionUsbViewVM>(); + } + else if (machine.GetType() == typeof(EmulatorExternalBridge)) + { + vm = await NotificationProvider.ShowDialog<MachineConnectionEmulatorViewVM>(); + } - await MachineOperator.Connect(); + if (vm.DialogResult) + { + ReassignEventHandlers(MachineOperator, machine); + MachineOperator = machine; + + await MachineOperator.Connect(); + + IsConnected = true; + } } /// <summary> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionEmulatorView.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionEmulatorView.xaml new file mode 100644 index 000000000..45be0817b --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionEmulatorView.xaml @@ -0,0 +1,53 @@ +<UserControl x:Class="Tango.FSE.UI.Dialogs.MachineConnectionEmulatorView" + 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:autoComplete="clr-namespace:Tango.AutoComplete.Editors;assembly=Tango.AutoComplete" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:local="clr-namespace:Tango.FSE.UI.Dialogs" + mc:Ignorable="d" + Height="300" Width="700" d:DataContext="{d:DesignInstance Type=local:MachineConnectionEmulatorViewVM, IsDesignTimeCreatable=False}" Background="{StaticResource FSE_PrimaryBackgroundLightBrush}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}"> + <Grid> + <DockPanel Margin="10"> + <StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="10"> + <ContentControl Height="60" Margin="-10 0 0 0" Style="{StaticResource FSE_EmulatorMachineIcon}"></ContentControl> + <TextBlock Text="Machine Selection" FontWeight="SemiBold" VerticalAlignment="Center" Margin="10 0 0 0" FontSize="{StaticResource FSE_MessageBoxTitleFontSize}"></TextBlock> + </StackPanel> + + <TextBlock DockPanel.Dock="Top" TextWrapping="Wrap" Margin="0 10 0 0"> + <Run>Connecting to an emulated machine requires the selection of an existing machine from the database.</Run> + <LineBreak/> + <LineBreak/> + <Run>Please select a 'virtual machine' by entering the machine serial number.</Run> + </TextBlock> + <StackPanel HorizontalAlignment="Left" VerticalAlignment="Center" Width="400"> + <TextBlock Margin="25 0 0 0" Foreground="{StaticResource FSE_EmulatorBrush}">Virtualized Machine</TextBlock> + <autoComplete:AutoCompleteTextBox materialDesign:HintAssist.Hint="Serial Number" MaxPopupHeight="300" Margin="0 5 0 0" Provider="{Binding Machines}" SelectedItem="{Binding SelectedMachine,Mode=TwoWay}" DisplayMember="SerialNumber"> + <autoComplete:AutoCompleteTextBox.SelectedItemTemplate> + <DataTemplate> + <DockPanel VerticalAlignment="Center"> + <Image RenderOptions.BitmapScalingMode="Fant" Source="{StaticResource FSE_Machine_Small}" Width="24" /> + <StackPanel VerticalAlignment="Center" Margin="10 0 0 0" Orientation="Horizontal"> + <TextBlock Text="{Binding SerialNumber}" FontSize="{StaticResource FSE_SmallFontSize}"></TextBlock> + <TextBlock Margin="10 0 0 0" FontSize="{StaticResource FSE_SmallFontSize}" Foreground="{StaticResource FSE_GrayBrush}" Text="{Binding Name}"></TextBlock> + </StackPanel> + </DockPanel> + </DataTemplate> + </autoComplete:AutoCompleteTextBox.SelectedItemTemplate> + <autoComplete:AutoCompleteTextBox.ItemTemplate> + <DataTemplate> + <DockPanel VerticalAlignment="Center"> + <Image RenderOptions.BitmapScalingMode="Fant" Source="{StaticResource FSE_Machine_Small}" Width="32" /> + <StackPanel Margin="5 0 0 0"> + <TextBlock Text="{Binding SerialNumber}"></TextBlock> + <TextBlock Margin="0 5 0 0" FontSize="{StaticResource FSE_SmallerFontSize}" Foreground="{StaticResource FSE_GrayBrush}" Text="{Binding Name}"></TextBlock> + </StackPanel> + </DockPanel> + </DataTemplate> + </autoComplete:AutoCompleteTextBox.ItemTemplate> + </autoComplete:AutoCompleteTextBox> + </StackPanel> + </DockPanel> + </Grid> +</UserControl> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionEmulatorView.xaml.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionEmulatorView.xaml.cs new file mode 100644 index 000000000..16550e48b --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionEmulatorView.xaml.cs @@ -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 Tango.FSE.UI.Dialogs +{ + /// <summary> + /// Interaction logic for MachineConnectionSerialView.xaml + /// </summary> + public partial class MachineConnectionEmulatorView : UserControl + { + public MachineConnectionEmulatorView() + { + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionEmulatorViewVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionEmulatorViewVM.cs new file mode 100644 index 000000000..b8f3637ab --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionEmulatorViewVM.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Data.Entity; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL; +using Tango.BL.Entities; +using Tango.FSE.Common; +using Tango.FSE.Common.AutoComplete; + +namespace Tango.FSE.UI.Dialogs +{ + public class MachineConnectionEmulatorViewVM : MachineConnectionUsbViewVM + { + + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionSerialView.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionSerialView.xaml deleted file mode 100644 index c8ff5e887..000000000 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionSerialView.xaml +++ /dev/null @@ -1,12 +0,0 @@ -<UserControl x:Class="Tango.FSE.UI.Dialogs.MachineConnectionSerialView" - 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:Tango.FSE.UI.Dialogs" - mc:Ignorable="d" - Height="300" Width="700" Background="{StaticResource FSE_PrimaryBackgroundLightBrush}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}"> - <Grid> - <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="40">Machine Serial Dialog</TextBlock> - </Grid> -</UserControl> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionSerialViewVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionSerialViewVM.cs deleted file mode 100644 index 79c68dd11..000000000 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionSerialViewVM.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Tango.FSE.Common; - -namespace Tango.FSE.UI.Dialogs -{ - public class MachineConnectionSerialViewVM : FSEDialogViewVM - { - public MachineConnectionSerialViewVM() : base() - { - AutoMode = true; - CancelText = "CANCEL"; - OKText = "CONNECT"; - } - } -} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionUsbView.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionUsbView.xaml new file mode 100644 index 000000000..6ab2414f3 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionUsbView.xaml @@ -0,0 +1,53 @@ +<UserControl x:Class="Tango.FSE.UI.Dialogs.MachineConnectionUsbView" + 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:autoComplete="clr-namespace:Tango.AutoComplete.Editors;assembly=Tango.AutoComplete" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:local="clr-namespace:Tango.FSE.UI.Dialogs" + mc:Ignorable="d" + Height="300" Width="700" d:DataContext="{d:DesignInstance Type=local:MachineConnectionUsbViewVM, IsDesignTimeCreatable=False}" Background="{StaticResource FSE_PrimaryBackgroundLightBrush}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}"> + <Grid> + <DockPanel Margin="10"> + <StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="10"> + <ContentControl Height="60" Margin="-10 0 0 0" Style="{StaticResource FSE_UsbMachineIcon}"></ContentControl> + <TextBlock Text="Machine Selection" FontWeight="SemiBold" VerticalAlignment="Center" Margin="10 0 0 0" FontSize="{StaticResource FSE_MessageBoxTitleFontSize}"></TextBlock> + </StackPanel> + + <TextBlock DockPanel.Dock="Top" TextWrapping="Wrap" Margin="0 10 0 0"> + <Run>Connecting directly to a machine's embedded firmware requires the selection of an existing machine from the database.</Run> + <LineBreak/> + <LineBreak/> + <Run>Please select a 'virtual machine' by entering the machine serial number.</Run> + </TextBlock> + <StackPanel HorizontalAlignment="Left" VerticalAlignment="Center" Width="400"> + <TextBlock Margin="25 0 0 0" Foreground="{StaticResource FSE_UsbBrush}">Virtualized Machine</TextBlock> + <autoComplete:AutoCompleteTextBox materialDesign:HintAssist.Hint="Serial Number" MaxPopupHeight="300" Margin="0 5 0 0" Provider="{Binding Machines}" SelectedItem="{Binding SelectedMachine,Mode=TwoWay}" DisplayMember="SerialNumber"> + <autoComplete:AutoCompleteTextBox.SelectedItemTemplate> + <DataTemplate> + <DockPanel VerticalAlignment="Center"> + <Image RenderOptions.BitmapScalingMode="Fant" Source="{StaticResource FSE_Machine_Small}" Width="24" /> + <StackPanel VerticalAlignment="Center" Margin="10 0 0 0" Orientation="Horizontal"> + <TextBlock Text="{Binding SerialNumber}" FontSize="{StaticResource FSE_SmallFontSize}"></TextBlock> + <TextBlock Margin="10 0 0 0" FontSize="{StaticResource FSE_SmallFontSize}" Foreground="{StaticResource FSE_GrayBrush}" Text="{Binding Name}"></TextBlock> + </StackPanel> + </DockPanel> + </DataTemplate> + </autoComplete:AutoCompleteTextBox.SelectedItemTemplate> + <autoComplete:AutoCompleteTextBox.ItemTemplate> + <DataTemplate> + <DockPanel VerticalAlignment="Center"> + <Image RenderOptions.BitmapScalingMode="Fant" Source="{StaticResource FSE_Machine_Small}" Width="32" /> + <StackPanel Margin="5 0 0 0"> + <TextBlock Text="{Binding SerialNumber}"></TextBlock> + <TextBlock Margin="0 5 0 0" FontSize="{StaticResource FSE_SmallerFontSize}" Foreground="{StaticResource FSE_GrayBrush}" Text="{Binding Name}"></TextBlock> + </StackPanel> + </DockPanel> + </DataTemplate> + </autoComplete:AutoCompleteTextBox.ItemTemplate> + </autoComplete:AutoCompleteTextBox> + </StackPanel> + </DockPanel> + </Grid> +</UserControl> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionSerialView.xaml.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionUsbView.xaml.cs index b29a83d72..4920b94b6 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionSerialView.xaml.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionUsbView.xaml.cs @@ -18,9 +18,9 @@ namespace Tango.FSE.UI.Dialogs /// <summary> /// Interaction logic for MachineConnectionSerialView.xaml /// </summary> - public partial class MachineConnectionSerialView : UserControl + public partial class MachineConnectionUsbView : UserControl { - public MachineConnectionSerialView() + public MachineConnectionUsbView() { InitializeComponent(); } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionUsbViewVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionUsbViewVM.cs new file mode 100644 index 000000000..4f2ee1479 --- /dev/null +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionUsbViewVM.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Data.Entity; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL; +using Tango.BL.Entities; +using Tango.FSE.Common; +using Tango.FSE.Common.AutoComplete; + +namespace Tango.FSE.UI.Dialogs +{ + public class MachineConnectionUsbViewVM : FSEDialogViewVM + { + public AutoCompleteSource<Machine> Machines { get; set; } + + private Machine _selectedMachine; + public Machine SelectedMachine + { + get { return _selectedMachine; } + set { _selectedMachine = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } + } + + public MachineConnectionUsbViewVM() : base() + { + AutoMode = true; + CancelText = "CANCEL"; + OKText = "CONNECT"; + + Machines = new AutoCompleteSource<Machine>(AutoCompleteMachines); + } + + private List<Machine> AutoCompleteMachines(string key) + { + key = key ?? String.Empty; + + try + { + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { + return db.Machines.Where(x => x.SerialNumber.ToLower().StartsWith(key)).Take(4).ToList(); + } + } + catch (Exception ex) + { + LogManager.Log(ex, "Error on auto complete virtualized machine filter."); + return new List<Machine>(); + } + } + + protected override bool CanOK() + { + return SelectedMachine != null; + } + + public async override void OnShow() + { + base.OnShow(); + + try + { + if (Settings.LastVirtualizedMachineSerialNumber != null) + { + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { + var machine = await db.Machines.SingleOrDefaultAsync(x => x.SerialNumber == Settings.LastVirtualizedMachineSerialNumber); + + if (SelectedMachine == null) + { + SelectedMachine = machine; + } + } + } + } + catch (Exception ex) + { + LogManager.Log(ex, "Error retrieving last virtualized machine."); + } + } + + protected override void Accept() + { + Settings.LastVirtualizedMachineSerialNumber = SelectedMachine.SerialNumber; + Settings.Save(); + + base.Accept(); + } + } +} diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/MachineConnectionPane.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/MachineConnectionPane.xaml index 2b8b6c1a9..9e9050201 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/MachineConnectionPane.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/MachineConnectionPane.xaml @@ -12,21 +12,43 @@ <Button Command="{Binding ConnectToMachineCommand}" DockPanel.Dock="Bottom" Height="50" Margin="5" material:ButtonAssist.CornerRadius="25"> CONNECT </Button> - <UniformGrid Rows="3"> - <Grid Margin="0 10"> + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="60" /> + <RowDefinition Height="1*" /> + <RowDefinition Height="5" /> + <RowDefinition Height="1*" /> + <RowDefinition Height="5" /> + <RowDefinition Height="1*" /> + </Grid.RowDefinitions> + <Grid Margin="0 10 0 0" Grid.Row="0"> + <DockPanel> + <ListBox x:Name="listEmulator" ItemsSource="{Binding EmulatorMachines}" SelectedItem="{Binding SelectedMachine,Mode=OneWay}" PreviewMouseDoubleClick="ListBox_PreviewMouseDoubleClick"> + <ListBox.ItemTemplate> + <DataTemplate> + <StackPanel Orientation="Horizontal"> + <ContentControl Style="{StaticResource FSE_EmulatorMachineIcon}" Height="35"></ContentControl> + <StackPanel Margin="10 0 0 0"> + <TextBlock FontSize="{StaticResource FSE_SmallFontSize}" FontWeight="SemiBold">In-Memory Emulator</TextBlock> + <TextBlock FontSize="{StaticResource FSE_SmallFontSize}"> + <Run FontWeight="SemiBold">Address:</Run> <Run Text="{Binding Adapter.Address,Mode=OneWay}"></Run> + </TextBlock> + </StackPanel> + </StackPanel> + </DataTemplate> + </ListBox.ItemTemplate> + </ListBox> + </DockPanel> + </Grid> + <Grid Margin="0 10 0 0" Grid.Row="1"> <DockPanel> <TextBlock FontSize="{StaticResource FSE_SmallFontSize}" DockPanel.Dock="Top" Text="Scanning for machines on the local serial ports..."></TextBlock> <ProgressBar DockPanel.Dock="Top" Height="2" IsIndeterminate="True" Margin="0 3 0 0" /> - <ListBox ItemsSource="{Binding UsbMachines}" SelectedItem="{Binding SelectedMachine,Mode=TwoWay}" PreviewMouseDoubleClick="ListBox_PreviewMouseDoubleClick"> + <ListBox x:Name="listUsb" Style="{StaticResource MaterialDesignListBox}" SelectedItem="{Binding SelectedMachine,Mode=OneWay}" ItemsSource="{Binding UsbMachines}" PreviewMouseDoubleClick="ListBox_PreviewMouseDoubleClick"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> - <Grid Height="35" RenderOptions.BitmapScalingMode="Fant"> - <Image Margin="0 10 0 0" Source="{StaticResource FSE_Machine_Small}"></Image> - <Canvas HorizontalAlignment="Right" VerticalAlignment="Top"> - <Image Width="24" Canvas.Left="-14" Canvas.Top="0" Source="/Images/Connections/usb.png"></Image> - </Canvas> - </Grid> + <ContentControl Style="{StaticResource FSE_UsbMachineIcon}" Height="35"></ContentControl> <StackPanel Margin="10 0 0 0"> <TextBlock FontSize="{StaticResource FSE_SmallFontSize}"> <Run FontWeight="SemiBold">Port:</Run> <Run Text="{Binding ComPort,Mode=OneWay}"></Run> @@ -41,20 +63,16 @@ </ListBox> </DockPanel> </Grid> - <Grid Margin="0 10"> + <GridSplitter HorizontalAlignment="Stretch" VerticalAlignment="Center" Height="5" Grid.Row="2" /> + <Grid Grid.Row="3"> <DockPanel> <TextBlock FontSize="{StaticResource FSE_SmallFontSize}" DockPanel.Dock="Top" Text="Scanning for machines on your local network..."></TextBlock> <ProgressBar DockPanel.Dock="Top" Height="2" IsIndeterminate="True" Margin="0 3 0 0" /> - <ListBox ItemsSource="{Binding TcpMachines}" SelectedItem="{Binding SelectedMachine,Mode=TwoWay}" PreviewMouseDoubleClick="ListBox_PreviewMouseDoubleClick"> + <ListBox x:Name="listWifi" ItemsSource="{Binding TcpMachines}" SelectedItem="{Binding SelectedMachine,Mode=OneWay}" PreviewMouseDoubleClick="ListBox_PreviewMouseDoubleClick"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> - <Grid Height="35" RenderOptions.BitmapScalingMode="Fant"> - <Image Margin="0 10 0 0" Source="{StaticResource FSE_Machine_Small}"></Image> - <Canvas HorizontalAlignment="Right" VerticalAlignment="Top"> - <Image Width="20" Canvas.Left="-14" Canvas.Top="0" Source="/Images/Connections/wifi.png"></Image> - </Canvas> - </Grid> + <ContentControl Style="{StaticResource FSE_WifiMachineIcon}" /> <StackPanel Margin="10 0 0 0"> <TextBlock FontSize="{StaticResource FSE_SmallFontSize}"> <Run FontWeight="SemiBold">S/N:</Run> <Run Text="{Binding SerialNumber,Mode=OneWay}"></Run> @@ -72,20 +90,16 @@ </ListBox> </DockPanel> </Grid> - <Grid Margin="0 10"> + <GridSplitter HorizontalAlignment="Stretch" VerticalAlignment="Center" Height="5" Grid.Row="4" /> + <Grid Grid.Row="5"> <DockPanel> <TextBlock FontSize="{StaticResource FSE_SmallFontSize}" DockPanel.Dock="Top" Text="Scanning for machines across the internet..."></TextBlock> <ProgressBar DockPanel.Dock="Top" Height="2" IsIndeterminate="True" Margin="0 3 0 0" /> - <ListBox ItemsSource="{Binding SignalRMachines}" SelectedItem="{Binding SelectedMachine,Mode=TwoWay}" PreviewMouseDoubleClick="ListBox_PreviewMouseDoubleClick"> + <ListBox x:Name="listSignalR" ItemsSource="{Binding SignalRMachines}" SelectedItem="{Binding SelectedMachine,Mode=OneWay}" PreviewMouseDoubleClick="ListBox_PreviewMouseDoubleClick"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> - <Grid Height="35" RenderOptions.BitmapScalingMode="Fant"> - <Image Margin="0 10 0 0" Source="{StaticResource FSE_Machine_Small}"></Image> - <Canvas HorizontalAlignment="Right" VerticalAlignment="Top"> - <Image Width="18" Canvas.Left="-14" Canvas.Top="0" Source="/Images/Connections/cloud.png"></Image> - </Canvas> - </Grid> + <ContentControl Style="{StaticResource FSE_SignalRMachineIcon}" /> <StackPanel Margin="10 0 0 0"> <TextBlock FontSize="{StaticResource FSE_SmallFontSize}"> <Run FontWeight="Bold">S/N:</Run> <Run Text="{Binding SerialNumber,Mode=OneWay}"></Run> @@ -103,7 +117,7 @@ </ListBox> </DockPanel> </Grid> - </UniformGrid> + </Grid> </DockPanel> </Grid> </UserControl> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/MachineConnectionPane.xaml.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/MachineConnectionPane.xaml.cs index 6e0a5e74f..f0571475f 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/MachineConnectionPane.xaml.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/MachineConnectionPane.xaml.cs @@ -20,9 +20,46 @@ namespace Tango.FSE.UI.Panes /// </summary> public partial class MachineConnectionPane : UserControl { + private List<ListBox> _lists; + private bool _blockSelection; + public MachineConnectionPane() { InitializeComponent(); + + _lists = new List<ListBox>(); + _lists.Add(listEmulator); + _lists.Add(listUsb); + _lists.Add(listWifi); + _lists.Add(listSignalR); + + _lists.ForEach(x => x.SelectionChanged += OnSelectionChanged); + } + + private void OnSelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (!_blockSelection && (sender as ListBox).SelectedItem != null) + { + _blockSelection = true; + + foreach (var list in _lists.Where(x => x != sender)) + { + list.SelectedIndex = -1; + } + + ApplySelectedItem((sender as ListBox).SelectedItem); + + _blockSelection = false; + } + } + + private void ApplySelectedItem(object item) + { + var vm = DataContext as MachineConnectionPaneVM; + if (vm != null) + { + vm.SelectedMachine = item as Integration.ExternalBridge.IExternalBridgeClient; + } } private void ListBox_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e) diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/MachineConnectionPaneVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/MachineConnectionPaneVM.cs index 37cf9b70f..bcf7eaaa6 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/MachineConnectionPaneVM.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/MachineConnectionPaneVM.cs @@ -6,7 +6,10 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.Core.Commands; +using Tango.Emulations.ExternalBridge; +using Tango.FSE.Common; using Tango.Integration.ExternalBridge; +using Tango.Settings; using Tango.SharedUI; namespace Tango.FSE.UI.Panes @@ -14,6 +17,8 @@ namespace Tango.FSE.UI.Panes public class MachineConnectionPaneVM : ViewModel { private ExternalBridgeScanner _scanner; + private EmulatorExternalBridge _emulator; + private FSESettings _settings; public event EventHandler<IExternalBridgeClient> MachineSelected; @@ -23,6 +28,8 @@ namespace Tango.FSE.UI.Panes public ObservableCollection<ExternalBridgeSignalRClient> SignalRMachines { get; set; } + public ObservableCollection<EmulatorExternalBridge> EmulatorMachines { get; set; } + public RelayCommand ConnectToMachineCommand { get; set; } private IExternalBridgeClient _selectedMachine; @@ -39,16 +46,22 @@ namespace Tango.FSE.UI.Panes UsbMachines = new ObservableCollection<ExternalBridgeUsbClient>(); TcpMachines = new ObservableCollection<ExternalBridgeTcpClient>(); SignalRMachines = new ObservableCollection<ExternalBridgeSignalRClient>(); + EmulatorMachines = new ObservableCollection<EmulatorExternalBridge>(); _scanner = new ExternalBridgeScanner(); _scanner.MachineDiscovered += _scanner_MachineDiscovered; _scanner.MachineLost += _scanner_MachineLost; + + _settings = SettingsManager.Default.GetOrCreate<FSESettings>(); } internal void ConnectToMachine() { if (SelectedMachine != null) { + _settings.LastSelectedMachine = SelectedMachine.ToString(); + _settings.Save(); + MachineSelected?.Invoke(this, SelectedMachine); } } @@ -88,15 +101,36 @@ namespace Tango.FSE.UI.Panes { SignalRMachines.Add(machine as ExternalBridgeSignalRClient); } + + TryAutoSelectMachine(); }); } - public void Start() + private void TryAutoSelectMachine() + { + if (SelectedMachine == null && _settings.LastSelectedMachine != null) + { + SelectedMachine = _scanner.AvailableMachines.Concat(EmulatorMachines).SingleOrDefault(x => x.ToString() == _settings.LastSelectedMachine); + } + } + + public async void Start() { TcpMachines.Clear(); SignalRMachines.Clear(); + EmulatorMachines.Clear(); SelectedMachine = null; + if (_emulator != null) + { + await _emulator.Disconnect(); + } + + _emulator = new EmulatorExternalBridge(); + EmulatorMachines.Add(_emulator); + + TryAutoSelectMachine(); + _scanner.Start(); } diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj index 3fed0c00e..a5d8dfb94 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj @@ -86,10 +86,14 @@ <Compile Include="Authentication\DefaultAuthenticationProvider.cs" /> <Compile Include="Connection\DefaultMachineProvider.cs" /> <Compile Include="Contracts\ILayoutView.cs" /> - <Compile Include="Dialogs\MachineConnectionSerialView.xaml.cs"> - <DependentUpon>MachineConnectionSerialView.xaml</DependentUpon> + <Compile Include="Dialogs\MachineConnectionEmulatorView.xaml.cs"> + <DependentUpon>MachineConnectionEmulatorView.xaml</DependentUpon> </Compile> - <Compile Include="Dialogs\MachineConnectionSerialViewVM.cs" /> + <Compile Include="Dialogs\MachineConnectionUsbView.xaml.cs"> + <DependentUpon>MachineConnectionUsbView.xaml</DependentUpon> + </Compile> + <Compile Include="Dialogs\MachineConnectionEmulatorViewVM.cs" /> + <Compile Include="Dialogs\MachineConnectionUsbViewVM.cs" /> <Compile Include="Gateway\DefaultGatewayService.cs" /> <Compile Include="InternalModule.cs" /> <Compile Include="Modules\DefaultFSEModuleLoader.cs" /> @@ -128,7 +132,11 @@ <Compile Include="Views\MainView.xaml.cs"> <DependentUpon>MainView.xaml</DependentUpon> </Compile> - <Page Include="Dialogs\MachineConnectionSerialView.xaml"> + <Page Include="Dialogs\MachineConnectionEmulatorView.xaml"> + <Generator>MSBuild:Compile</Generator> + <SubType>Designer</SubType> + </Page> + <Page Include="Dialogs\MachineConnectionUsbView.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> @@ -201,6 +209,10 @@ <None Include="App.config" /> </ItemGroup> <ItemGroup> + <ProjectReference Include="..\..\SideChains\Tango.AutoComplete\Tango.AutoComplete.csproj"> + <Project>{bb2abb74-ba58-4812-83aa-ec8171f42df4}</Project> + <Name>Tango.AutoComplete</Name> + </ProjectReference> <ProjectReference Include="..\..\Tango.BL\Tango.BL.csproj"> <Project>{f441feee-322a-4943-b566-110e12fd3b72}</Project> <Name>Tango.BL</Name> @@ -209,6 +221,10 @@ <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project> <Name>Tango.Core</Name> </ProjectReference> + <ProjectReference Include="..\..\Tango.Emulations\Tango.Emulations.csproj"> + <Project>{63561e19-ff5a-414b-a5ef-e30711543e1d}</Project> + <Name>Tango.Emulations</Name> + </ProjectReference> <ProjectReference Include="..\..\Tango.Integration\Tango.Integration.csproj"> <Project>{4206AC58-3B57-4699-8835-90BF6DB01A61}</Project> <Name>Tango.Integration</Name> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml index b4a4d620a..0adbe95e3 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml @@ -67,7 +67,7 @@ <Border Background="{StaticResource FSE_PrimaryBackgroundBrush}" CornerRadius="0 0 5 5" Padding="10"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right"> <Button Height="40" MinWidth="150" Margin="0 0 5 0" Style="{StaticResource FSE_RaisedButton_Dark_Hover}" Command="{Binding DataContext.CloseCommand}" Visibility="{Binding DataContext.CanClose,Converter={StaticResource BooleanToVisibilityConverter}}" Content="{Binding DataContext.CancelText,TargetNullValue='CANCEL'}"></Button> - <Button x:Name="btnDialogOK" Height="40" MinWidth="150" IsDefault="True" Style="{StaticResource FSE_RaisedButton_Dark_Hover}" Command="{Binding DataContext.OKCommand}" Content="{Binding DataContext.OKText,TargetNullValue='OK'}"></Button> + <Button x:Name="btnDialogOK" Height="40" MinWidth="150" IsDefault="{Binding DataContext.HasDefault}" Style="{StaticResource FSE_RaisedButton_Dark_Hover}" Command="{Binding DataContext.OKCommand}" Content="{Binding DataContext.OKText,TargetNullValue='OK'}"></Button> </StackPanel> </Border> <Rectangle VerticalAlignment="Top" DockPanel.Dock="Bottom" Stroke="{StaticResource FSE_BorderBrush}" StrokeThickness="1" StrokeDashArray="5" /> @@ -88,18 +88,7 @@ <!--MESSAGE BOXES--> <Grid x:Name="gridMessageBox" IsVisibleChanged="GridMessageBox_IsVisibleChanged" Background="{StaticResource FSE_SemiTransparentBrush}" Visibility="{Binding NotificationProvider.HasMessageBox,Converter={StaticResource BooleanToVisibilityConverter}}"> - <Grid> - <Grid.RowDefinitions> - <RowDefinition Height="100*"/> - <RowDefinition Height="155*" MaxHeight="350" MinHeight="300" /> - <RowDefinition Height="100*"/> - </Grid.RowDefinitions> - <Grid.ColumnDefinitions> - <ColumnDefinition Width="100*"/> - <ColumnDefinition Width="200*" MaxWidth="780" MinWidth="400" /> - <ColumnDefinition Width="100*"/> - </Grid.ColumnDefinitions> - <Grid Margin="20" RenderTransformOrigin="0.5,0.5" Grid.Column="1" Grid.Row="1"> + <Grid MinWidth="650" MaxWidth="800" MaxHeight="400" MinHeight="280" HorizontalAlignment="Center" VerticalAlignment="Center" RenderTransformOrigin="0.5,0.5" Grid.Column="1" Grid.Row="1"> <Grid.Style> <Style TargetType="Grid"> <Setter Property="RenderTransform"> @@ -137,9 +126,9 @@ <Grid ClipToBounds="True"> <Grid> <Grid.RowDefinitions> - <RowDefinition Height="30*" /> + <RowDefinition Height="48" /> <RowDefinition Height="80*" /> - <RowDefinition Height="35*" /> + <RowDefinition Height="60" /> </Grid.RowDefinitions> <Grid> <Border CornerRadius="5 5 0 0" Background="{StaticResource FSE_PrimaryBackgroundLightBrush}"></Border> @@ -175,21 +164,15 @@ <TextBlock Grid.Row="1" Margin="40" Text="{Binding Message}" VerticalAlignment="Top" HorizontalAlignment="Left" TextWrapping="Wrap"></TextBlock> - <Grid Grid.Row="2" Margin="10"> - <Grid.ColumnDefinitions> - <ColumnDefinition Width="80*" /> - <ColumnDefinition Width="50*" /> - <ColumnDefinition Width="50*" /> - </Grid.ColumnDefinitions> - <Button Grid.Column="1" x:Name="btnCancel" Height="Auto" Style="{StaticResource FSE_RaisedButton_Dark_Hover}" Margin="0 0 10 0" Command="{Binding CloseCommand}" Visibility="{Binding HasCancel,Converter={StaticResource BooleanToVisibilityConverter}}" Content="{Binding CancelText}"></Button> - <Button Grid.Column="2" x:Name="btnOK" IsDefault="True" Style="{StaticResource FSE_RaisedButton_Dark_Hover}" Height="Auto" Command="{Binding OKCommand}" Content="{Binding OKText}"></Button> - </Grid> + <StackPanel HorizontalAlignment="Right" Grid.Row="2" Margin="10" Orientation="Horizontal"> + <Button MinWidth="150" x:Name="btnCancel" Height="Auto" Style="{StaticResource FSE_RaisedButton_Dark_Hover}" Margin="0 0 10 0" Command="{Binding CloseCommand}" Visibility="{Binding HasCancel,Converter={StaticResource BooleanToVisibilityConverter}}" Content="{Binding CancelText}"></Button> + <Button MinWidth="150" x:Name="btnOK" IsDefault="True" Style="{StaticResource FSE_RaisedButton_Dark_Hover}" Height="Auto" Command="{Binding OKCommand}" Content="{Binding OKText}"></Button> + </StackPanel> </Grid> </Grid> </Border> </Grid> </Grid> - </Grid> <!--MESSAGE BOXES--> </Grid> diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml.cs index 12add824b..ae56ff7db 100644 --- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml.cs +++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Views/MainView.xaml.cs @@ -46,15 +46,18 @@ namespace Tango.FSE.UI.Views private async void GridDialog_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) { - if (gridDialog.IsVisible) + if (btnDialogOK.IsDefault) { - _previousFocusedElement = Keyboard.FocusedElement as UIElement; - await Task.Delay(100); - btnDialogOK.Focus(); - } - else - { - _previousFocusedElement?.Focus(); + if (gridDialog.IsVisible) + { + _previousFocusedElement = Keyboard.FocusedElement as UIElement; + await Task.Delay(100); + btnDialogOK.Focus(); + } + else + { + _previousFocusedElement?.Focus(); + } } } } diff --git a/Software/Visual_Studio/SideChains/Tango.AutoComplete/Editors/AutoCompleteTextBox.cs b/Software/Visual_Studio/SideChains/Tango.AutoComplete/Editors/AutoCompleteTextBox.cs index 253843a57..7ed4814d3 100644 --- a/Software/Visual_Studio/SideChains/Tango.AutoComplete/Editors/AutoCompleteTextBox.cs +++ b/Software/Visual_Studio/SideChains/Tango.AutoComplete/Editors/AutoCompleteTextBox.cs @@ -18,6 +18,8 @@ namespace Tango.AutoComplete.Editors public class AutoCompleteTextBox : Control { + private ContentControl _partSelectedContent; + #region "Fields" public const string PartEditor = "PART_Editor"; @@ -65,7 +67,7 @@ namespace Tango.AutoComplete.Editors private SuggestionsAdapter _suggestionsAdapter; - + #endregion #region "Constructors" @@ -79,14 +81,22 @@ namespace Tango.AutoComplete.Editors #region "Properties" - + public DataTemplate SelectedItemTemplate + { + get { return (DataTemplate)GetValue(SelectedItemTemplateProperty); } + set { SetValue(SelectedItemTemplateProperty, value); } + } + public static readonly DependencyProperty SelectedItemTemplateProperty = + DependencyProperty.Register("SelectedItemTemplate", typeof(DataTemplate), typeof(AutoCompleteTextBox), new PropertyMetadata(null)); + + public int MaxPopupHeight { - get { return (int) GetValue(MaxPopUpHeightProperty); } - set { SetValue(MaxPopUpHeightProperty, value);} + get { return (int)GetValue(MaxPopUpHeightProperty); } + set { SetValue(MaxPopUpHeightProperty, value); } } - + public BindingEvaluator BindingEvaluator { get { return _bindingEvaluator; } @@ -95,13 +105,13 @@ namespace Tango.AutoComplete.Editors public CharacterCasing CharacterCasing { - get { return (System.Windows.Controls.CharacterCasing) GetValue(CharacterCasingProperty); } - set { SetValue(CharacterCasingProperty, value);} + get { return (System.Windows.Controls.CharacterCasing)GetValue(CharacterCasingProperty); } + set { SetValue(CharacterCasingProperty, value); } } public int MaxLength { - get { return (int) GetValue(DelayProperty); } + get { return (int)GetValue(DelayProperty); } set { SetValue(MaxLengthProperty, value); } } @@ -247,7 +257,8 @@ namespace Tango.AutoComplete.Editors set { SetValue(WatermarkProperty, value); } } - public Brush SuggestionBackground { + public Brush SuggestionBackground + { get { return (Brush)GetValue(SuggestionBackgroundProperty); } set { SetValue(SuggestionBackgroundProperty, value); } @@ -267,6 +278,22 @@ namespace Tango.AutoComplete.Editors { act._isUpdatingText = true; act.Editor.Text = act.BindingEvaluator.Evaluate(e.NewValue); + Keyboard.ClearFocus(); + + if (act._partSelectedContent != null) + { + if (act.SelectedItem == null) + { + act._partSelectedContent.Visibility = Visibility.Collapsed; + act.Editor.Foreground = Application.Current.Resources["FSE_PrimaryForegroundBrush"] as Brush; + } + else + { + act._partSelectedContent.Visibility = Visibility.Visible; + act.Editor.Foreground = Brushes.Transparent; + } + } + act._isUpdatingText = false; } } @@ -279,7 +306,7 @@ namespace Tango.AutoComplete.Editors listBox.ScrollIntoView(listBox.SelectedItem); } - + public override void OnApplyTemplate() { _isUpdatingText = true; @@ -289,6 +316,7 @@ namespace Tango.AutoComplete.Editors Editor = Template.FindName(PartEditor, this) as TextBox; Popup = Template.FindName(PartPopup, this) as Popup; ItemsSelector = Template.FindName(PartSelector, this) as Selector; + _partSelectedContent = Template.FindName("PART_SelectedContent", this) as ContentControl; BindingEvaluator = new BindingEvaluator(new Binding(DisplayMember)); if (Editor != null) diff --git a/Software/Visual_Studio/SideChains/Tango.AutoComplete/Editors/Themes/Generic.xaml b/Software/Visual_Studio/SideChains/Tango.AutoComplete/Editors/Themes/Generic.xaml index 25667d1d1..4e12f40fc 100644 --- a/Software/Visual_Studio/SideChains/Tango.AutoComplete/Editors/Themes/Generic.xaml +++ b/Software/Visual_Studio/SideChains/Tango.AutoComplete/Editors/Themes/Generic.xaml @@ -110,6 +110,7 @@ <ListBox x:Name="PART_Selector" ItemTemplate="{TemplateBinding ItemTemplate}" ItemTemplateSelector="{TemplateBinding ItemTemplateSelector}" + DisplayMemberPath="{TemplateBinding DisplayMember}" Focusable="False" BorderThickness="0" MaxHeight="{Binding Path=MaxPopupHeight, RelativeSource={RelativeSource Mode=TemplatedParent},Mode=TwoWay}" |
