diff options
| author | Avi Levkovich <avi@twine-s.com> | 2018-02-20 16:45:00 +0200 |
|---|---|---|
| committer | Avi Levkovich <avi@twine-s.com> | 2018-02-20 16:45:00 +0200 |
| commit | 6c208c90bc45aff4a7fa214356a42fe7757c5e6f (patch) | |
| tree | 0d77bc6a0ecfbb53cf42c5462ee19212197ee1bd /Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common | |
| parent | b0823127f152fe97a6e8fce29e427c7f3db9cf5a (diff) | |
| parent | 1a573aaa346ec4b8bd58a0e35ab9df571a09b855 (diff) | |
| download | Tango-6c208c90bc45aff4a7fa214356a42fe7757c5e6f.tar.gz Tango-6c208c90bc45aff4a7fa214356a42fe7757c5e6f.zip | |
MERGE
Diffstat (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common')
40 files changed, 1992 insertions, 29 deletions
diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Authentication/IAuthenticationProvider.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Authentication/IAuthenticationProvider.cs index 488a2f6dc..590936163 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Authentication/IAuthenticationProvider.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Authentication/IAuthenticationProvider.cs @@ -3,18 +3,36 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; -using Tango.DAL.Observables; +using Tango.Integration.Observables; namespace Tango.MachineStudio.Common.Authentication { + /// <summary> + /// Represents the Machine Studio user authentication provider responsible for the current logged-in user. + /// </summary> public interface IAuthenticationProvider { + /// <summary> + /// Occurs when the current logged-in user has changed. + /// </summary> event EventHandler<User> CurrentUserChanged; + /// <summary> + /// Gets the current logged-in user. + /// </summary> User CurrentUser { get; } + /// <summary> + /// Performs a user login by the specified email and password. + /// </summary> + /// <param name="email">The email.</param> + /// <param name="password">The password.</param> + /// <returns></returns> User Login(String email, String password); + /// <summary> + /// Logs-out the current logged-in user. + /// </summary> void Logout(); } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/HiveColorPickerControl.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/HiveColorPickerControl.xaml new file mode 100644 index 000000000..6a9bf9cc9 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/HiveColorPickerControl.xaml @@ -0,0 +1,23 @@ +<UserControl x:Class="Tango.MachineStudio.Common.Controls.HiveColorPickerControl" + 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:colorPicker="clr-namespace:Tango;assembly=Tango.ColorPicker" + xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI" + xmlns:local="clr-namespace:Tango.MachineStudio.Common.Controls" + mc:Ignorable="d" + d:DesignHeight="250" d:DesignWidth="500" > + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="235"/> + <ColumnDefinition Width="43*"/> + </Grid.ColumnDefinitions> + + <colorPicker:ColorCanvas SelectedColor="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=SelectedColor,Mode=TwoWay}" Background="Transparent" BorderThickness="0" UsingAlphaChannel="False" /> + + <Viewbox Stretch="Uniform" Grid.Column="1" Margin="5"> + <controls:HiveControl x:Name="hive" Height="250" HexagonSelected="hive_HexagonSelected" MaxSelections="1" Width="250" BorderThickness="1" /> + </Viewbox> + </Grid> +</UserControl> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/HiveColorPickerControl.xaml.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/HiveColorPickerControl.xaml.cs new file mode 100644 index 000000000..9432ae9ef --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/HiveColorPickerControl.xaml.cs @@ -0,0 +1,102 @@ +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.MachineStudio.Common.Controls +{ + /// <summary> + /// Interaction logic for HiveColorPickerControl.xaml + /// </summary> + public partial class HiveColorPickerControl : UserControl + { + public event EventHandler<Color> SelectedColorChanged; + private bool _preventHiveSelectedColorChange; + + public bool DemoMode + { + get { return (bool)GetValue(DemoModeProperty); } + set { SetValue(DemoModeProperty, value); } + } + public static readonly DependencyProperty DemoModeProperty = + DependencyProperty.Register("DemoMode", typeof(bool), typeof(HiveColorPickerControl), new PropertyMetadata(false)); + + public Color SelectedColor + { + get { return (Color)GetValue(SelectedColorProperty); } + set { SetValue(SelectedColorProperty, value); } + } + public static readonly DependencyProperty SelectedColorProperty = + DependencyProperty.Register("SelectedColor", typeof(Color), typeof(HiveColorPickerControl), new PropertyMetadata(Colors.Red, (d, e) => (d as HiveColorPickerControl).OnSelectedColorChanged())); + + public Color SelectedHiveColor + { + get { return (Color)GetValue(SelectedHiveColorProperty); } + set { SetValue(SelectedHiveColorProperty, value); } + } + public static readonly DependencyProperty SelectedHiveColorProperty = + DependencyProperty.Register("SelectedHiveColor", typeof(Color), typeof(HiveColorPickerControl), new PropertyMetadata(Colors.Red)); + + public HiveColorPickerControl() + { + InitializeComponent(); + + hive.Loaded += Hive_Loaded; + } + + private void Hive_Loaded(object sender, RoutedEventArgs e) + { + OnSelectedColorChanged(); + } + + private void OnSelectedColorChanged() + { + if (DemoMode) + { + if (!_preventHiveSelectedColorChange) + { + GenerateDemoModeHiveColors(); + } + SelectedColorChanged?.Invoke(this, SelectedColor); + } + } + + private void hive_HexagonSelected(object sender, SharedUI.Controls.HexagonControl hexagon) + { + SelectedHiveColor = (hexagon.Fill as SolidColorBrush).Color; + + _preventHiveSelectedColorChange = true; + SelectedColor = SelectedHiveColor; + _preventHiveSelectedColorChange = false; + } + + private void GenerateDemoModeHiveColors() + { + if (hive.CenterHexagon != null) + { + Random rnd = new Random(); + + (hive.CenterHexagon.Fill as SolidColorBrush).Color = SelectedColor; + + int counter = 0; + + foreach (var hexagon in hive.Hexagons.Where(x => x != hive.CenterHexagon).OrderBy(x => rnd.Next())) + { + (hexagon.Fill as SolidColorBrush).Color = Color.FromRgb((byte)Math.Min(SelectedColor.R + counter++, 255), (byte)Math.Min((SelectedColor.G + counter++), 255), (byte)Math.Min((SelectedColor.B + counter++), 255)); + + counter += 4; + } + } + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/IRealTimeGraph.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/IRealTimeGraph.cs new file mode 100644 index 000000000..bf40d459e --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/IRealTimeGraph.cs @@ -0,0 +1,53 @@ +using RealTimeGraphEx; +using RealTimeGraphEx.Controllers; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.MachineStudio.Common.Controls +{ + public interface IRealTimeGraph + { + /// <summary> + /// Gets or sets the name of the sensor. + /// </summary> + String SensorName { get; set; } + + /// <summary> + /// Gets or sets the tag. + /// </summary> + Object Tag { get; set; } + + /// <summary> + /// Gets or sets the sensor units. + /// </summary> + String SensorUnits { get; set; } + + /// <summary> + /// Occurs when the graph remove button has been pressed. + /// </summary> + event EventHandler GraphRemoveButtonPressed; + + /// <summary> + /// Occurs when the graph full screen button has been pressed. + /// </summary> + event EventHandler GraphFullScreenButtonPressed; + + /// <summary> + /// Gets or sets the inner real-time graph control. + /// </summary> + RealTimeGraphExBase InnerGraph { get; set; } + + /// <summary> + /// Gets or sets the inner graph controller. + /// </summary> + GraphControllerBase Controller { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether to enable toolbar buttons. + /// </summary> + bool EnableToolBar { get; set; } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/MdiChild.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/MdiChild.cs index 469e3fda5..109b00531 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/MdiChild.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/MdiChild.cs @@ -10,19 +10,34 @@ using Tango.Core.Commands; namespace Tango.MachineStudio.Common.Controls { + /// <summary> + /// Represents an <see cref="MdiContainerControl"/> child control. + /// </summary> + /// <seealso cref="System.Windows.DependencyObject" /> public class MdiChild : DependencyObject { + /// <summary> + /// Initializes a new instance of the <see cref="MdiChild"/> class. + /// </summary> public MdiChild() { } + /// <summary> + /// Initializes a new instance of the <see cref="MdiChild"/> class. + /// </summary> + /// <param name="header">The header.</param> + /// <param name="view">The view.</param> public MdiChild(String header, FrameworkElement view) : this() { Header = header; View = view; } + /// <summary> + /// Gets or sets the icon. + /// </summary> public PackIconKind Icon { get { return (PackIconKind)GetValue(IconProperty); } @@ -31,6 +46,9 @@ namespace Tango.MachineStudio.Common.Controls public static readonly DependencyProperty IconProperty = DependencyProperty.Register("Icon", typeof(PackIconKind), typeof(MdiChild), new PropertyMetadata(PackIconKind.LaptopWindows)); + /// <summary> + /// Gets or sets the header. + /// </summary> public String Header { get { return (String)GetValue(HeaderProperty); } @@ -39,6 +57,9 @@ namespace Tango.MachineStudio.Common.Controls public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register("Header", typeof(String), typeof(MdiChild), new PropertyMetadata(null)); + /// <summary> + /// Gets or sets the view. + /// </summary> public FrameworkElement View { get { return (FrameworkElement)GetValue(ViewProperty); } @@ -47,6 +68,9 @@ namespace Tango.MachineStudio.Common.Controls public static readonly DependencyProperty ViewProperty = DependencyProperty.Register("View", typeof(FrameworkElement), typeof(MdiChild), new PropertyMetadata(null)); + /// <summary> + /// Gets or sets the location. + /// </summary> public Point Location { get { return (Point)GetValue(LocationProperty); } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/MdiContainerControl.xaml.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/MdiContainerControl.xaml.cs index dbf4ee74b..ceeda050b 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/MdiContainerControl.xaml.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/MdiContainerControl.xaml.cs @@ -20,8 +20,11 @@ using Tango.SharedUI.Helpers; namespace Tango.MachineStudio.Common.Controls { /// <summary> - /// Interaction logic for MdiContainerControl.xaml + /// Represents an MDI-style container /// </summary> + /// <seealso cref="System.Windows.Controls.UserControl" /> + /// <seealso cref="System.Windows.Markup.IComponentConnector" /> + /// <seealso cref="System.Windows.Markup.IStyleConnector" /> public partial class MdiContainerControl : UserControl { private const int MIN_SIZE = 200; @@ -63,7 +66,6 @@ namespace Tango.MachineStudio.Common.Controls return UIHelper.FindChild<Canvas>(itemsControl, "canvas"); } - private void OnControlMouseDown(object sender, MouseButtonEventArgs e) { Canvas.SetZIndex(sender as FrameworkElement, GetCanvas().Children.OfType<FrameworkElement>().Max(x => Canvas.GetZIndex(x) + 1)); diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphControl.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphControl.xaml new file mode 100644 index 000000000..2f43869d5 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphControl.xaml @@ -0,0 +1,90 @@ +<UserControl x:Class="Tango.MachineStudio.Common.Controls.RealTimeGraphControl" + 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:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:graphEx="clr-namespace:RealTimeGraphEx.FastGraphs;assembly=RealTimeGraphEx" + xmlns:components="clr-namespace:RealTimeGraphEx.Components;assembly=RealTimeGraphEx" + xmlns:converters="clr-namespace:Tango.MachineStudio.Common.Converters" + xmlns:local="clr-namespace:Tango.MachineStudio.Common.Controls" + mc:Ignorable="d" + d:DesignHeight="150" d:DesignWidth="300"> + + <UserControl.Resources> + <ResourceDictionary> + <ResourceDictionary.MergedDictionaries> + <!--RealTimeGraphEx--> + <ResourceDictionary Source="pack://application:,,,/RealTimeGraphEx;component/Resources/Resources.xaml"></ResourceDictionary> + <ResourceDictionary Source="../Resources/MaterialDesign.xaml"></ResourceDictionary> + + <ResourceDictionary> + <Style TargetType="ContentControl" x:Key="graphContent"> + <Style.Setters> + <Setter Property="ContentTemplate"> + <Setter.Value> + <DataTemplate> + <Grid MouseEnter="Graph_MouseEnter" MouseLeave="Graph_MouseLeave" ClipToBounds="True"> + <ContentControl Content="{Binding}"></ContentControl> + <Grid Opacity="0.8" HorizontalAlignment="Stretch" VerticalAlignment="Top" ClipToBounds="True" Height="35" Margin="0 -35 0 0"> + <StackPanel Orientation="Horizontal" Margin="5" HorizontalAlignment="Right" VerticalAlignment="Top"> + <Button Margin="0 0 5 0" Click="OnGraphFullScreen" ToolTip="Full Screen" Width="24" Height="24" BorderBrush="Transparent" Background="{StaticResource AccentColorBrush}" Style="{StaticResource MaterialDesignFloatingActionAccentButton}" > + <materialDesign:PackIcon Kind="Fullscreen" HorizontalAlignment="Right" Width="20" Height="20" Foreground="{StaticResource WhiteBrush}" /> + </Button> + <Button Click="OnGraphRemove" ToolTip="Remove" Width="24" Height="24" BorderBrush="Transparent" Background="#FF7777" Style="{StaticResource MaterialDesignFloatingActionAccentButton}" > + <materialDesign:PackIcon Kind="CloseCircle" HorizontalAlignment="Right" Width="20" Height="20" Foreground="{StaticResource WhiteBrush}" /> + </Button> + </StackPanel> + </Grid> + </Grid> + </DataTemplate> + </Setter.Value> + </Setter> + </Style.Setters> + </Style> + </ResourceDictionary> + + <ResourceDictionary> + <converters:SecondsToGraphPointsConverter x:Key="secondsToPoints"></converters:SecondsToGraphPointsConverter> + </ResourceDictionary> + </ResourceDictionary.MergedDictionaries> + </ResourceDictionary> + </UserControl.Resources> + + <Grid> + <!--Temperature--> + <ContentControl Style="{StaticResource graphContent}" Margin="0 0 0 0" MinHeight="5"> + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="40"/> + <ColumnDefinition Width="438*"/> + </Grid.ColumnDefinitions> + + <Border BorderBrush="{StaticResource AccentColorBrush}" BorderThickness="1 1 0 1" Background="#90FFFFFF"> + <StackPanel Orientation="Horizontal"> + <components:YAxisScroll x:Name="yAxis" Interval="6" Graph="{Binding ElementName=Graph}" Width="35" Foreground="{StaticResource MaterialDesignLightForeground}" VerticalOffset="-5" FontSize="8" StringFormat="#0.0"></components:YAxisScroll> + <components:YAxisTicks x:Name="yAxisTicks" SmallTickTemplate="{StaticResource graphTicksTemplate}" Width="5" SmallTicks="6" Foreground="{StaticResource MaterialDesignLightForeground}" BigTicks="10" Graph="{Binding ElementName=Graph}"></components:YAxisTicks> + </StackPanel> + </Border> + <Border Grid.Column="1" BorderThickness="1" BorderBrush="{StaticResource borderBrush}" Background="{DynamicResource graphBackground}" Margin="5 0 0 0"> + <graphEx:RealTimeGraphExLineErase x:Name="Graph" x:FieldModifier="public" Controller="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=Controller}" Antialiased="True" RefreshRate="30" MarkerColor="{StaticResource graphsMarkerColor}" FillGraph="False" Stroke="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=Color}" Minimum="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=Minimum}" Maximum="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=Maximum}"> + <graphEx:RealTimeGraphExLineErase.Components> + <components:MouseValueToolTip ToolTipTemplate="{StaticResource graphTooltipTemplate}" /> + <components:GridLines Rows="4" Columns="6" GridBrush="{DynamicResource graphGridLinesBrush}"></components:GridLines> + </graphEx:RealTimeGraphExLineErase.Components> + <graphEx:RealTimeGraphExLineErase.InnerContent> + <Grid> + <Label Style="{StaticResource graphLabel}"> + <StackPanel Orientation="Horizontal"> + <TextBlock VerticalAlignment="Center" Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl,AncestorLevel=2},Path=SensorName,FallbackValue='Dispenser Motor'}"></TextBlock> + <TextBlock Foreground="Gray" Margin="10 0 0 0" FontFamily="Sylfaen Regular" VerticalAlignment="Center" Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl,AncestorLevel=2},Path=SensorUnits,FallbackValue='(hz)'}"></TextBlock> + </StackPanel> + </Label> + </Grid> + </graphEx:RealTimeGraphExLineErase.InnerContent> + </graphEx:RealTimeGraphExLineErase> + </Border> + </Grid> + </ContentControl> + </Grid> +</UserControl> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphControl.xaml.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphControl.xaml.cs new file mode 100644 index 000000000..dd9aa1414 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphControl.xaml.cs @@ -0,0 +1,179 @@ +using System; +using System.Collections.Generic; +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.Animation; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using RealTimeGraphEx; +using RealTimeGraphEx.Controllers; + +namespace Tango.MachineStudio.Common.Controls +{ + /// <summary> + /// Interaction logic for RealTimeGraphControl.xaml + /// </summary> + public partial class RealTimeGraphControl : UserControl, IRealTimeGraph + { + private Grid headerGrid; + + #region Properties + + /// <summary> + /// Gets or sets the name of the sensor. + /// </summary> + public String SensorName + { + get { return (String)GetValue(SensorNameProperty); } + set { SetValue(SensorNameProperty, value); } + } + public static readonly DependencyProperty SensorNameProperty = + DependencyProperty.Register("SensorName", typeof(String), typeof(RealTimeGraphControl), new PropertyMetadata(null)); + + /// <summary> + /// Gets or sets the sensor units. + /// </summary> + public String SensorUnits + { + get { return (String)GetValue(SensorUnitsProperty); } + set { SetValue(SensorUnitsProperty, value); } + } + public static readonly DependencyProperty SensorUnitsProperty = + DependencyProperty.Register("SensorUnits", typeof(String), typeof(RealTimeGraphControl), new PropertyMetadata(null)); + + + + public double Minimum + { + get { return (double)GetValue(MinimumProperty); } + set { SetValue(MinimumProperty, value); } + } + public static readonly DependencyProperty MinimumProperty = + DependencyProperty.Register("Minimum", typeof(double), typeof(RealTimeGraphControl), new PropertyMetadata(0.0)); + + + + public double Maximum + { + get { return (double)GetValue(MaximumProperty); } + set { SetValue(MaximumProperty, value); } + } + public static readonly DependencyProperty MaximumProperty = + DependencyProperty.Register("Maximum", typeof(double), typeof(RealTimeGraphControl), new PropertyMetadata(100.0)); + + + + public Color Color + { + get { return (Color)GetValue(ColorProperty); } + set { SetValue(ColorProperty, value); } + } + public static readonly DependencyProperty ColorProperty = + DependencyProperty.Register("Color", typeof(Color), typeof(RealTimeGraphControl), new PropertyMetadata(Colors.DodgerBlue)); + + + + public void InvalidateGraph() + { + InnerGraph.Clear(); + yAxis.Render(InnerGraph); + yAxisTicks.Render(InnerGraph); + } + + /// <summary> + /// Gets or sets the inner real-time graph control. + /// </summary> + public RealTimeGraphExBase InnerGraph { get; set; } + + /// <summary> + /// Gets or sets the inner graph controller. + /// </summary> + public GraphControllerBase Controller { get; set; } + + + private bool _enableToolbar; + /// <summary> + /// Gets or sets a value indicating whether to enable toolbar buttons. + /// </summary> + public bool EnableToolBar + { + get { return _enableToolbar; } + set + { + _enableToolbar = value; + + if (!value) + { + if (headerGrid != null) + { + ThicknessAnimation ani = new ThicknessAnimation(); + ani.To = new Thickness(0, -35, 0, 0); + ani.Duration = TimeSpan.FromSeconds(0.2); + headerGrid.BeginAnimation(Grid.MarginProperty, ani); + } + } + } + } + + + #endregion + + #region Events + + public event EventHandler GraphRemoveButtonPressed; + public event EventHandler GraphFullScreenButtonPressed; + + #endregion + + public RealTimeGraphControl() + { + InitializeComponent(); + EnableToolBar = true; + InnerGraph = Graph; + Controller = new GraphController(); + } + + private void OnGraphFullScreen(object sender, RoutedEventArgs e) + { + GraphFullScreenButtonPressed?.Invoke(this, new EventArgs()); + } + + private void Graph_MouseEnter(object sender, MouseEventArgs e) + { + if (EnableToolBar) + { + Grid mainGrid = sender as Grid; + headerGrid = mainGrid.Children.OfType<Grid>().ToList().First(); + ThicknessAnimation ani = new ThicknessAnimation(); + ani.To = new Thickness(0, 0, 0, 0); + ani.Duration = TimeSpan.FromSeconds(0.2); + headerGrid.BeginAnimation(Grid.MarginProperty, ani); + } + } + + private void Graph_MouseLeave(object sender, MouseEventArgs e) + { + Grid mainGrid = sender as Grid; + headerGrid = mainGrid.Children.OfType<Grid>().ToList().First(); + ThicknessAnimation ani = new ThicknessAnimation(); + ani.To = new Thickness(0, -35, 0, 0); + ani.Duration = TimeSpan.FromSeconds(0.2); + headerGrid.BeginAnimation(Grid.MarginProperty, ani); + } + + private void OnGraphRemove(object sender, RoutedEventArgs e) + { + GraphRemoveButtonPressed?.Invoke(this, new EventArgs()); + } + + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphMultiControl.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphMultiControl.xaml new file mode 100644 index 000000000..5548c452e --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphMultiControl.xaml @@ -0,0 +1,95 @@ +<UserControl x:Class="Tango.MachineStudio.Common.Controls.RealTimeGraphMultiControl" + 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:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:graphEx="clr-namespace:RealTimeGraphEx.FastGraphs;assembly=RealTimeGraphEx" + xmlns:components="clr-namespace:RealTimeGraphEx.Components;assembly=RealTimeGraphEx" + xmlns:converters="clr-namespace:Tango.MachineStudio.Common.Converters" + xmlns:local="clr-namespace:Tango.MachineStudio.Common.Controls" + mc:Ignorable="d" + d:DesignHeight="150" d:DesignWidth="300"> + + <UserControl.Resources> + <ResourceDictionary> + <ResourceDictionary.MergedDictionaries> + <!--RealTimeGraphEx--> + <ResourceDictionary Source="pack://application:,,,/RealTimeGraphEx;component/Resources/Resources.xaml"></ResourceDictionary> + <ResourceDictionary Source="../Resources/MaterialDesign.xaml"></ResourceDictionary> + + <ResourceDictionary> + <Style TargetType="ContentControl" x:Key="graphContent"> + <Style.Setters> + <Setter Property="ContentTemplate"> + <Setter.Value> + <DataTemplate> + <Grid MouseEnter="Graph_MouseEnter" MouseLeave="Graph_MouseLeave" ClipToBounds="True"> + <ContentControl Content="{Binding}"></ContentControl> + <Grid Opacity="0.8" HorizontalAlignment="Stretch" VerticalAlignment="Top" ClipToBounds="True" Height="35" Margin="0 -35 0 0"> + <StackPanel Orientation="Horizontal" Margin="5" HorizontalAlignment="Right" VerticalAlignment="Top"> + <Button Margin="0 0 5 0" Click="OnGraphFullScreen" ToolTip="Full Screen" Width="24" Height="24" BorderBrush="Transparent" Background="{StaticResource AccentColorBrush}" Style="{StaticResource MaterialDesignFloatingActionAccentButton}" > + <materialDesign:PackIcon Kind="Fullscreen" HorizontalAlignment="Right" Width="20" Height="20" Foreground="{StaticResource WhiteBrush}" /> + </Button> + <Button Click="OnGraphRemove" ToolTip="Remove" Width="24" Height="24" BorderBrush="Transparent" Background="#FF7777" Style="{StaticResource MaterialDesignFloatingActionAccentButton}" > + <materialDesign:PackIcon Kind="CloseCircle" HorizontalAlignment="Right" Width="20" Height="20" Foreground="{StaticResource WhiteBrush}" /> + </Button> + </StackPanel> + </Grid> + </Grid> + </DataTemplate> + </Setter.Value> + </Setter> + </Style.Setters> + </Style> + </ResourceDictionary> + + <ResourceDictionary> + <converters:SecondsToGraphPointsConverter x:Key="secondsToPoints"></converters:SecondsToGraphPointsConverter> + </ResourceDictionary> + </ResourceDictionary.MergedDictionaries> + </ResourceDictionary> + </UserControl.Resources> + + <Grid> + <!--Temperature--> + <ContentControl Style="{StaticResource graphContent}" Margin="0 0 0 0" MinHeight="5"> + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="40"/> + <ColumnDefinition Width="438*"/> + </Grid.ColumnDefinitions> + + <Border BorderBrush="{StaticResource AccentColorBrush}" BorderThickness="1 1 0 1" Background="#90FFFFFF"> + <StackPanel Orientation="Horizontal"> + <components:YAxisScroll x:Name="yAxis" Interval="6" Graph="{Binding ElementName=Graph}" Width="35" Foreground="{StaticResource MaterialDesignLightForeground}" VerticalOffset="-5" FontSize="8" StringFormat="#0.0"></components:YAxisScroll> + <components:YAxisTicks x:Name="yAxisTicks" SmallTickTemplate="{StaticResource graphTicksTemplate}" Width="5" SmallTicks="6" Foreground="{StaticResource MaterialDesignLightForeground}" BigTicks="10" Graph="{Binding ElementName=Graph}"></components:YAxisTicks> + </StackPanel> + </Border> + <Border Grid.Column="1" BorderThickness="1" BorderBrush="{StaticResource borderBrush}" Background="{DynamicResource graphBackground}" Margin="5 0 0 0"> + <graphEx:RealTimeGraphExMultiLineErase x:Name="Graph" x:FieldModifier="public" Controller="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=Controller}" Antialiased="True" RefreshRate="30" MarkerColor="{StaticResource graphsMarkerColor}" FillGraph="False" Minimum="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=Minimum}" Maximum="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=Maximum}" Stroke="DodgerBlue"> + <graphEx:RealTimeGraphExMultiLineErase.Components> + <components:MouseValueToolTip ToolTipTemplate="{StaticResource graphTooltipTemplate}" /> + <components:GridLines Rows="4" Columns="6" GridBrush="{DynamicResource graphGridLinesBrush}"></components:GridLines> + </graphEx:RealTimeGraphExMultiLineErase.Components> + <graphEx:RealTimeGraphExMultiLineErase.InnerContent> + <Grid> + <Label Style="{StaticResource graphLabel}"> + <StackPanel Orientation="Horizontal"> + <TextBlock VerticalAlignment="Center" Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl,AncestorLevel=2},Path=SensorName,FallbackValue='Dispensers Motors'}"></TextBlock> + <TextBlock Foreground="Gray" Margin="10 0 0 0" FontFamily="Sylfaen Regular" VerticalAlignment="Center" Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl,AncestorLevel=2},Path=SensorUnits,FallbackValue='(hz)'}"></TextBlock> + </StackPanel> + </Label> + </Grid> + </graphEx:RealTimeGraphExMultiLineErase.InnerContent> + </graphEx:RealTimeGraphExMultiLineErase> + </Border> + + <Border Grid.Column="2" Margin="5 0 0 0" HorizontalAlignment="Right" Opacity="0.8"> + <components:YAxisLegends VerticalAlignment="Center" Margin="0 0 5 0" Graph="{Binding ElementName=Graph}" Width="70" FlowDirection="RightToLeft" LegendTemplate="{StaticResource graphLegendTemplate}"> + </components:YAxisLegends> + </Border> + </Grid> + </ContentControl> + </Grid> +</UserControl> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphMultiControl.xaml.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphMultiControl.xaml.cs new file mode 100644 index 000000000..8e3b6b6e3 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphMultiControl.xaml.cs @@ -0,0 +1,162 @@ +using RealTimeGraphEx; +using RealTimeGraphEx.Controllers; +using System; +using System.Collections.Generic; +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.Animation; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Tango.MachineStudio.Common.Controls +{ + /// <summary> + /// Interaction logic for RealTimeGraphControl.xaml + /// </summary> + public partial class RealTimeGraphMultiControl : UserControl , IRealTimeGraph + { + private Grid headerGrid; + + #region Properties + + /// <summary> + /// Gets or sets the name of the sensor. + /// </summary> + public String SensorName + { + get { return (String)GetValue(SensorNameProperty); } + set { SetValue(SensorNameProperty, value); } + } + public static readonly DependencyProperty SensorNameProperty = + DependencyProperty.Register("SensorName", typeof(String), typeof(RealTimeGraphMultiControl), new PropertyMetadata(null)); + + /// <summary> + /// Gets or sets the sensor units. + /// </summary> + public String SensorUnits + { + get { return (String)GetValue(SensorUnitsProperty); } + set { SetValue(SensorUnitsProperty, value); } + } + public static readonly DependencyProperty SensorUnitsProperty = + DependencyProperty.Register("SensorUnits", typeof(String), typeof(RealTimeGraphMultiControl), new PropertyMetadata(null)); + + public double Minimum + { + get { return (double)GetValue(MinimumProperty); } + set { SetValue(MinimumProperty, value); } + } + public static readonly DependencyProperty MinimumProperty = + DependencyProperty.Register("Minimum", typeof(double), typeof(RealTimeGraphMultiControl), new PropertyMetadata(0.0)); + + + + public double Maximum + { + get { return (double)GetValue(MaximumProperty); } + set { SetValue(MaximumProperty, value); } + } + public static readonly DependencyProperty MaximumProperty = + DependencyProperty.Register("Maximum", typeof(double), typeof(RealTimeGraphMultiControl), new PropertyMetadata(100.0)); + + public void InvalidateGraph() + { + InnerGraph.Clear(); + yAxis.Render(InnerGraph); + yAxisTicks.Render(InnerGraph); + } + + /// <summary> + /// Gets or sets the inner real-time graph control. + /// </summary> + public RealTimeGraphExBase InnerGraph { get; set; } + + /// <summary> + /// Gets or sets the inner graph controller. + /// </summary> + public GraphControllerBase Controller { get; set; } + + private bool _enableToolbar; + /// <summary> + /// Gets or sets a value indicating whether to enable toolbar buttons. + /// </summary> + public bool EnableToolBar + { + get { return _enableToolbar; } + set + { + _enableToolbar = value; + + if (!value) + { + if (headerGrid != null) + { + ThicknessAnimation ani = new ThicknessAnimation(); + ani.To = new Thickness(0, -35, 0, 0); + ani.Duration = TimeSpan.FromSeconds(0.2); + headerGrid.BeginAnimation(Grid.MarginProperty, ani); + } + } + } + } + + #endregion + + #region Events + + public event EventHandler GraphRemoveButtonPressed; + public event EventHandler GraphFullScreenButtonPressed; + + #endregion + + public RealTimeGraphMultiControl() + { + InitializeComponent(); + EnableToolBar = true; + InnerGraph = Graph; + Controller = new GraphMultiController(); + } + + private void OnGraphFullScreen(object sender, RoutedEventArgs e) + { + GraphFullScreenButtonPressed?.Invoke(this, new EventArgs()); + } + + private void Graph_MouseEnter(object sender, MouseEventArgs e) + { + if (EnableToolBar) + { + Grid mainGrid = sender as Grid; + headerGrid = mainGrid.Children.OfType<Grid>().ToList().First(); + ThicknessAnimation ani = new ThicknessAnimation(); + ani.To = new Thickness(0, 0, 0, 0); + ani.Duration = TimeSpan.FromSeconds(0.2); + headerGrid.BeginAnimation(Grid.MarginProperty, ani); + } + } + + private void Graph_MouseLeave(object sender, MouseEventArgs e) + { + Grid mainGrid = sender as Grid; + headerGrid = mainGrid.Children.OfType<Grid>().ToList().First(); + ThicknessAnimation ani = new ThicknessAnimation(); + ani.To = new Thickness(0, -35, 0, 0); + ani.Duration = TimeSpan.FromSeconds(0.2); + headerGrid.BeginAnimation(Grid.MarginProperty, ani); + } + + private void OnGraphRemove(object sender, RoutedEventArgs e) + { + GraphRemoveButtonPressed?.Invoke(this, new EventArgs()); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/TableGrid.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/TableGrid.cs new file mode 100644 index 000000000..07fd0c446 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/TableGrid.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; + +namespace Tango.MachineStudio.Common.Controls +{ + public class TableGrid : Grid + { + public TableGrid() + { + ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Auto) }); + ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) }); + this.Loaded += TableGrid_Loaded; + } + + private void TableGrid_Loaded(object sender, RoutedEventArgs e) + { + InvalidateGrid(); + } + + protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved) + { + base.OnVisualChildrenChanged(visualAdded, visualRemoved); + } + + protected override Size ArrangeOverride(Size arrangeSize) + { + return base.ArrangeOverride(arrangeSize); + } + + private void InvalidateGrid() + { + RowDefinitions.Clear(); + RowDefinitions.Add(new RowDefinition() { Height = new GridLength(50, GridUnitType.Pixel) }); + + int currentRow = 0; + + for (int i = 0; i < Children.Count; i++) + { + SetRow(Children[i], currentRow); + + if (i % 2 != 0) + { + SetColumn(Children[i], 1); + (Children[i] as FrameworkElement).Margin = new Thickness(20, 0, 0, 0); + currentRow++; + RowDefinitions.Add(new RowDefinition() { Height = new GridLength(50, GridUnitType.Pixel) }); + } + + (Children[i] as FrameworkElement).VerticalAlignment = VerticalAlignment.Bottom; + } + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Converters/PointToMarginConverter.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Converters/PointToMarginConverter.cs index e6587b1ee..94748fb26 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Converters/PointToMarginConverter.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Converters/PointToMarginConverter.cs @@ -9,8 +9,13 @@ using System.Windows.Data; namespace Tango.MachineStudio.Common.Converters { + /// <summary> + /// Represents a <see cref="Point"/> to <see cref="Thickness"/> binding converter. + /// </summary> + /// <seealso cref="System.Windows.Data.IValueConverter" /> public class PointToMarginConverter : IValueConverter { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { Point p = (Point)value; diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Converters/SecondsToGraphPointsConverter.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Converters/SecondsToGraphPointsConverter.cs new file mode 100644 index 000000000..17df7b9d5 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Converters/SecondsToGraphPointsConverter.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; + +namespace Tango.MachineStudio.Common.Converters +{ + /// <summary> + /// Converts number of seconds to graph FIFO capacity. + /// </summary> + /// <seealso cref="System.Windows.Data.IValueConverter" /> + public class SecondsToGraphPointsConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + double arrLength = double.Parse(parameter.ToString()); + return Helpers.GraphsHelper.GetMaxPoints(arrLength); + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + return value; + } + } +}
\ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Diagnostics/DefaultDiagnosticsFrameProvider.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Diagnostics/DefaultDiagnosticsFrameProvider.cs new file mode 100644 index 000000000..b77619ac2 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Diagnostics/DefaultDiagnosticsFrameProvider.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Integration.Operators; +using Tango.MachineStudio.Common.StudioApplication; +using Tango.PMR.Diagnostics; + +namespace Tango.MachineStudio.Common.Diagnostics +{ + /// <summary> + /// Represents the default diagnostics frame provider. + /// </summary> + /// <seealso cref="Tango.MachineStudio.Common.Diagnostics.IDiagnosticsFrameProvider" /> + public class DefaultDiagnosticsFrameProvider : IDiagnosticsFrameProvider + { + /// <summary> + /// Disables the frame delivery from the current connected machine and enables the manual push frame method. + /// </summary> + public bool Disable { get; set; } + + /// <summary> + /// Occurs when a new data frame is available. + /// </summary> + public event EventHandler<PushDiagnosticsResponse> FrameReceived; + + /// <summary> + /// Initializes a new instance of the <see cref="DefaultDiagnosticsFrameProvider"/> class. + /// </summary> + /// <param name="applicationManager">The application manager.</param> + public DefaultDiagnosticsFrameProvider(IStudioApplicationManager applicationManager) + { + applicationManager.ConnectedMachineChanged += ApplicationManager_ConnectedMachineChanged; + } + + /// <summary> + /// Applications the manager connected machine changed. + /// </summary> + /// <param name="sender">The sender.</param> + /// <param name="machine">The machine.</param> + private void ApplicationManager_ConnectedMachineChanged(object sender, Integration.Services.IExternalBridgeClient machine) + { + if (machine != null) + { + (machine as MachineOperator).DiagnosticsDataAvailable += DefaultDiagnosticsFrameProvider_DiagnosticsDataAvailable; + } + } + + /// <summary> + /// Defaults the diagnostics frame provider diagnostics data available. + /// </summary> + /// <param name="sender">The sender.</param> + /// <param name="frame">The frame.</param> + private void DefaultDiagnosticsFrameProvider_DiagnosticsDataAvailable(object sender, PushDiagnosticsResponse frame) + { + if (!Disable) + { + OnFrameReceived(frame); + } + } + + /// <summary> + /// Push frames manual. (Only when Disable = true) + /// </summary> + /// <param name="frame">The frame.</param> + public void PushFrame(PushDiagnosticsResponse frame) + { + if (Disable) + { + OnFrameReceived(frame); + } + } + + /// <summary> + /// Raises the <see cref="FrameReceived"/> event. + /// </summary> + /// <param name="frame">The frame.</param> + protected virtual void OnFrameReceived(PushDiagnosticsResponse frame) + { + FrameReceived?.Invoke(this, frame); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Diagnostics/IDiagnosticsFrameProvider.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Diagnostics/IDiagnosticsFrameProvider.cs new file mode 100644 index 000000000..0d63b59b6 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Diagnostics/IDiagnosticsFrameProvider.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.PMR.Diagnostics; + +namespace Tango.MachineStudio.Common.Diagnostics +{ + /// <summary> + /// Represents a tango machine diagnostics frame provider. + /// </summary> + public interface IDiagnosticsFrameProvider + { + /// <summary> + /// Occurs when a new data frame is available. + /// </summary> + event EventHandler<PushDiagnosticsResponse> FrameReceived; + + /// <summary> + /// Disables the frame delivery from the current connected machine and enables the manual push frame method. + /// </summary> + bool Disable { get; set; } + + /// <summary> + /// Push frames manual. (Only when Disable = true) + /// </summary> + /// <param name="frame">The frame.</param> + void PushFrame(PushDiagnosticsResponse frame); + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/ExtensionMethods/IStudioMessageExtensions.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/ExtensionMethods/IStudioMessageExtensions.cs index 83183f328..7ae259e04 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/ExtensionMethods/IStudioMessageExtensions.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/ExtensionMethods/IStudioMessageExtensions.cs @@ -6,8 +6,15 @@ using System.Text; using System.Threading.Tasks; using Tango.MachineStudio.Common.Messages; +/// <summary> +/// Contains <see cref="IStudioMessage"/> extension methods. +/// </summary> public static class IStudioMessageExtensions { + /// <summary> + /// Sends the message. + /// </summary> + /// <param name="message">The message.</param> public static void Send(this IStudioMessage message) { Messenger.Default.Send(message); diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/ExtensionMethods/UserExtensions.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/ExtensionMethods/UserExtensions.cs deleted file mode 100644 index a6c98319e..000000000 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/ExtensionMethods/UserExtensions.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Tango.DAL.Observables; - -public static class UserExtensions -{ - public static bool HasPermission(this User user, Permissions permission) - { - return user.UsersRoles.Select(x => x.Role).ToList().SelectMany(x => x.RolesPermissions).ToList().Exists(x => x.Permission.Code == permission.ToInt32()); - } -} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/digital-7.ttf b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/digital-7.ttf Binary files differnew file mode 100644 index 000000000..5dbe6f908 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Fonts/digital-7.ttf diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Helpers/GraphsHelper.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Helpers/GraphsHelper.cs new file mode 100644 index 000000000..53e832eb5 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Helpers/GraphsHelper.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Settings; + +namespace Tango.MachineStudio.Common.Helpers +{ + /// <summary> + /// Contains RealTimeGraphEx helper methods. + /// </summary> + public static class GraphsHelper + { + /// <summary> + /// Gets the maximum points graph points by correlating between seconds duration from settings and expected graph points per frame. + /// </summary> + /// <param name="pointsPerFrame">Length of graph points per frame.</param> + /// <returns></returns> + public static int GetMaxPoints(double pointsPerFrame) + { + try + { + double seconds = SettingsManager.Default.MachineStudio.TechnicianModule.GraphsDuration; + double pullRate = SettingsManager.Default.MachineStudio.TechnicianModule.GraphsPullingInterval; + return (int)(((pullRate * pointsPerFrame * 10 * seconds) * (10 / pullRate)) * 0.65); + } + catch (Exception) + { + return 300; + } + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/IStudioModule.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/IStudioModule.cs index 902a45a2f..7718c0a7a 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/IStudioModule.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/IStudioModule.cs @@ -5,24 +5,54 @@ using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Media.Imaging; -using Tango.DAL.Observables; +using Tango.Integration.Observables; namespace Tango.MachineStudio.Common { + /// <summary> + /// Represents a Machine Studio module. + /// </summary> + /// <seealso cref="System.IDisposable" /> public interface IStudioModule : IDisposable { + /// <summary> + /// Gets the module name. + /// </summary> String Name { get; } + /// <summary> + /// Gets the module description. + /// </summary> String Description { get; } + /// <summary> + /// Gets the module cover image. + /// </summary> BitmapSource Image { get; } + /// <summary> + /// Gets the module entry point view. + /// </summary> FrameworkElement MainView { get; } + /// <summary> + /// Gets the permission required to see and load this module. + /// </summary> Permissions Permission { get; } + /// <summary> + /// Gets a value indicating whether this module has been initialized. + /// </summary> bool IsInitialized { get; } + /// <summary> + /// Perform any operations required to initialize this module. + /// </summary> void Initialize(); + + /// <summary> + /// Sets a value indicating whether this module is loaded. + /// </summary> + bool IsLoaded { set; get; } } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Messages/IStudioMessage.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Messages/IStudioMessage.cs index 7d1232c7b..61056ab16 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Messages/IStudioMessage.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Messages/IStudioMessage.cs @@ -6,6 +6,9 @@ using System.Threading.Tasks; namespace Tango.MachineStudio.Common.Messages { + /// <summary> + /// Represents an MVVM base interface for MVVM Light Messenger messages. + /// </summary> public interface IStudioMessage { diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Modules/IStudioModuleLoader.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Modules/IStudioModuleLoader.cs index d67accbc1..1fd72c53a 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Modules/IStudioModuleLoader.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Modules/IStudioModuleLoader.cs @@ -7,12 +7,31 @@ using System.Threading.Tasks; namespace Tango.MachineStudio.Common.Modules { + /// <summary> + /// Represents a Machine Studio <see cref="IStudioModule"/> modules loading engine. + /// </summary> public interface IStudioModuleLoader { + /// <summary> + /// Gets all loaded modules. + /// </summary> ObservableCollection<IStudioModule> AllModules { get; } + /// <summary> + /// Gets all the user permitted modules. + /// </summary> ObservableCollection<IStudioModule> UserModules { get; } + /// <summary> + /// Gets the studio module of type T if loaded. + /// </summary> + /// <typeparam name="T"></typeparam> + /// <returns></returns> + T GetStudioModule<T>() where T : IStudioModule; + + /// <summary> + /// Loads all available Machine Studio modules. + /// </summary> void LoadModules(); } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Navigation/INavigationManager.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Navigation/INavigationManager.cs index 631f9e2eb..4d1cbea8c 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Navigation/INavigationManager.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Navigation/INavigationManager.cs @@ -6,8 +6,15 @@ using System.Threading.Tasks; namespace Tango.MachineStudio.Common.Navigation { + /// <summary> + /// Represents the Machine Studio views navigation manager. + /// </summary> public interface INavigationManager { + /// <summary> + /// Navigates to the specified view. + /// </summary> + /// <param name="view">The view.</param> void NavigateTo(NavigationView view); } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Navigation/NavigationView.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Navigation/NavigationView.cs index 77dbaf5b4..db0f0471f 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Navigation/NavigationView.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Navigation/NavigationView.cs @@ -6,6 +6,9 @@ using System.Threading.Tasks; namespace Tango.MachineStudio.Common.Navigation { + /// <summary> + /// Represents the available views to navigate to using the <see cref="INavigationManager"/>. + /// </summary> public enum NavigationView { LoadingView, diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Notifications/BarItem.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Notifications/BarItem.cs new file mode 100644 index 000000000..d46bf5b5d --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Notifications/BarItem.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using Tango.Core; + +namespace Tango.MachineStudio.Common.Notifications +{ + public class BarItem : ExtendedObject, IDisposable + { + private INotificationProvider _notificationProvider; + + public FrameworkElement Element { get; set; } + + public BarItem(INotificationProvider notificationProvider) + { + _notificationProvider = notificationProvider; + } + + public BarItem(INotificationProvider notificationProvider, FrameworkElement element) : this(notificationProvider) + { + Element = element; + } + + /// <summary> + /// Removed this item from the queue. + /// </summary> + public void Pop() + { + _notificationProvider.PopBarItem(this); + } + + /// <summary> + /// Pushes this item to the queue. + /// </summary> + public void Push() + { + _notificationProvider.PushBarItem(this); + } + + /// <summary> + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// </summary> + public void Dispose() + { + Pop(); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Notifications/DialogViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Notifications/DialogViewVM.cs index e5e4cac78..5fcd63071 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Notifications/DialogViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Notifications/DialogViewVM.cs @@ -8,11 +8,18 @@ using Tango.SharedUI; namespace Tango.MachineStudio.Common.Notifications { + /// <summary> + /// Represents a dialog view model base class. + /// </summary> + /// <seealso cref="Tango.SharedUI.ViewModel" /> public abstract class DialogViewVM : ViewModel { public event Action Accepted; public event Action Canceled; + /// <summary> + /// Initializes a new instance of the <see cref="DialogViewVM"/> class. + /// </summary> public DialogViewVM() { CanClose = true; @@ -20,25 +27,39 @@ namespace Tango.MachineStudio.Common.Notifications } private bool _canClose; - + /// <summary> + /// Gets or sets a value indicating whether this dialog can be closed. + /// </summary> public bool CanClose { get { return _canClose; } set { _canClose = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } } + /// <summary> + /// Gets or sets the close command. + /// </summary> public RelayCommand CloseCommand { get; set; } + /// <summary> + /// Called when the dialog has been shown. + /// </summary> public virtual void OnShow() { } + /// <summary> + /// Invokes the <see cref="Accepted"/> event. + /// </summary> protected virtual void Accept() { Accepted?.Invoke(); } + /// <summary> + /// Invokes the <see cref="Canceled"/> event. + /// </summary> protected virtual void Cancel() { Canceled?.Invoke(); diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Notifications/INotificationProvider.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Notifications/INotificationProvider.cs index 937a39ec2..e1b6275bd 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Notifications/INotificationProvider.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Notifications/INotificationProvider.cs @@ -10,34 +10,135 @@ using System.Windows.Media; namespace Tango.MachineStudio.Common.Notifications { + /// <summary> + /// Represents the Machine Studio user notification provider responsible for displaying information, alerts and dialogs to the user. + /// </summary> public interface INotificationProvider { + /// <summary> + /// Gets the collection of active task items. + /// </summary> ObservableCollection<TaskItem> TaskItems { get; } + /// <summary> + /// Gets the collection of active bar items. + /// </summary> + ObservableCollection<BarItem> BarItems { get; } + + /// <summary> + /// Gets the current displayed task item. + /// </summary> TaskItem CurrentTaskItem { get; } + /// <summary> + /// Gets a value indicating whether there are any queued task items. + /// </summary> bool HasTaskItems { get; } + /// <summary> + /// Pushes the specified task item to the queue. + /// </summary> + /// <param name="taskItem">The task item.</param> void PushTaskItem(TaskItem taskItem); + /// <summary> + /// Create and push a new task item from the specified message. + /// </summary> + /// <param name="message">The message.</param> + /// <returns></returns> TaskItem PushTaskItem(String message); + /// <summary> + /// Creates and push a new bar item from the specified framework element. + /// </summary> + /// <param name="element">The element.</param> + /// <returns></returns> + BarItem PushBarItem(FrameworkElement element); + + /// <summary> + /// Pushes the specified bar item. + /// </summary> + /// <param name="barItem">The bar item.</param> + /// <returns></returns> + BarItem PushBarItem(BarItem barItem); + + /// <summary> + /// Removed the specified task item from the queue. + /// </summary> + /// <param name="taskItem">The task item.</param> void PopTaskItem(TaskItem taskItem); + /// <summary> + /// Removed the specified bar item. + /// </summary> + /// <param name="barItem">The bar item.</param> + void PopBarItem(BarItem barItem); + + /// <summary> + /// Creates a new instance of the specified View type and displays it as a modal dialog. + /// </summary> + /// <typeparam name="View">The type of the view.</typeparam> + /// <typeparam name="VM">The type of the view model.</typeparam> + /// <param name="onAccept">Accept button callback.</param> + /// <param name="onCancel">Cancel button callback.</param> void ShowModalDialog<View, VM>(Action<VM> onAccept, Action onCancel) where View : FrameworkElement where VM : DialogViewVM; + /// <summary> + /// Creates a new view by a naming convention of the specified view model type. + /// </summary> + /// <typeparam name="VM">The type of the view model.</typeparam> + /// <param name="onAccept">Accept button callback.</param> + /// <param name="onCancel">Cancel button callback.</param> void ShowModalDialog<VM>(Action<VM> onAccept, Action onCancel) where VM : DialogViewVM; + /// <summary> + /// Creates a new view by a naming convention of the specified view model type. + /// </summary> + /// <typeparam name="VM">The type of the view model.</typeparam> + /// <param name="onAccept">Accept button callback.</param> void ShowModalDialog<VM>(Action<VM> onAccept) where VM : DialogViewVM; - bool? ShowDialog(PackIconKind icon, Brush iconColor, String message, bool hasCancel); + /// <summary> + /// Display a message box. + /// </summary> + /// <param name="icon">The icon.</param> + /// <param name="iconColor">Color of the icon.</param> + /// <param name="message">The message.</param> + /// <param name="hasCancel">if set to <c>true</c> displays the cancel button.</param> + /// <returns></returns> + bool? ShowMessageBox(PackIconKind icon, Brush iconColor, String message, bool hasCancel); + /// <summary> + /// Shows an information message box. + /// </summary> + /// <param name="message">The message.</param> void ShowInfo(String message); - void ShowWarnning(String message); + /// <summary> + /// Shows warning message box. + /// </summary> + /// <param name="message">The message.</param> + void ShowWarning(String message); + /// <summary> + /// Shows an error message box. + /// </summary> + /// <param name="message">The message.</param> void ShowError(String message); + /// <summary> + /// Shows a question message box. + /// </summary> + /// <param name="message">The message.</param> bool ShowQuestion(String message); + + /// <summary> + /// Shows a dialog with a text input field and returns the response. + /// </summary> + /// <param name="message">The message.</param> + /// <param name="hint">Text field hint.</param> + /// <param name="defaultResponse">Optional default response.</param> + /// <returns></returns> + String ShowTextInput(String message, String hint, String defaultResponse = null); } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Notifications/TaskItem.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Notifications/TaskItem.cs index 0cf5e2c8e..110fbfa74 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Notifications/TaskItem.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Notifications/TaskItem.cs @@ -7,32 +7,53 @@ using Tango.Core; namespace Tango.MachineStudio.Common.Notifications { + /// <summary> + /// Represents a Machine Studio "work-bar" item. + /// </summary> + /// <seealso cref="Tango.Core.ExtendedObject" /> + /// <seealso cref="System.IDisposable" /> public class TaskItem : ExtendedObject, IDisposable { private INotificationProvider _notificationProvider; + /// <summary> + /// Initializes a new instance of the <see cref="TaskItem"/> class. + /// </summary> + /// <param name="notificationProvider">The notification provider.</param> public TaskItem(INotificationProvider notificationProvider) { _notificationProvider = notificationProvider; } private String _message; + /// <summary> + /// Gets or sets the message. + /// </summary> public String Message { get { return _message; } set { _message = value; RaisePropertyChangedAuto(); } } + /// <summary> + /// Removed this item from the queue. + /// </summary> public void Pop() { _notificationProvider.PopTaskItem(this); } + /// <summary> + /// Pushes this item to the queue. + /// </summary> public void Push() { _notificationProvider.PushTaskItem(this); } + /// <summary> + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// </summary> public void Dispose() { Pop(); diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Properties/AssemblyInfo.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Properties/AssemblyInfo.cs index 33d6edb60..f03b250be 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Properties/AssemblyInfo.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Properties/AssemblyInfo.cs @@ -15,3 +15,6 @@ using System.Windows; //(used if a resource is not found in the page, // app, or any theme specific resource dictionaries) )] + +//Friends With +[assembly: InternalsVisibleTo("Tango.MachineStudio.UI")] diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Resources/GradientOffsetSlider.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Resources/GradientOffsetSlider.xaml new file mode 100644 index 000000000..28d29a727 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Resources/GradientOffsetSlider.xaml @@ -0,0 +1,83 @@ +<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:local="clr-namespace:Tango.MachineStudio.Common.Resources" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"> + + + <Style x:Key="SliderRepeatButton" TargetType="RepeatButton"> + <Setter Property="SnapsToDevicePixels" Value="true" /> + <Setter Property="OverridesDefaultStyle" Value="true" /> + <Setter Property="IsTabStop" Value="false" /> + <Setter Property="Focusable" Value="false" /> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="RepeatButton"> + <Border BorderThickness="1" BorderBrush="#8A8A8A" Background="#8A8A8A" Height="3"/> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <Style x:Key="SliderRepeatButton1" TargetType="RepeatButton"> + <Setter Property="SnapsToDevicePixels" Value="true" /> + <Setter Property="OverridesDefaultStyle" Value="true" /> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="RepeatButton"> + <Border SnapsToDevicePixels="True" Background="#7F7F7F" BorderThickness="1" BorderBrush="#777777" Height="3"/> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <Style x:Key="SliderThumb" TargetType="Thumb"> + <Setter Property="SnapsToDevicePixels" Value="true" /> + <Setter Property="OverridesDefaultStyle" Value="true" /> + <Setter Property="Background" Value="Transparent"></Setter> + <Setter Property="Margin" Value="-11 -20 0 0"></Setter> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="Thumb"> + <Canvas> + <materialDesign:PackIcon Kind="MapMarker" Width="24" Background="Transparent" Height="24" IsHitTestVisible="True" Margin="0 0 0 0" /> + </Canvas> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <ControlTemplate x:Key="Slider" TargetType="Slider"> + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" MinHeight="{TemplateBinding MinHeight}" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <Track Grid.Row="1" x:Name="PART_Track" > + <Track.DecreaseRepeatButton> + <RepeatButton Style="{StaticResource SliderRepeatButton1}" Command="Slider.DecreaseLarge" /> + </Track.DecreaseRepeatButton> + <Track.Thumb> + <Thumb Style="{StaticResource SliderThumb}" /> + </Track.Thumb> + <Track.IncreaseRepeatButton> + <RepeatButton Style="{StaticResource SliderRepeatButton}" Command="Slider.IncreaseLarge" /> + </Track.IncreaseRepeatButton> + </Track> + </Grid> + </ControlTemplate> + + <Style x:Key="GradientOffsetSlider" TargetType="Slider"> + <Setter Property="Focusable" Value="False"/> + <Setter Property="SnapsToDevicePixels" Value="true" /> + <Setter Property="OverridesDefaultStyle" Value="true" /> + <Style.Triggers> + <Trigger Property="Orientation" Value="Horizontal"> + <Setter Property="MinHeight" Value="21" /> + <Setter Property="MinWidth" Value="104" /> + <Setter Property="Template" Value="{StaticResource Slider}" /> + </Trigger> + </Style.Triggers> + </Style> + +</ResourceDictionary>
\ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Resources/MaterialDesign.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Resources/MaterialDesign.xaml index 58bb9ef34..ca0685f3c 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Resources/MaterialDesign.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Resources/MaterialDesign.xaml @@ -1,7 +1,9 @@ <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:converters="clr-namespace:MaterialDesignThemes.Wpf.Converters;assembly=MaterialDesignThemes.Wpf" + xmlns:converters="clr-namespace:MaterialDesignThemes.Wpf.Converters;assembly=MaterialDesignThemes.Wpf" xmlns:editors="clr-namespace:Tango.AutoComplete.Editors;assembly=Tango.AutoComplete" + xmlns:dragAndDrop="clr-namespace:Tango.DragAndDrop;assembly=Tango.DragAndDrop" + xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:local="clr-namespace:Tango.MachineStudio.Common.Resources"> <ResourceDictionary.MergedDictionaries> <!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! --> @@ -43,6 +45,7 @@ </ResourceDictionary> <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/materialdesigntheme.ProgressBar.xaml"/> + <ResourceDictionary Source="GradientOffsetSlider.xaml" /> <!--MahApps Brushes--> <ResourceDictionary> @@ -62,6 +65,11 @@ <SolidColorBrush x:Key="IdealForegroundColorBrush" Color="{DynamicResource Primary500Foreground}" /> <SolidColorBrush x:Key="IdealForegroundDisabledBrush" Color="{DynamicResource Primary500}" Opacity="0.4" /> </ResourceDictionary> + + <!--Fonts--> + <ResourceDictionary> + <FontFamily x:Key="digital-7">../Fonts/#digital-7</FontFamily> + </ResourceDictionary> <!--Styles--> <ResourceDictionary> @@ -172,6 +180,302 @@ </Setter.Value> </Setter> </Style> + + + <!--Extensions--> + + <FontFamily x:Key="FontName">Segoe UI</FontFamily> + <FontFamily x:Key="NotesFont">Lucida Console</FontFamily> + + <sys:Double x:Key="ExtraExtraLargeFontSize">28</sys:Double> + <sys:Double x:Key="ExtraLargeFontSize">26</sys:Double> + <sys:Double x:Key="LargeFontSize">20</sys:Double> + <sys:Double x:Key="MediumFontSize">16</sys:Double> + <sys:Double x:Key="SmallFontSize">14</sys:Double> + <sys:Double x:Key="MiniFontSize">12</sys:Double> + <sys:Double x:Key="TinyFontSize">9</sys:Double> + + <!--Colors--> + <Color x:Key="borderColor">Silver</Color> + <Color x:Key="graphGridLinesColor">#FFE9E9E9</Color> + <Color x:Key="graphsMarkerColor">Gray</Color> + <Color x:Key="materialColor">#03A9F4</Color> + + <!--Brushes--> + <SolidColorBrush x:Key="borderBrush" Color="{StaticResource borderColor}"></SolidColorBrush> + <SolidColorBrush x:Key="graphGridLinesBrush" Color="{StaticResource graphGridLinesColor}"></SolidColorBrush> + <SolidColorBrush x:Key="BlackBrush" Color="#545454"></SolidColorBrush> + + <SolidColorBrush x:Key="graphGridLinesLightBrush" Color="{StaticResource graphGridLinesColor}"></SolidColorBrush> + <SolidColorBrush x:Key="graphGridLinesDarkBrush" Color="#FF2E2E2E"></SolidColorBrush> + + <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0" x:Key="graphBackgroundLight"> + <GradientStop Color="White"/> + <GradientStop Color="#FFE9E9E9" Offset="1"/> + </LinearGradientBrush> + + <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0" x:Key="graphBackgroundDark"> + <GradientStop Color="Black"/> + <GradientStop Color="#FF333333" Offset="1"/> + </LinearGradientBrush> + + <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0" x:Key="graphBackground"> + <GradientStop Color="White"/> + <GradientStop Color="#FFE9E9E9" Offset="1"/> + </LinearGradientBrush> + + <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0" x:Key="graphLabelBackground" Opacity="0.7"> + <GradientStop Color="White"/> + <GradientStop Color="#FFD9D9D9" Offset="1"/> + </LinearGradientBrush> + + <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0" x:Key="graphLegendBackground" Opacity="0.7"> + <GradientStop Color="#FFE9E9E9"/> + <GradientStop Color="#FFBDBDBD" Offset="1"/> + </LinearGradientBrush> + + <SolidColorBrush Color="#FFF1F1F1" x:Key="topBarBackgroundBrush"></SolidColorBrush> + <!--Brushes--> + + <!--Graph Label--> + <Style x:Key="graphLabel" TargetType="Label"> + <Style.Setters> + <Setter Property="IsHitTestVisible" Value="False"></Setter> + <Setter Property="Margin" Value="-1 -1 0 0"></Setter> + <Setter Property="HorizontalAlignment" Value="Left"></Setter> + <Setter Property="VerticalAlignment" Value="Top"></Setter> + <Setter Property="Padding" Value="0"></Setter> + <Setter Property="ContentTemplate"> + <Setter.Value> + <DataTemplate> + <Border Width="Auto" Padding="0 0 20 0" Height="25" BorderBrush="{StaticResource AccentColorBrush}" BorderThickness="1" CornerRadius="0 0 30 0" Background="{StaticResource graphLabelBackground}" > + <Label Margin="5 0 0 0" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="{StaticResource TinyFontSize}" Content="{Binding}"></Label> + </Border> + </DataTemplate> + </Setter.Value> + </Setter> + </Style.Setters> + </Style> + <!--Graph Label--> + + + <!--Graph Ticks Template--> + <DataTemplate x:Key="graphTicksTemplate"> + <Ellipse Width="3" Height="3" Margin="0 0 0 0" Fill="{StaticResource AccentColorBrush}"></Ellipse> + </DataTemplate> + <!--Graph Ticks Template--> + + <DataTemplate x:Key="graphTooltipTemplate"> + <Border CornerRadius="5" BorderThickness="1" BorderBrush="White" Padding="8" MinWidth="50" Margin="20 0 20 0"> + <Border.Background> + <SolidColorBrush Color="Black" Opacity="0.5"></SolidColorBrush> + </Border.Background> + <TextBlock Foreground="White" FontSize="10" HorizontalAlignment="Center" TextAlignment="Center" Text="{Binding StringFormat='0.000'}"></TextBlock> + </Border> + </DataTemplate> + + <!--Graph Legend Template--> + <DataTemplate x:Key="graphLegendTemplate"> + <Border Width="20" Height="20" Margin="2"> + <Grid> + <ToggleButton IsChecked="{Binding IsVisible}" Padding="0" Margin="0" Background="Transparent" BorderBrush="{x:Null}" BorderThickness="0"> + <ToggleButton.Style> + <Style TargetType="ToggleButton"> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate> + <Grid Background="Transparent"> + <Grid> + <Ellipse HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Fill="{StaticResource graphLegendBackground}" StrokeThickness="1"> + <Ellipse.Style> + <Style TargetType="Ellipse"> + <Style.Triggers> + <DataTrigger Binding="{Binding IsVisible}" Value="True"> + <Setter Property="Stroke" Value="{Binding Stroke}"></Setter> + </DataTrigger> + <DataTrigger Binding="{Binding IsVisible}" Value="False"> + <Setter Property="Stroke" Value="Transparent"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </Ellipse.Style> + </Ellipse> + <TextBlock FontSize="8" Text="{Binding Name}" VerticalAlignment="Center" Foreground="Black" FontWeight="DemiBold" HorizontalAlignment="Center"></TextBlock> + </Grid> + </Grid> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + </ToggleButton.Style> + </ToggleButton> + </Grid> + </Border> + </DataTemplate> + <!--Graph Legend Template--> + + + <Style TargetType="{x:Type ListBoxItem}" x:Key="basicListBoxItem"> + <Setter Property="Background" Value="Transparent"/> + <Setter Property="BorderThickness" Value="0"></Setter> + <Setter Property="FocusVisualStyle" Value="{x:Null}"></Setter> + <Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter> + <Setter Property="Padding" Value="0"/> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type ListBoxItem}"> + <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0" Background="{TemplateBinding Background}" Padding="0" SnapsToDevicePixels="true"> + <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> + </Border> + <ControlTemplate.Triggers> + <Trigger Property="IsSelected" Value="true"> + <Setter Property="Background" TargetName="Bd" Value="Transparent"/> + </Trigger> + <MultiTrigger> + <MultiTrigger.Conditions> + <Condition Property="IsSelected" Value="true"/> + <Condition Property="Selector.IsSelectionActive" Value="false"/> + </MultiTrigger.Conditions> + <Setter Property="Background" TargetName="Bd" Value="Transparent"/> + </MultiTrigger> + <Trigger Property="IsEnabled" Value="false"> + <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <PathGeometry x:Key="CirclePath">M46.615 402.03c6.549 9.313 13.718 18.176 21.456 26.528l23.472-21.728c-6.767-7.3-13.038-15.045-18.768-23.184 L46.615 402.03z M32.007 254.83c0.178-112.07 83.047-206.811 194.096-221.904l-4.192-31.728C81.787 20.041-16.53 148.91 2.314 289.033 c3.942 29.31 12.932 57.716 26.573 83.957l28.368-14.784C40.563 326.311 31.897 290.828 32.007 254.83z M92.807 452.03c8.765 7.252 17.995 13.923 27.632 19.968l16.976-27.2c-8.448-5.292-16.535-11.139-24.208-17.504 L92.807 452.03z M361.761 21.742c-22.756-10.308-46.898-17.229-71.658-20.544l-4.192 31.728 c122.555 16.88 208.221 129.915 191.341 252.469C462.017 396.001 367.656 478.501 256.007 478.83 c-31.831 0.078-63.306-6.694-92.288-19.856l-13.216 29.152c128.788 58.337 280.484 1.225 338.821-127.563 C547.661 231.775 490.549 80.079 361.761 21.742z</PathGeometry> + + <Style TargetType="ContentControl" x:Key="numberBorder"> + <Style.Setters> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="ContentControl"> + <Grid> + <Viewbox> + <Path Data="{StaticResource CirclePath}" Fill="{TemplateBinding Foreground}"></Path> + </Viewbox> + <ContentPresenter Content="{TemplateBinding Content}" /> + </Grid> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style.Setters> + </Style> + + <Style x:Key="emptyToggleButton" TargetType="ToggleButton"> + <Setter Property="Background" Value="Transparent" /> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="ToggleButton"> + <Grid Background="{TemplateBinding Background}"> + <ContentPresenter /> + </Grid> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <Style x:Key="emptyButton" TargetType="Button"> + <Setter Property="Background" Value="Transparent" /> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="Button"> + <Grid Background="{TemplateBinding Background}"> + <ContentPresenter /> + </Grid> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + + <!--Drag & Drop--> + <Style x:Key="draggableGrid" TargetType="Grid"> + <Setter Property="RenderTransform"> + <Setter.Value> + <ScaleTransform ScaleX="1" ScaleY="1"></ScaleTransform> + </Setter.Value> + </Setter> + <Setter Property="RenderTransformOrigin" Value="0.5,0.5"></Setter> + <Setter Property="Background" Value="Transparent"></Setter> + <Setter Property="dragAndDrop:DragAndDropService.Draggable" Value="True"></Setter> + <Setter Property="dragAndDrop:DragAndDropService.DraggingSurface" Value="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DraggingSurface}"></Setter> + </Style> + + <Style x:Key="droppableGrid" TargetType="Grid"> + <Setter Property="RenderTransform"> + <Setter.Value> + <ScaleTransform ScaleX="1" ScaleY="1"></ScaleTransform> + </Setter.Value> + </Setter> + <Setter Property="RenderTransformOrigin" Value="0.5,0.5"></Setter> + <Setter Property="Background" Value="Transparent"></Setter> + <Setter Property="dragAndDrop:DragAndDropService.Droppable" Value="True"></Setter> + <Setter Property="dragAndDrop:DragAndDropService.DraggingSurface" Value="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DraggingSurface}"></Setter> + <Style.Triggers> + <Trigger Property="dragAndDrop:DragAndDropService.IsDraggableOver" Value="True"> + <Setter Property="Opacity" Value="0.5"></Setter> + <Trigger.EnterActions> + <BeginStoryboard> + <Storyboard> + <DoubleAnimation To="0.95" Duration="00:00:0.2" Storyboard.TargetProperty="RenderTransform.ScaleX"></DoubleAnimation> + <DoubleAnimation To="0.95" Duration="00:00:0.2" Storyboard.TargetProperty="RenderTransform.ScaleY"></DoubleAnimation> + </Storyboard> + </BeginStoryboard> + </Trigger.EnterActions> + <Trigger.ExitActions> + <BeginStoryboard> + <Storyboard> + <DoubleAnimation To="1" Duration="00:00:0.2" Storyboard.TargetProperty="RenderTransform.ScaleX"></DoubleAnimation> + <DoubleAnimation To="1" Duration="00:00:0.2" Storyboard.TargetProperty="RenderTransform.ScaleY"></DoubleAnimation> + </Storyboard> + </BeginStoryboard> + </Trigger.ExitActions> + </Trigger> + </Style.Triggers> + </Style> + + <Style x:Key="draggableDroppableGrid" TargetType="Grid"> + <Setter Property="RenderTransform"> + <Setter.Value> + <ScaleTransform ScaleX="1" ScaleY="1"></ScaleTransform> + </Setter.Value> + </Setter> + <Setter Property="RenderTransformOrigin" Value="0.5,0.5"></Setter> + <Setter Property="Background" Value="Transparent"></Setter> + <Setter Property="dragAndDrop:DragAndDropService.Draggable" Value="True"></Setter> + <Setter Property="dragAndDrop:DragAndDropService.Droppable" Value="True"></Setter> + <Setter Property="dragAndDrop:DragAndDropService.DraggingSurface" Value="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DraggingSurface}"></Setter> + <Style.Triggers> + <Trigger Property="dragAndDrop:DragAndDropService.IsDraggableOver" Value="True"> + <Setter Property="Opacity" Value="0.5"></Setter> + <Trigger.EnterActions> + <BeginStoryboard> + <Storyboard> + <DoubleAnimation To="0.95" Duration="00:00:0.2" Storyboard.TargetProperty="RenderTransform.ScaleX"></DoubleAnimation> + <DoubleAnimation To="0.95" Duration="00:00:0.2" Storyboard.TargetProperty="RenderTransform.ScaleY"></DoubleAnimation> + </Storyboard> + </BeginStoryboard> + </Trigger.EnterActions> + <Trigger.ExitActions> + <BeginStoryboard> + <Storyboard> + <DoubleAnimation To="1" Duration="00:00:0.2" Storyboard.TargetProperty="RenderTransform.ScaleX"></DoubleAnimation> + <DoubleAnimation To="1" Duration="00:00:0.2" Storyboard.TargetProperty="RenderTransform.ScaleY"></DoubleAnimation> + </Storyboard> + </BeginStoryboard> + </Trigger.ExitActions> + </Trigger> + </Style.Triggers> + </Style> + <!--Drag & Drop--> + + <!--Extensions--> + </ResourceDictionary> </ResourceDictionary.MergedDictionaries> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioApplication/IModuleRequestListener.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioApplication/IModuleRequestListener.cs new file mode 100644 index 000000000..b950d7bcd --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioApplication/IModuleRequestListener.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.MachineStudio.Common.StudioApplication +{ + /// <summary> + /// Represents a type which will be notified when a new module request was made by <see cref="IStudioApplicationManager.RequestModule(string, object)"/> + /// </summary> + public interface IModuleRequestListener + { + /// <summary> + /// Called when the request has been made. + /// </summary> + /// <param name="module">The module instance.</param> + /// <param name="args">The arguments.</param> + void OnRequestModule(IStudioModule module, Object args); + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioApplication/IShutdownListener.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioApplication/IShutdownListener.cs new file mode 100644 index 000000000..1ca5a7df2 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioApplication/IShutdownListener.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.MachineStudio.Common.StudioApplication +{ + /// <summary> + /// Used to notify view models about application terminating. + /// </summary> + public interface IShutdownListener + { + /// <summary> + /// Called when the application is about to terminate. + /// </summary> + void OnShuttingDown(); + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioApplication/IShutdownRequestBlocker.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioApplication/IShutdownRequestBlocker.cs index a157bd598..4d5f968a4 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioApplication/IShutdownRequestBlocker.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioApplication/IShutdownRequestBlocker.cs @@ -6,8 +6,16 @@ using System.Threading.Tasks; namespace Tango.MachineStudio.Common.StudioApplication { + /// <summary> + /// Represents a component capable of receiving notification for when the Machine Studio shuts down. + /// The component can perform it's own shutdown operations, or cancel the current shutdown operation. + /// </summary> public interface IShutdownRequestBlocker { + /// <summary> + /// Called when the application is shutting down. + /// </summary> + /// <returns></returns> Task<bool> OnShutdownRequest(); } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioApplication/IStudioApplicationManager.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioApplication/IStudioApplicationManager.cs index 42f4f7b65..c67c34044 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioApplication/IStudioApplicationManager.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioApplication/IStudioApplicationManager.cs @@ -7,12 +7,46 @@ using Tango.Integration.Services; namespace Tango.MachineStudio.Common.StudioApplication { + /// <summary> + /// Represents the Machine Studio application manager. + /// </summary> public interface IStudioApplicationManager { - bool IsShuttingDown { get;} + /// <summary> + /// Occurs when the connected machine property has changed. + /// </summary> + event EventHandler<IExternalBridgeClient> ConnectedMachineChanged; + + /// <summary> + /// Gets a value indicating whether Machine Studio is shutting down. + /// </summary> + bool IsShuttingDown { get; } + + /// <summary> + /// Shutdown the application. + /// </summary> void ShutDown(); + + /// <summary> + /// Gets or sets the currently connected machine if any. + /// </summary> IExternalBridgeClient ConnectedMachine { get; set; } + + /// <summary> + /// Gets a value indicating whether the <see cref="ConnectedMachine"/> is valid. + /// </summary> bool IsMachineConnected { get; } - bool IsMachineConnectedViaTCP { get; } + + /// <summary> + /// Gets a value indicating whether the <see cref="ConnectedMachine"/> is valid and connected through TCP/IP. + /// </summary> + bool IsMachineConnectedViaTCP { get; } + + /// <summary> + /// Loads the specified module if permitted. + /// </summary> + /// <param name="moduleName">Name of the module.</param> + /// <param name="args">The arguments.</param> + void RequestModule(String moduleName, Object args); } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioModuleBase.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioModuleBase.cs new file mode 100644 index 000000000..5c594ab70 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioModuleBase.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Media.Imaging; +using Tango.Integration.Observables; + +namespace Tango.MachineStudio.Common +{ + /// <summary> + /// Represents a base class for studio modules. + /// </summary> + /// <seealso cref="Tango.MachineStudio.Common.IStudioModule" /> + public abstract class StudioModuleBase : IStudioModule + { + private bool _isInitialized; + private bool _isLoaded; + + /// <summary> + /// Occurs when the user has navigated into or out of this module. + /// </summary> + public event EventHandler<bool> IsLoadedChanged; + + /// <summary> + /// Gets the module name. + /// </summary> + public abstract string Name { get; } + + /// <summary> + /// Gets the module description. + /// </summary> + public abstract string Description { get; } + + /// <summary> + /// Gets the module cover image. + /// </summary> + public abstract BitmapSource Image { get; } + + /// <summary> + /// Gets the module entry point view. + /// </summary> + public abstract FrameworkElement MainView { get; } + + /// <summary> + /// Gets the permission required to see and load this module. + /// </summary> + public abstract Permissions Permission { get; } + + /// <summary> + /// Gets a value indicating whether this module has been initialized. + /// </summary> + public bool IsInitialized + { + get + { + return _isInitialized; + } + private set + { + _isInitialized = value; + } + } + + /// <summary> + /// Sets a value indicating whether this module is loaded. + /// </summary> + public bool IsLoaded + { + get + { + return _isLoaded; + } + set + { + _isLoaded = value; + IsLoadedChanged?.Invoke(this, value); + } + } + + /// <summary> + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// </summary> + public abstract void Dispose(); + + /// <summary> + /// Perform any operations required to initialize this module. + /// </summary> + public void Initialize() + { + OnInitialized(); + IsInitialized = true; + } + + /// <summary> + /// Called when machine studio initializes this module. + /// </summary> + protected virtual void OnInitialized() + { + + } + + /// <summary> + /// Raises the <see cref="IsLoadedChanged"/> event. + /// </summary> + /// <param name="loaded">if set to <c>true</c> the module is loaded.</param> + protected virtual void OnLoadedChanged(bool loaded) + { + + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj index 49fee31f1..cd4fc1aeb 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj @@ -71,13 +71,38 @@ <Reference Include="PresentationFramework" /> </ItemGroup> <ItemGroup> + <Compile Include="Controls\HiveColorPickerControl.xaml.cs"> + <DependentUpon>HiveColorPickerControl.xaml</DependentUpon> + </Compile> + <Compile Include="Controls\IRealTimeGraph.cs" /> + <Compile Include="Controls\RealTimeGraphMultiControl.xaml.cs"> + <DependentUpon>RealTimeGraphMultiControl.xaml</DependentUpon> + </Compile> + <Compile Include="Controls\RealTimeGraphControl.xaml.cs"> + <DependentUpon>RealTimeGraphControl.xaml</DependentUpon> + </Compile> + <Compile Include="Controls\TableGrid.cs" /> + <Compile Include="Converters\SecondsToGraphPointsConverter.cs" /> + <Compile Include="Diagnostics\DefaultDiagnosticsFrameProvider.cs" /> + <Compile Include="Diagnostics\IDiagnosticsFrameProvider.cs" /> + <Compile Include="Helpers\GraphsHelper.cs" /> + <Compile Include="Notifications\BarItem.cs" /> <Compile Include="Notifications\DialogViewVM.cs" /> + <Compile Include="StudioApplication\IModuleRequestListener.cs" /> + <Compile Include="StudioApplication\IShutdownListener.cs" /> <Compile Include="StudioApplication\IStudioApplicationManager.cs" /> <Compile Include="StudioApplication\IShutdownRequestBlocker.cs" /> <Compile Include="ExtensionMethods\IStudioMessageExtensions.cs" /> <Compile Include="Messages\IStudioMessage.cs" /> <Compile Include="Notifications\TaskItem.cs" /> + <Compile Include="StudioModuleBase.cs" /> <Compile Include="ValidationRules\Required.cs" /> + <Compile Include="Video\DefaultVideoCaptureProvider.cs" /> + <Compile Include="Video\IVideoCaptureProvider.cs" /> + <Page Include="Controls\HiveColorPickerControl.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> <Page Include="Controls\MdiContainerControl.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> @@ -91,12 +116,23 @@ <DependentUpon>MdiContainerControl.xaml</DependentUpon> </Compile> <Compile Include="Converters\PointToMarginConverter.cs" /> - <Compile Include="ExtensionMethods\UserExtensions.cs" /> <Compile Include="IStudioModule.cs" /> <Compile Include="Modules\IStudioModuleLoader.cs" /> <Compile Include="Navigation\INavigationManager.cs" /> <Compile Include="Navigation\NavigationView.cs" /> <Compile Include="Notifications\INotificationProvider.cs" /> + <Page Include="Controls\RealTimeGraphMultiControl.xaml"> + <Generator>MSBuild:Compile</Generator> + <SubType>Designer</SubType> + </Page> + <Page Include="Controls\RealTimeGraphControl.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="Resources\GradientOffsetSlider.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> <Page Include="Resources\MaterialDesign.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> @@ -121,6 +157,7 @@ <LastGenOutput>Resources.Designer.cs</LastGenOutput> </EmbeddedResource> <None Include="app.config" /> + <Resource Include="Fonts\digital-7.ttf" /> <None Include="packages.config" /> <None Include="Properties\Settings.settings"> <Generator>SettingsSingleFileGenerator</Generator> @@ -128,30 +165,58 @@ </None> </ItemGroup> <ItemGroup> + <ProjectReference Include="..\..\SideChains\RealTimeGraphEx\RealTimeGraphEx.csproj"> + <Project>{b9ae25d6-be35-492f-9079-21a7f3e6f7cc}</Project> + <Name>RealTimeGraphEx</Name> + </ProjectReference> <ProjectReference Include="..\..\SideChains\Tango.AutoComplete\Tango.AutoComplete.csproj"> <Project>{bb2abb74-ba58-4812-83aa-ec8171f42df4}</Project> <Name>Tango.AutoComplete</Name> </ProjectReference> + <ProjectReference Include="..\..\Tango.ColorPicker\Tango.ColorPicker.csproj"> + <Project>{a2f5af44-29ff-45d6-9d25-ecda5cce88b5}</Project> + <Name>Tango.ColorPicker</Name> + </ProjectReference> <ProjectReference Include="..\..\Tango.Core\Tango.Core.csproj"> <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project> <Name>Tango.Core</Name> </ProjectReference> - <ProjectReference Include="..\..\Tango.DAL.Observables\Tango.DAL.Observables.csproj"> - <Project>{0ecd6da8-7aa6-48d9-8b65-279d176ad9af}</Project> - <Name>Tango.DAL.Observables</Name> - </ProjectReference> <ProjectReference Include="..\..\Tango.DAL.Remote\Tango.DAL.Remote.csproj"> <Project>{38197109-8610-4d3f-92b9-16d48df94d7c}</Project> <Name>Tango.DAL.Remote</Name> </ProjectReference> + <ProjectReference Include="..\..\Tango.DragAndDrop\Tango.DragAndDrop.csproj"> + <Project>{b112d89a-a106-41ae-a0c1-4abc84c477f5}</Project> + <Name>Tango.DragAndDrop</Name> + </ProjectReference> + <ProjectReference Include="..\..\Tango.Editors\Tango.Editors.csproj"> + <Project>{de2f2b86-025b-4f26-83a4-38bd48224ed5}</Project> + <Name>Tango.Editors</Name> + </ProjectReference> <ProjectReference Include="..\..\Tango.Integration\Tango.Integration.csproj"> <Project>{4206ac58-3b57-4699-8835-90bf6db01a61}</Project> <Name>Tango.Integration</Name> </ProjectReference> + <ProjectReference Include="..\..\Tango.PMR\Tango.PMR.csproj"> + <Project>{e4927038-348d-4295-aaf4-861c58cb3943}</Project> + <Name>Tango.PMR</Name> + </ProjectReference> + <ProjectReference Include="..\..\Tango.Settings\Tango.Settings.csproj"> + <Project>{d8f1ad85-526a-4f50-b6dc-d437af63d8d8}</Project> + <Name>Tango.Settings</Name> + </ProjectReference> <ProjectReference Include="..\..\Tango.SharedUI\Tango.SharedUI.csproj"> <Project>{8491d07b-c1f6-4b62-a412-41b9fd2d6538}</Project> <Name>Tango.SharedUI</Name> </ProjectReference> + <ProjectReference Include="..\..\Tango.Transport\Tango.Transport.csproj"> + <Project>{74e700b0-1156-4126-be40-ee450d3c3026}</Project> + <Name>Tango.Transport</Name> + </ProjectReference> + <ProjectReference Include="..\..\Tango.Video\Tango.Video.csproj"> + <Project>{9652f972-2bd1-4283-99cb-fc6240434c17}</Project> + <Name>Tango.Video</Name> + </ProjectReference> </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> </Project>
\ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/ValidationRules/Required.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/ValidationRules/Required.cs index 84f274965..aac00fdf1 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/ValidationRules/Required.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/ValidationRules/Required.cs @@ -8,8 +8,20 @@ using System.Windows.Controls; namespace Tango.MachineStudio.Common.ValidationRules { + /// <summary> + /// Represents a required field validation rule. + /// </summary> + /// <seealso cref="System.Windows.Controls.ValidationRule" /> public class Required : ValidationRule { + /// <summary> + /// When overridden in a derived class, performs validation checks on a value. + /// </summary> + /// <param name="value">The value from the binding target to check.</param> + /// <param name="cultureInfo">The culture to use in this rule.</param> + /// <returns> + /// A <see cref="T:System.Windows.Controls.ValidationResult" /> object. + /// </returns> public override ValidationResult Validate(object value, CultureInfo cultureInfo) { return new ValidationResult(!String.IsNullOrWhiteSpace(value.ToStringSafe()), "Required"); diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Video/DefaultVideoCaptureProvider.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Video/DefaultVideoCaptureProvider.cs new file mode 100644 index 000000000..3aa9d4c88 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Video/DefaultVideoCaptureProvider.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Video.DirectCapture; + +namespace Tango.MachineStudio.Common.Video +{ + /// <summary> + /// Represents the default implementation of <see cref="IVideoCaptureProvider"/>. + /// </summary> + /// <seealso cref="Tango.MachineStudio.Common.Video.IVideoCaptureProvider" /> + public class DefaultVideoCaptureProvider : IVideoCaptureProvider + { + /// <summary> + /// Gets the available capture devices. + /// </summary> + public ObservableCollection<CaptureDevice> AvailableCaptureDevices { get; private set; } + + /// <summary> + /// Initializes a new instance of the <see cref="DefaultVideoCaptureProvider"/> class. + /// </summary> + public DefaultVideoCaptureProvider() + { + AvailableCaptureDevices = new ObservableCollection<CaptureDevice>(); + + var availableDevices = CaptureDevice.GetAvailableCaptureDevices(); + + for (int i = 0; i < 3; i++) + { + if (i > availableDevices.Count - 1) + { + AvailableCaptureDevices.Add(new CaptureDevice() { Device = null }); + } + else + { + AvailableCaptureDevices.Add(new CaptureDevice() { Device = availableDevices[i] }); + } + } + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Video/IVideoCaptureProvider.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Video/IVideoCaptureProvider.cs new file mode 100644 index 000000000..cd797dce2 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Video/IVideoCaptureProvider.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Video.DirectCapture; + +namespace Tango.MachineStudio.Common.Video +{ + /// <summary> + /// Represents a video capturing device provider. + /// </summary> + public interface IVideoCaptureProvider + { + /// <summary> + /// Gets the available capture devices. + /// </summary> + ObservableCollection<CaptureDevice> AvailableCaptureDevices { get; } + } +} |
