aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls
diff options
context:
space:
mode:
authorAvi Levkovich <avi@twine-s.com>2018-02-20 16:45:00 +0200
committerAvi Levkovich <avi@twine-s.com>2018-02-20 16:45:00 +0200
commit6c208c90bc45aff4a7fa214356a42fe7757c5e6f (patch)
tree0d77bc6a0ecfbb53cf42c5462ee19212197ee1bd /Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls
parentb0823127f152fe97a6e8fce29e427c7f3db9cf5a (diff)
parent1a573aaa346ec4b8bd58a0e35ab9df571a09b855 (diff)
downloadTango-6c208c90bc45aff4a7fa214356a42fe7757c5e6f.tar.gz
Tango-6c208c90bc45aff4a7fa214356a42fe7757c5e6f.zip
MERGE
Diffstat (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls')
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/HiveColorPickerControl.xaml23
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/HiveColorPickerControl.xaml.cs102
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/IRealTimeGraph.cs53
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/MdiChild.cs24
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/MdiContainerControl.xaml.cs6
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphControl.xaml90
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphControl.xaml.cs179
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphMultiControl.xaml95
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphMultiControl.xaml.cs162
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/TableGrid.cs58
10 files changed, 790 insertions, 2 deletions
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;
+ }
+ }
+ }
+}