aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio
diff options
context:
space:
mode:
authorVictoria Plitt <Victoria.Plitt@twine-s.com>2020-02-16 14:48:33 +0200
committerVictoria Plitt <Victoria.Plitt@twine-s.com>2020-02-16 14:48:33 +0200
commite2fbc8e6047fef09681b994efe2ca1043d25ac9d (patch)
treed51c5787ec50711361d557bb060c976a5b278dcb /Software/Visual_Studio
parent1ae720e9052b2419200c113ad1fa42550382e6c7 (diff)
downloadTango-e2fbc8e6047fef09681b994efe2ca1043d25ac9d.tar.gz
Tango-e2fbc8e6047fef09681b994efe2ca1043d25ac9d.zip
Implement Job Runs View. Create 2 views in Statistics. Implements Part of JobRunsView.
Related Work Items: #2509
Diffstat (limited to 'Software/Visual_Studio')
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/DateIsInListToBooleanConverter.cs29
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/StringToBoolYesNoNullConverter.cs37
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/JobRunModel.cs46
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/JobRunStatisticsModel.cs45
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Tango.MachineStudio.Statistics.csproj19
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/ChartsViewVM.cs362
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/JobRunsViewVM.cs209
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/MainViewVM.cs339
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/ChartsView.xaml110
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/ChartsView.xaml.cs35
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/JobRunsView.xaml239
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/JobRunsView.xaml.cs44
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/MainView.xaml114
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/MainView.xaml.cs6
-rw-r--r--Software/Visual_Studio/Tango.SharedUI/Controls/MultiSelectComboBox.cs180
-rw-r--r--Software/Visual_Studio/Tango.SharedUI/Tango.SharedUI.csproj7
-rw-r--r--Software/Visual_Studio/Tango.SharedUI/Themes/Generic.xaml127
-rw-r--r--Software/Visual_Studio/Utilities/Tango.UITests/MainWindow.xaml35
-rw-r--r--Software/Visual_Studio/Utilities/Tango.UITests/MainWindow.xaml.cs111
19 files changed, 1513 insertions, 581 deletions
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/DateIsInListToBooleanConverter.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/DateIsInListToBooleanConverter.cs
new file mode 100644
index 000000000..74e0c61d8
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/DateIsInListToBooleanConverter.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+
+namespace Tango.MachineStudio.Statistics.Converters
+{
+ public class DateIsInListToBooleanConverter : IMultiValueConverter
+ {
+ public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (values.Length < 2 || !(values[0] is DateTime) || !(values[1] is IEnumerable<DateTime>))
+ return false;
+
+ var date = (DateTime)values[0];
+ var dateList = (IEnumerable<DateTime>)values[1];
+
+ return dateList.ToList().Exists(x => x.ToLocalTime().ToShortDateString() == date.ToLocalTime().ToShortDateString());
+ }
+
+ public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/StringToBoolYesNoNullConverter.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/StringToBoolYesNoNullConverter.cs
new file mode 100644
index 000000000..f7633a7d0
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/StringToBoolYesNoNullConverter.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Controls;
+using System.Windows.Data;
+
+namespace Tango.MachineStudio.Statistics.Converters
+{
+ public class StringToBoolYesNoNullConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if(value is bool)
+ {
+ return (bool)value ? "Yes" : "No";
+ }
+ return "Null";
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ //throw new NotImplementedException();
+ if (value is ComboBoxItem)
+ {
+ string str_val = ((ComboBoxItem)value).Content.ToString();
+ if (str_val.ToUpper() == "NO")
+ return false;
+ if (str_val.ToUpper() == "YES")
+ return true;
+ }
+ return null;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/JobRunModel.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/JobRunModel.cs
index 8e5642e3d..e269f761f 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/JobRunModel.cs
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/JobRunModel.cs
@@ -1,45 +1,37 @@
-
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
-using Tango.BL;
using Tango.BL.Entities;
-using Tango.Core.ExtensionMethods;
namespace Tango.MachineStudio.Statistics.Models
{
- public class JobRunModel : JobRun
+ public class JobRunModel
{
- private static Dictionary<String, Machine> _machines = new Dictionary<string, Machine>();
+ public JobRun JobRun { get; set; }
- public JobRunModel()
- {
+ public Machine Machine { get; set; }
- }
+ public User User { get; set; }
- public JobRunModel(JobRun run)
- {
- run.MapPropertiesTo(this, MappingFlags.NoReferenceTypes);
- }
+ public TimeSpan? UploadDuration { get; set; }
+
+ public TimeSpan? HeatingDuration { get; set; }
- public Task LoadMachine(ObservablesContext context)
+
+
+ public void Init()
{
- return Task.Factory.StartNew(() =>
+ if (JobRun.HeatingStartDate != null)
{
- if (!_machines.ContainsKey(MachineGuid))
- {
- Machine = context.Machines.SingleOrDefault(x => x.Guid == MachineGuid);
- _machines.Add(MachineGuid, Machine);
- }
- else
- {
- Machine = _machines[MachineGuid];
- }
- });
- }
+ UploadDuration = JobRun.HeatingStartDate - JobRun.StartDate;
+ }
- public Machine Machine { get; set; }
+ if (JobRun.ActualStartDate != null && JobRun.HeatingStartDate != null)
+ {
+ HeatingDuration = JobRun.ActualStartDate - JobRun.HeatingStartDate;
+ }
+ }
}
}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/JobRunStatisticsModel.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/JobRunStatisticsModel.cs
new file mode 100644
index 000000000..98b719cae
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Models/JobRunStatisticsModel.cs
@@ -0,0 +1,45 @@
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL;
+using Tango.BL.Entities;
+using Tango.Core.ExtensionMethods;
+
+namespace Tango.MachineStudio.Statistics.Models
+{
+ public class JobRunStatisticsModel : JobRun
+ {
+ private static Dictionary<String, Machine> _machines = new Dictionary<string, Machine>();
+
+ public JobRunStatisticsModel()
+ {
+
+ }
+
+ public JobRunStatisticsModel(JobRun run)
+ {
+ run.MapPropertiesTo(this, MappingFlags.NoReferenceTypes);
+ }
+
+ public Task LoadMachine(ObservablesContext context)
+ {
+ return Task.Factory.StartNew(() =>
+ {
+ if (!_machines.ContainsKey(MachineGuid))
+ {
+ Machine = context.Machines.SingleOrDefault(x => x.Guid == MachineGuid);
+ _machines.Add(MachineGuid, Machine);
+ }
+ else
+ {
+ Machine = _machines[MachineGuid];
+ }
+ });
+ }
+
+ public Machine Machine { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Tango.MachineStudio.Statistics.csproj b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Tango.MachineStudio.Statistics.csproj
index 36c371165..4b3535f83 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Tango.MachineStudio.Statistics.csproj
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Tango.MachineStudio.Statistics.csproj
@@ -73,14 +73,25 @@
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="Converters\StringToBoolYesNoNullConverter.cs" />
+ <Compile Include="Converters\DateIsInListToBooleanConverter.cs" />
<Compile Include="Models\JobRunModel.cs" />
+ <Compile Include="Models\JobRunStatisticsModel.cs" />
<Compile Include="Models\LabeledSeriesCollection.cs" />
<Compile Include="Tooltips\PieChartTooltipControl.xaml.cs">
<DependentUpon>PieChartTooltipControl.xaml</DependentUpon>
</Compile>
<Compile Include="StatisticsModule.cs" />
<Compile Include="ViewModelLocator.cs" />
+ <Compile Include="ViewModels\ChartsViewVM.cs" />
+ <Compile Include="ViewModels\JobRunsViewVM.cs" />
<Compile Include="ViewModels\MainViewVM.cs" />
+ <Compile Include="Views\ChartsView.xaml.cs">
+ <DependentUpon>ChartsView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Views\JobRunsView.xaml.cs">
+ <DependentUpon>JobRunsView.xaml</DependentUpon>
+ </Compile>
<Compile Include="Views\MainView.xaml.cs">
<DependentUpon>MainView.xaml</DependentUpon>
</Compile>
@@ -95,6 +106,14 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
+ <Page Include="Views\ChartsView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="Views\JobRunsView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
<Page Include="Views\MainView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/ChartsViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/ChartsViewVM.cs
new file mode 100644
index 000000000..b06261306
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/ChartsViewVM.cs
@@ -0,0 +1,362 @@
+using LiveCharts;
+using LiveCharts.Wpf;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Media;
+using Tango.BL.Enumerations;
+using Tango.MachineStudio.Common;
+using Tango.MachineStudio.Statistics.Models;
+using Tango.BL.Entities;
+using Tango.SharedUI;
+using Tango.BL;
+using Tango.MachineStudio.Common.Notifications;
+using System.Threading.Tasks;
+
+namespace Tango.MachineStudio.Statistics.ViewModels
+{
+ public class ChartsViewVM : ViewModel
+ {
+ private INotificationProvider _notification;
+ private ObservablesContext _context;
+ private List<JobRunStatisticsModel> _job_runs;
+ private bool _loaded;
+
+ #region Properties
+ private LabeledSeriesCollection _timelineJobStatusSeries;
+ public LabeledSeriesCollection TimelineJobStatusSeries
+ {
+ get { return _timelineJobStatusSeries; }
+ set { _timelineJobStatusSeries = value; RaisePropertyChangedAuto(); }
+ }
+
+ private LabeledSeriesCollection _pieJobFailedReasons;
+ public LabeledSeriesCollection PieJobFailedReasons
+ {
+ get { return _pieJobFailedReasons; }
+ set { _pieJobFailedReasons = value; RaisePropertyChangedAuto(); }
+ }
+
+ private LabeledSeriesCollection _printPerWeekSeries;
+ public LabeledSeriesCollection PrintPerWeekSeries
+ {
+ get { return _printPerWeekSeries; }
+ set { _printPerWeekSeries = value; RaisePropertyChangedAuto(); }
+ }
+
+ private DateTime _startDate;
+ public DateTime StartDate
+ {
+ get { return _startDate; }
+ set { _startDate = value; RaisePropertyChangedAuto(); OnDateRangeChanged(); }
+ }
+
+ private DateTime _endDate;
+ public DateTime EndDate
+ {
+ get { return _endDate; }
+ set { _endDate = value; RaisePropertyChangedAuto(); OnDateRangeChanged(); }
+ }
+
+ private DateTime _minDate;
+ public DateTime MinDate
+ {
+ get { return _minDate; }
+ set { _minDate = value; RaisePropertyChangedAuto(); }
+ }
+
+ private DateTime _maxDate;
+ public DateTime MaxDate
+ {
+ get { return _maxDate; }
+ set { _maxDate = value; RaisePropertyChangedAuto(); }
+ }
+ #endregion
+
+ public ChartsViewVM(INotificationProvider notificationProvider)
+ {
+ _notification = notificationProvider;
+ StartDate = DateTime.Now.AddMonths(-1);
+ EndDate = DateTime.Now;
+ }
+
+ #region Generate Charts
+
+ public async void Init()
+ {
+ using (_notification.PushTaskItem("Loading statistics..."))
+ {
+ IsFree = false;
+
+ await Task.Factory.StartNew(() =>
+ {
+ _context = ObservablesContext.CreateDefault();
+ _job_runs = _context.JobRuns.OrderBy(x => x.StartDate).ToList().Select(x => new JobRunStatisticsModel(x)).ToList();
+ foreach (var run in _job_runs)
+ {
+ run.LoadMachine(_context).GetAwaiter().GetResult();
+ }
+ });
+
+ if (_job_runs.Count > 0)
+ {
+ MinDate = _job_runs.Min(x => x.StartDate);
+ MaxDate = _job_runs.Max(x => x.StartDate);
+ }
+
+ InvokeUIOnIdle(() =>
+ {
+ if (_loaded)
+ {
+ OnDateRangeChanged();
+ }
+ });
+
+ _loaded = true;
+ IsFree = true;
+ }
+ }
+
+ private List<JobRunStatisticsModel> GetJobRunsByDateRange(DateTime startDate, DateTime endTime, JobRunStatus? status = null)
+ {
+ return _job_runs.Where(x => x.StartDate.ToLocalTime() >= startDate && x.StartDate.ToLocalTime() <= endTime && (status == null || x.JobRunStatus == status)).ToList();
+ }
+
+ private List<JobRunStatisticsModel> GetJobRunsByDate(DateTime date, JobRunStatus? status = null)
+ {
+ return _job_runs.Where(x => x.StartDate.ToLocalTime().Date == date.Date && (status == null || x.JobRunStatus == status)).ToList();
+ }
+
+ private IEnumerable<DateTime> CreateDates(DateTime start, DateTime end)
+ {
+ for (DateTime date = start.Date; date.Date <= end.Date; date = date.AddDays(1))
+ {
+ yield return date;
+ }
+ }
+
+ private void GenerateTimelineJobStatusChart()
+ {
+ TimelineJobStatusSeries = new LabeledSeriesCollection()
+ {
+ Title = "Job Runs Status",
+ ChartTitle = "Number Of Runs",
+ LabelsTitle = "Date",
+ SeriesColors = new List<Color>()
+ {
+ Colors.Green,
+ Colors.Orange,
+ Colors.Red,
+ },
+ };
+
+ Series completed_job_runs = new ColumnSeries()
+ {
+ Title = "Completed",
+ Values = new ChartValues<int>(),
+ Fill = Brushes.Green,
+ MinWidth = 1,
+
+ };
+ Series aborted_job_runs = new ColumnSeries()
+ {
+ Title = "Aborted",
+ Values = new ChartValues<int>(),
+ Fill = Brushes.Orange,
+ MinWidth = 1,
+ };
+ Series failed_job_runs = new ColumnSeries()
+ {
+ Title = "Failed",
+ Values = new ChartValues<int>(),
+ Fill = Brushes.Red,
+ MinWidth = 1,
+ };
+
+ if (EndDate - StartDate > TimeSpan.FromDays(40))
+ {
+ completed_job_runs = new LineSeries()
+ {
+ Title = "Completed",
+ Values = new ChartValues<int>(),
+ Fill = new SolidColorBrush(Colors.Green) { Opacity = 0.5 },
+ MinWidth = 1,
+ PointGeometry = null,
+ StrokeThickness = 0,
+
+ };
+ aborted_job_runs = new LineSeries()
+ {
+ Title = "Aborted",
+ Values = new ChartValues<int>(),
+ Fill = new SolidColorBrush(Colors.Orange) { Opacity = 0.5 },
+ MinWidth = 1,
+ PointGeometry = null,
+ StrokeThickness = 0,
+ };
+ failed_job_runs = new LineSeries()
+ {
+ Title = "Failed",
+ Values = new ChartValues<int>(),
+ Fill = new SolidColorBrush(Colors.Red) { Opacity = 0.5 },
+ MinWidth = 1,
+ PointGeometry = null,
+ StrokeThickness = 0,
+ };
+ }
+
+ foreach (var date in CreateDates(StartDate, EndDate))
+ {
+ completed_job_runs.Values.Add(GetJobRunsByDate(date, JobRunStatus.Completed).Count());
+ aborted_job_runs.Values.Add(GetJobRunsByDate(date, JobRunStatus.Aborted).Count());
+ failed_job_runs.Values.Add(GetJobRunsByDate(date, JobRunStatus.Failed).Count());
+
+ TimelineJobStatusSeries.Labels.Add(date.ToShortDateString());
+ }
+
+
+
+ TimelineJobStatusSeries.SeriesCollection.Add(failed_job_runs);
+ TimelineJobStatusSeries.SeriesCollection.Add(aborted_job_runs);
+ TimelineJobStatusSeries.SeriesCollection.Add(completed_job_runs);
+ }
+
+ private void GeneratePieFailedReasonsChart()
+ {
+ var groups = GetJobRunsByDateRange(StartDate, EndDate, JobRunStatus.Failed).GroupBy(x => x.FailedMessage).OrderBy(x => x.Count());
+
+ List<Color> colors = new List<Color>();
+
+ int max = groups.Count() > 0 ? groups.Max(x => x.Count()) : 0;
+
+ for (int i = 0; i < groups.Count(); i++)
+ {
+ int count = groups.ElementAt(i).Count();
+ double alpha = Math.Max(((double)(count) / max * 200), 20);
+ colors.Add(Color.FromArgb((byte)alpha, 200, 0, 0));
+ }
+
+ PieJobFailedReasons = new LabeledSeriesCollection()
+ {
+ Title = "Job Failure Reasons",
+ SeriesColors = colors,
+ };
+
+ int index = 0;
+
+ foreach (var group in groups)
+ {
+ int count = group.Count();
+
+ var series = new PieSeries()
+ {
+ Title = group.First().FailedMessage,
+ Values = new ChartValues<int>() { count },
+ Fill = new SolidColorBrush(colors[index++]),
+ DataLabels = true,
+ ToolTip = group.First().FailedMessage,
+ };
+
+ PieJobFailedReasons.SeriesCollection.Add(series);
+ }
+ }
+
+ private void GeneratePrintPerWeekChart()
+ {
+ List<JobRunStatisticsModel> range_job_runs = GetJobRunsByDateRange(StartDate, EndDate);
+
+ Dictionary<Machine, List<double>> weeks_print_avg = new Dictionary<Machine, List<double>>();
+
+ //Init machines weeks averages dictionary.
+ foreach (var machine in range_job_runs.Select(x => x.Machine).OrderBy(x => x.Name).DistinctBy(x => x.Guid))
+ {
+ weeks_print_avg[machine] = new List<double>();
+ }
+
+ //Create all available dates
+ List<DateTime> all_dates = range_job_runs.Select(x => x.StartDate).ToList();
+
+ //get first Sunday.
+ DateTime current_sunday = all_dates.FirstOrDefault(x => x.DayOfWeek == DayOfWeek.Sunday);
+
+ if (current_sunday != null && all_dates.Count > 0)
+ {
+ //Iterate over each week starting from the earliest Sunday.
+ while (current_sunday <= all_dates.Last())
+ {
+ var week_job_runs = range_job_runs.Where(x => x.EndPosition > 10 && x.StartDate >= current_sunday && x.StartDate <= current_sunday.AddDays(7)).ToList();
+
+ foreach (var machine_job_runs in week_job_runs.GroupBy(x => x.Machine))
+ {
+ weeks_print_avg[machine_job_runs.Key].Add(machine_job_runs.Select(x => x.EndPosition).Average());
+ }
+
+ current_sunday = current_sunday.AddDays(8);
+ }
+ }
+
+ Dictionary<Machine, double> week_print_avg = new Dictionary<Machine, double>();
+
+ //Init machines week average dictionary.
+ foreach (var machine in weeks_print_avg)
+ {
+ if (machine.Value.Count > 0)
+ {
+ week_print_avg[machine.Key] = machine.Value.Average();
+ }
+ }
+
+ //Init chart series
+ PrintPerWeekSeries = new LabeledSeriesCollection()
+ {
+ Title = "Average Printed Thread Per Week (m)",
+ ChartTitle = "Average Print Per Week (m)",
+ LabelsTitle = "Date",
+ SeriesColors = new List<Color>()
+ {
+
+ },
+ };
+
+ //Init series colors intensity by number of prints.
+ double max = week_print_avg.Count > 0 ? week_print_avg.Max(x => x.Value) : 0;
+ foreach (var machine in week_print_avg)
+ {
+ double a = (machine.Value / max);
+ PrintPerWeekSeries.SeriesColors.Add(Color.FromArgb((byte)(255d * (machine.Value / max)), 0, 200, 0));
+ }
+
+ //Init columns.
+ int index = 0;
+
+ foreach (var machine in week_print_avg)
+ {
+ var series = new ColumnSeries()
+ {
+ Title = machine.Key.Name,
+ Values = new ChartValues<int>() { (int)machine.Value },
+ Fill = new SolidColorBrush(PrintPerWeekSeries.SeriesColors[index++]),
+ DataLabels = true,
+ ToolTip = machine.Key.SerialNumber,
+ };
+
+ PrintPerWeekSeries.SeriesCollection.Add(series);
+ }
+ }
+
+ #endregion
+
+ #region Filter by Date
+ public void OnDateRangeChanged()
+ {
+ if (_job_runs != null && _job_runs.Count > 0)// && _loaded)
+ {
+ GenerateTimelineJobStatusChart();
+ GeneratePieFailedReasonsChart();
+ GeneratePrintPerWeekChart();
+ }
+ }
+ #endregion
+
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/JobRunsViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/JobRunsViewVM.cs
new file mode 100644
index 000000000..f03e7f67d
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/JobRunsViewVM.cs
@@ -0,0 +1,209 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Data.Entity;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL;
+using Tango.BL.Entities;
+using Tango.BL.Enumerations;
+using Tango.Core.Commands;
+using Tango.MachineStudio.Common;
+using Tango.MachineStudio.Common.Notifications;
+using Tango.MachineStudio.Statistics.Models;
+using Tango.SharedUI;
+using Tango.SharedUI.Components;
+
+namespace Tango.MachineStudio.Statistics.ViewModels
+{
+ public class JobRunsViewVM : ViewModel
+ {
+ private INotificationProvider _notification;
+ private List<Machine> _allMachines;
+ private List<User> _allUsers;
+
+ #region Properties
+
+ private List<JobRunModel> _jobRuns;
+ public List<JobRunModel> JobRuns
+ {
+ get { return _jobRuns; }
+ set
+ {
+ _jobRuns = value;
+ RaisePropertyChangedAuto();
+ }
+ }
+
+ private JobRunModel _selectedJobRun = null;
+ public JobRunModel SelectedJobRun
+ {
+ get { return _selectedJobRun; }
+ set
+ {
+ _selectedJobRun = value;
+ RaisePropertyChangedAuto();
+ }
+ }
+
+ private SelectedObjectCollection<Machine> _selectedMachines;
+ public SelectedObjectCollection<Machine> SelectedMachines
+ {
+ get { return _selectedMachines; }
+ set
+ {
+ _selectedMachines = value;
+ RaisePropertyChangedAuto();
+ }
+ }
+
+ private DateTime _startSelectedDate;
+ public DateTime StartSelectedDate
+ {
+ get { return _startSelectedDate; }
+ set { _startSelectedDate = value; RaisePropertyChangedAuto(); }
+ }
+
+ private DateTime _endSelectedDate;
+ public DateTime EndSelectedDate
+ {
+ get { return _endSelectedDate; }
+ set { _endSelectedDate = value; RaisePropertyChangedAuto(); }
+ }
+
+ protected Double _length;
+ public Double Length
+ {
+ get { return _length; }
+ set
+ {
+ _length = value;
+ RaisePropertyChangedAuto();
+ }
+ }
+
+ private JobSource _jobRunSource;
+
+ public JobSource JobRunSource
+ {
+ get { return _jobRunSource; }
+ set { _jobRunSource = value; RaisePropertyChangedAuto(); }
+ }
+
+ private JobRunStatus _jobRunStatus;
+
+ public JobRunStatus JobRunStatus
+ {
+ get { return _jobRunStatus; }
+ set { _jobRunStatus = value; RaisePropertyChangedAuto(); }
+ }
+
+ private bool? _isGradient;
+
+ public bool? IsGradient
+ {
+ get { return _isGradient; }
+ set {
+ _isGradient = value;
+ RaisePropertyChangedAuto(); }
+ }
+
+ private string _jobName;
+
+ public string JobName
+ {
+ get { return _jobName; }
+ set { _jobName = value; }
+ }
+
+
+ #endregion
+
+ public RelayCommand LoadJobRunsCommand { get; set; }
+
+ public JobRunsViewVM(INotificationProvider notificationProvider)
+ {
+ _notification = notificationProvider;
+ JobRuns = new List<JobRunModel>();
+ LoadJobRunsCommand = new RelayCommand( GetJobRuns);
+ }
+
+
+ public async void Init()
+ {
+ using (_notification.PushTaskItem("Loading job runs..."))
+ {
+ try
+ {
+ IsFree = false;
+
+ using (var db = ObservablesContext.CreateDefault())
+ {
+ _allMachines = await db.Machines.ToListAsync();
+ _allUsers = await db.Users.ToListAsync();
+ SelectedMachines = new SelectedObjectCollection<Machine>(_allMachines.ToObservableCollection(), new ObservableCollection<Machine>());
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error loading job runs.");
+ }
+ finally
+ {
+ IsFree = true;
+ }
+ }
+ }
+
+ private async void GetJobRuns()
+ {
+ await LoadJobRuns();
+ }
+
+ private async Task LoadJobRuns()
+ {
+ using (_notification.PushTaskItem("Loading job runs..."))
+ {
+ try
+ {
+ IsFree = false;
+
+ using (var db = ObservablesContext.CreateDefault())
+ {
+ DateTime startUtc = StartSelectedDate.ToUniversalTime();
+ TimeSpan offsetTime = (EndSelectedDate.Date == DateTime.Now.Date) ? DateTime.Now.TimeOfDay : new TimeSpan(23, 59, 59);
+ DateTime endUtc = EndSelectedDate.ToUniversalTime() + offsetTime;
+
+ var runs = await db.JobRuns.Select(x => new JobRunModel()
+ {
+ JobRun = x,
+ Machine = _allMachines.FirstOrDefault(y => y.Guid == x.MachineGuid),
+ User = _allUsers.SingleOrDefault(y => y.Guid == x.UserGuid),
+ }).ToListAsync();
+
+ // .Query(y => y.Where
+ //(x => JobName == null ||
+ //(x.JobName.ToString().ToLower().StartsWith(JobName)
+ //|| Length == null || (x.JobLength == Length)
+ //|| IsGradient == null || (x.IsGradient != null && x.IsGradient == IsGradient)
+ //|| ( x.JobRunSource == JobRunSource))))
+ //.BuildAsync();
+
+ runs.ForEach(x => x.Init());
+
+ JobRuns = runs;
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error loading job runs.");
+ }
+ finally
+ {
+ IsFree = true;
+ }
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/MainViewVM.cs
index dfbfe2648..4a75a41c8 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/MainViewVM.cs
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/MainViewVM.cs
@@ -19,349 +19,38 @@ namespace Tango.MachineStudio.Statistics.ViewModels
{
public class MainViewVM : StudioViewModel
{
- private ObservablesContext _context;
- private List<JobRunModel> _job_runs;
- private bool rendered;
private INotificationProvider _notification;
- private bool _loaded;
- private LabeledSeriesCollection _timelineJobStatusSeries;
- public LabeledSeriesCollection TimelineJobStatusSeries
+ private ChartsViewVM _chartsViewVM;
+ public ChartsViewVM ChartsViewVM
{
- get { return _timelineJobStatusSeries; }
- set { _timelineJobStatusSeries = value; RaisePropertyChangedAuto(); }
+ get { return _chartsViewVM; }
+ set { _chartsViewVM = value; RaisePropertyChangedAuto(); }
}
- private LabeledSeriesCollection _pieJobFailedReasons;
- public LabeledSeriesCollection PieJobFailedReasons
+ private JobRunsViewVM _jobRunsViewVM;
+ public JobRunsViewVM JobRunsViewVM
{
- get { return _pieJobFailedReasons; }
- set { _pieJobFailedReasons = value; RaisePropertyChangedAuto(); }
+ get { return _jobRunsViewVM; }
+ set { _jobRunsViewVM = value; RaisePropertyChangedAuto(); }
}
-
- private LabeledSeriesCollection _printPerWeekSeries;
- public LabeledSeriesCollection PrintPerWeekSeries
- {
- get { return _printPerWeekSeries; }
- set { _printPerWeekSeries = value; RaisePropertyChangedAuto(); }
- }
-
- private DateTime _startDate;
- public DateTime StartDate
- {
- get { return _startDate; }
- set { _startDate = value; RaisePropertyChangedAuto(); OnDateRangeChanged(); }
- }
-
- private DateTime _endDate;
- public DateTime EndDate
- {
- get { return _endDate; }
- set { _endDate = value; RaisePropertyChangedAuto(); OnDateRangeChanged(); }
- }
-
- private DateTime _minDate;
- public DateTime MinDate
- {
- get { return _minDate; }
- set { _minDate = value; RaisePropertyChangedAuto(); }
- }
-
- private DateTime _maxDate;
- public DateTime MaxDate
- {
- get { return _maxDate; }
- set { _maxDate = value; RaisePropertyChangedAuto(); }
- }
-
+
public MainViewVM(INotificationProvider notificationProvider)
{
_notification = notificationProvider;
-
- StartDate = DateTime.Now.AddMonths(-1);
- EndDate = DateTime.Now;
+ ChartsViewVM = new ChartsViewVM(_notification);
+ JobRunsViewVM = new JobRunsViewVM(_notification);
}
public override void OnApplicationReady()
{
-
- }
-
- private List<JobRunModel> GetJobRunsByDateRange(DateTime startDate, DateTime endTime, JobRunStatus? status = null)
- {
- return _job_runs.Where(x => x.StartDate.ToLocalTime() >= startDate && x.StartDate.ToLocalTime() <= endTime && (status == null || x.JobRunStatus == status)).ToList();
- }
-
- private List<JobRunModel> GetJobRunsByDate(DateTime date, JobRunStatus? status = null)
- {
- return _job_runs.Where(x => x.StartDate.ToLocalTime().Date == date.Date && (status == null || x.JobRunStatus == status)).ToList();
- }
-
- private IEnumerable<DateTime> CreateDates(DateTime start, DateTime end)
- {
- for (DateTime date = start.Date; date.Date <= end.Date; date = date.AddDays(1))
- {
- yield return date;
- }
+ JobRunsViewVM.Init();
}
- public override async void OnNavigatedTo()
+ public override void OnNavigatedTo()
{
base.OnNavigatedTo();
-
- if (rendered) return;
-
- rendered = true;
-
-
- using (_notification.PushTaskItem("Loading statistics..."))
- {
- IsFree = false;
-
- await Task.Factory.StartNew(() =>
- {
- _context = ObservablesContext.CreateDefault();
- _job_runs = _context.JobRuns.OrderBy(x => x.StartDate).ToList().Select(x => new JobRunModel(x)).ToList();
- foreach (var run in _job_runs)
- {
- run.LoadMachine(_context).GetAwaiter().GetResult();
- }
- });
-
- if (_job_runs.Count > 0)
- {
- MinDate = _job_runs.Min(x => x.StartDate);
- MaxDate = _job_runs.Max(x => x.StartDate);
- }
-
- InvokeUIOnIdle(() =>
- {
- OnDateRangeChanged();
- });
-
- _loaded = true;
-
- IsFree = true;
- }
- }
-
- private void OnDateRangeChanged()
- {
- if (_job_runs != null && _job_runs.Count > 0 && _loaded)
- {
- GenerateTimelineJobStatusChart();
- GeneratePieFailedReasonsChart();
- GeneratePrintPerWeekChart();
- }
- }
-
- private void GenerateTimelineJobStatusChart()
- {
- TimelineJobStatusSeries = new LabeledSeriesCollection()
- {
- Title = "Job Runs Status",
- ChartTitle = "Number Of Runs",
- LabelsTitle = "Date",
- SeriesColors = new List<Color>()
- {
- Colors.Green,
- Colors.Orange,
- Colors.Red,
- },
- };
-
- Series completed_job_runs = new ColumnSeries()
- {
- Title = "Completed",
- Values = new ChartValues<int>(),
- Fill = Brushes.Green,
- MinWidth = 1,
-
- };
- Series aborted_job_runs = new ColumnSeries()
- {
- Title = "Aborted",
- Values = new ChartValues<int>(),
- Fill = Brushes.Orange,
- MinWidth = 1,
- };
- Series failed_job_runs = new ColumnSeries()
- {
- Title = "Failed",
- Values = new ChartValues<int>(),
- Fill = Brushes.Red,
- MinWidth = 1,
- };
-
- if (EndDate - StartDate > TimeSpan.FromDays(40))
- {
- completed_job_runs = new LineSeries()
- {
- Title = "Completed",
- Values = new ChartValues<int>(),
- Fill = new SolidColorBrush(Colors.Green) { Opacity = 0.5 },
- MinWidth = 1,
- PointGeometry = null,
- StrokeThickness = 0,
-
- };
- aborted_job_runs = new LineSeries()
- {
- Title = "Aborted",
- Values = new ChartValues<int>(),
- Fill = new SolidColorBrush(Colors.Orange) { Opacity = 0.5 },
- MinWidth = 1,
- PointGeometry = null,
- StrokeThickness = 0,
- };
- failed_job_runs = new LineSeries()
- {
- Title = "Failed",
- Values = new ChartValues<int>(),
- Fill = new SolidColorBrush(Colors.Red) { Opacity = 0.5 },
- MinWidth = 1,
- PointGeometry = null,
- StrokeThickness = 0,
- };
- }
-
- foreach (var date in CreateDates(StartDate, EndDate))
- {
- completed_job_runs.Values.Add(GetJobRunsByDate(date, JobRunStatus.Completed).Count());
- aborted_job_runs.Values.Add(GetJobRunsByDate(date, JobRunStatus.Aborted).Count());
- failed_job_runs.Values.Add(GetJobRunsByDate(date, JobRunStatus.Failed).Count());
-
- TimelineJobStatusSeries.Labels.Add(date.ToShortDateString());
- }
-
-
-
- TimelineJobStatusSeries.SeriesCollection.Add(failed_job_runs);
- TimelineJobStatusSeries.SeriesCollection.Add(aborted_job_runs);
- TimelineJobStatusSeries.SeriesCollection.Add(completed_job_runs);
- }
-
- private void GeneratePieFailedReasonsChart()
- {
- var groups = GetJobRunsByDateRange(StartDate, EndDate, JobRunStatus.Failed).GroupBy(x => x.FailedMessage).OrderBy(x => x.Count());
-
- List<Color> colors = new List<Color>();
-
- int max = groups.Count() > 0 ? groups.Max(x => x.Count()) : 0;
-
- for (int i = 0; i < groups.Count(); i++)
- {
- int count = groups.ElementAt(i).Count();
- double alpha = Math.Max(((double)(count) / max * 200), 20);
- colors.Add(Color.FromArgb((byte)alpha, 200, 0, 0));
- }
-
- PieJobFailedReasons = new LabeledSeriesCollection()
- {
- Title = "Job Failure Reasons",
- SeriesColors = colors,
- };
-
- int index = 0;
-
- foreach (var group in groups)
- {
- int count = group.Count();
-
- var series = new PieSeries()
- {
- Title = group.First().FailedMessage,
- Values = new ChartValues<int>() { count },
- Fill = new SolidColorBrush(colors[index++]),
- DataLabels = true,
- ToolTip = group.First().FailedMessage,
- };
-
- PieJobFailedReasons.SeriesCollection.Add(series);
- }
- }
-
- private void GeneratePrintPerWeekChart()
- {
- List<JobRunModel> range_job_runs = GetJobRunsByDateRange(StartDate, EndDate);
-
- Dictionary<Machine, List<double>> weeks_print_avg = new Dictionary<Machine, List<double>>();
-
- //Init machines weeks averages dictionary.
- foreach (var machine in range_job_runs.Select(x => x.Machine).OrderBy(x => x.Name).DistinctBy(x => x.Guid))
- {
- weeks_print_avg[machine] = new List<double>();
- }
-
- //Create all available dates
- List<DateTime> all_dates = range_job_runs.Select(x => x.StartDate).ToList();
-
- //get first Sunday.
- DateTime current_sunday = all_dates.FirstOrDefault(x => x.DayOfWeek == DayOfWeek.Sunday);
-
- if (current_sunday != null && all_dates.Count > 0)
- {
- //Iterate over each week starting from the earliest Sunday.
- while (current_sunday <= all_dates.Last())
- {
- var week_job_runs = range_job_runs.Where(x => x.EndPosition > 10 && x.StartDate >= current_sunday && x.StartDate <= current_sunday.AddDays(7)).ToList();
-
- foreach (var machine_job_runs in week_job_runs.GroupBy(x => x.Machine))
- {
- weeks_print_avg[machine_job_runs.Key].Add(machine_job_runs.Select(x => x.EndPosition).Average());
- }
-
- current_sunday = current_sunday.AddDays(8);
- }
- }
-
- Dictionary<Machine, double> week_print_avg = new Dictionary<Machine, double>();
-
- //Init machines week average dictionary.
- foreach (var machine in weeks_print_avg)
- {
- if (machine.Value.Count > 0)
- {
- week_print_avg[machine.Key] = machine.Value.Average();
- }
- }
-
- //Init chart series
- PrintPerWeekSeries = new LabeledSeriesCollection()
- {
- Title = "Average Printed Thread Per Week (m)",
- ChartTitle = "Average Print Per Week (m)",
- LabelsTitle = "Date",
- SeriesColors = new List<Color>()
- {
-
- },
- };
-
- //Init series colors intensity by number of prints.
- double max = week_print_avg.Count > 0 ? week_print_avg.Max(x => x.Value) : 0;
- foreach (var machine in week_print_avg)
- {
- double a = (machine.Value / max);
- PrintPerWeekSeries.SeriesColors.Add(Color.FromArgb((byte)(255d * (machine.Value / max)), 0, 200, 0));
- }
-
- //Init columns.
- int index = 0;
-
- foreach (var machine in week_print_avg)
- {
- var series = new ColumnSeries()
- {
- Title = machine.Key.Name,
- Values = new ChartValues<int>() { (int)machine.Value },
- Fill = new SolidColorBrush(PrintPerWeekSeries.SeriesColors[index++]),
- DataLabels = true,
- ToolTip = machine.Key.SerialNumber,
- };
-
- PrintPerWeekSeries.SeriesCollection.Add(series);
- }
+ ChartsViewVM.Init();
}
}
}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/ChartsView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/ChartsView.xaml
new file mode 100644
index 000000000..ecd7e01ed
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/ChartsView.xaml
@@ -0,0 +1,110 @@
+<UserControl x:Class="Tango.MachineStudio.Statistics.Views.ChartsView"
+ 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:vm="clr-namespace:Tango.MachineStudio.Statistics.ViewModels"
+ xmlns:global="clr-namespace:Tango.MachineStudio.Statistics"
+ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
+ xmlns:local="clr-namespace:Tango.MachineStudio.Statistics.Views"
+ xmlns:tooltips="clr-namespace:Tango.MachineStudio.Statistics.Tooltips"
+ xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
+ mc:Ignorable="d"
+ d:DesignHeight="450" d:DesignWidth="800">
+ <Grid IsEnabled="{Binding IsFree}">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="80"/>
+ <RowDefinition Height="337*"/>
+ </Grid.RowDefinitions>
+
+ <StackPanel Margin="60 20 0 0" VerticalAlignment="Center" HorizontalAlignment="Left" Orientation="Horizontal">
+ <StackPanel>
+ <TextBlock FontSize="10">Start Date:</TextBlock>
+ <DatePicker DisplayDateStart="{Binding MinDate}" DisplayDateEnd="{Binding MaxDate}" SelectedDate="{Binding StartDate}" materialDesign:HintAssist.Hint="Pick start date" Width="200" VerticalAlignment="Bottom" FontSize="16"></DatePicker>
+ </StackPanel>
+
+ <StackPanel Margin="40 0 0 0">
+ <TextBlock FontSize="10">End Date:</TextBlock>
+ <DatePicker DisplayDateStart="{Binding MinDate}" DisplayDateEnd="{Binding MaxDate}" SelectedDate="{Binding EndDate}" materialDesign:HintAssist.Hint="Pick end date" Width="200" VerticalAlignment="Bottom" FontSize="16"></DatePicker>
+ </StackPanel>
+ </StackPanel>
+
+ <UniformGrid Columns="3" Margin="50 20 50 50" Rows="2" Grid.Row="1">
+ <Border BorderBrush="{StaticResource Statistics.BorderBrush}" Padding="5" BorderThickness="1" CornerRadius="5" Margin="10">
+ <DockPanel>
+ <TextBlock DockPanel.Dock="Top" FontSize="16" FontWeight="Bold" HorizontalAlignment="Center" Padding="10" Text="{Binding TimelineJobStatusSeries.Title}"></TextBlock>
+ <lvc:CartesianChart Series="{Binding TimelineJobStatusSeries.SeriesCollection}" LegendLocation="Bottom" SeriesColors="{Binding TimelineJobStatusSeries.SeriesColors}">
+ <lvc:CartesianChart.DataTooltip>
+ <lvc:DefaultTooltip BulletSize="20" Background="{StaticResource TransparentBackgroundBrush450}" Foreground="{StaticResource Dialog.Foreground}"/>
+ </lvc:CartesianChart.DataTooltip>
+ <lvc:CartesianChart.AxisX>
+ <lvc:Axis Title="{Binding TimelineJobStatusSeries.LabelsTitle}" Labels="{Binding TimelineJobStatusSeries.Labels}" Foreground="{StaticResource DarkGrayBrush200}">
+ <lvc:Axis.Separator>
+ <lvc:Separator Stroke="#A5A5A5" />
+ </lvc:Axis.Separator>
+ </lvc:Axis>
+ </lvc:CartesianChart.AxisX>
+ <lvc:CartesianChart.AxisY>
+ <lvc:Axis Title="{Binding TimelineJobStatusSeries.ChartTitle}" MinValue="0" Foreground="{StaticResource DarkGrayBrush200}" >
+ <lvc:Axis.Separator>
+ <lvc:Separator Stroke="#B0B0B0" />
+ </lvc:Axis.Separator>
+ </lvc:Axis>
+ </lvc:CartesianChart.AxisY>
+ </lvc:CartesianChart>
+ </DockPanel>
+ </Border>
+
+ <Border BorderBrush="{StaticResource Statistics.BorderBrush}" Padding="5" BorderThickness="1" CornerRadius="5" Margin="10">
+ <DockPanel>
+ <TextBlock DockPanel.Dock="Top" FontSize="16" FontWeight="Bold" HorizontalAlignment="Center" Padding="10" Text="{Binding PieJobFailedReasons.Title}"></TextBlock>
+ <UniformGrid Columns="2">
+ <lvc:PieChart DataHover="PieChart_DataHover" Series="{Binding PieJobFailedReasons.SeriesCollection}" LegendLocation="None" SeriesColors="{Binding PieJobFailedReasons.SeriesColors}" Background="Transparent">
+ <lvc:PieChart.Resources>
+ <Style TargetType="lvc:PieSeries">
+ <Setter Property="Stroke" Value="#99F9F9F9"></Setter>
+ <Setter Property="StrokeThickness" Value="2"/>
+ </Style>
+ </lvc:PieChart.Resources>
+ <lvc:PieChart.DataTooltip>
+ <tooltips:PieChartTooltipControl Visibility="Hidden" />
+ </lvc:PieChart.DataTooltip>
+ </lvc:PieChart>
+
+ <TextBlock x:Name="txtPieTitle" TextWrapping="Wrap"></TextBlock>
+ </UniformGrid>
+ </DockPanel>
+ </Border>
+
+ <Border BorderBrush="{StaticResource Statistics.BorderBrush}" Padding="5" BorderThickness="1" CornerRadius="5" Margin="10">
+ <DockPanel>
+ <TextBlock DockPanel.Dock="Top" FontSize="16" FontWeight="Bold" HorizontalAlignment="Center" Padding="10" Text="{Binding PrintPerWeekSeries.Title}"></TextBlock>
+ <lvc:CartesianChart Series="{Binding PrintPerWeekSeries.SeriesCollection}" LegendLocation="Bottom" SeriesColors="{Binding PrintPerWeekSeries.SeriesColors}" >
+ <lvc:CartesianChart.Resources>
+ <Style TargetType="lvc:ColumnSeries">
+ <Setter Property="Foreground" Value="{StaticResource DarkGrayBrush200}"></Setter>
+ </Style>
+ </lvc:CartesianChart.Resources>
+ <lvc:CartesianChart.AxisX>
+ <lvc:Axis Title="{Binding PrintPerWeekSeries.LabelsTitle}" Labels="{Binding PrintPerWeekSeries.Labels}" Foreground="{StaticResource DarkGrayBrush200}">
+ <lvc:Axis.Separator>
+ <lvc:Separator Stroke="#A5A5A5" />
+ </lvc:Axis.Separator>
+ </lvc:Axis>
+ </lvc:CartesianChart.AxisX>
+ <lvc:CartesianChart.AxisY>
+ <lvc:Axis Title="{Binding PrintPerWeekSeries.ChartTitle}" MinValue="0" Foreground="{StaticResource DarkGrayBrush200}" >
+ <lvc:Axis.Separator>
+ <lvc:Separator Stroke="#6F6F6F" />
+ </lvc:Axis.Separator>
+ </lvc:Axis>
+ </lvc:CartesianChart.AxisY>
+ <lvc:CartesianChart.DataTooltip>
+ <lvc:DefaultTooltip BulletSize="20" Background="{StaticResource TransparentBackgroundBrush450}" Foreground="{StaticResource Dialog.Foreground}"/>
+ </lvc:CartesianChart.DataTooltip>
+ </lvc:CartesianChart>
+ </DockPanel>
+ </Border>
+ </UniformGrid>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/ChartsView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/ChartsView.xaml.cs
new file mode 100644
index 000000000..d79d88281
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/ChartsView.xaml.cs
@@ -0,0 +1,35 @@
+using LiveCharts;
+using LiveCharts.Wpf;
+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.Statistics.Views
+{
+ /// <summary>
+ /// Interaction logic for ChartsView.xaml
+ /// </summary>
+ public partial class ChartsView : UserControl
+ {
+ public ChartsView()
+ {
+ InitializeComponent();
+ }
+ private void PieChart_DataHover(object sender, ChartPoint chartPoint)
+ {
+ var tooltip = ((chartPoint.ChartView as PieChart).DataTooltip as Tooltips.PieChartTooltipControl).Title;
+ txtPieTitle.Text = tooltip;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/JobRunsView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/JobRunsView.xaml
new file mode 100644
index 000000000..4667959b8
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/JobRunsView.xaml
@@ -0,0 +1,239 @@
+<UserControl x:Class="Tango.MachineStudio.Statistics.Views.JobRunsView"
+ 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:sharedConverters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI"
+ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
+ xmlns:localConverters="clr-namespace:Tango.MachineStudio.Statistics.Converters"
+ xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls"
+ xmlns:sys="clr-namespace:System;assembly=mscorlib"
+ xmlns:enumerations="clr-namespace:Tango.BL.Enumerations;assembly=Tango.BL"
+ xmlns:local="clr-namespace:Tango.MachineStudio.Statistics.Views"
+ mc:Ignorable="d"
+ d:DesignHeight="450" d:DesignWidth="1200">
+ <UserControl.Resources>
+ <sharedConverters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
+ <sharedConverters:EnumToDescriptionConverter x:Key="EnumToDescriptionConverter" />
+ <sharedConverters:DateTimeUTCToShortDateTimeConverter x:Key="DateTimeUTCToShortDateTimeConverter"/>
+ <localConverters:DateIsInListToBooleanConverter x:Key="DateIsInListToBooleanConverter"/>
+ <localConverters:StringToBoolYesNoNullConverter x:Key="StringToBoolYesNoNullConverter"/>
+
+ <ResourceDictionary x:Key="SelectAllTextBoxResource">
+ <Style TargetType="TextBox">
+ <EventSetter Event="GotFocus" Handler="TextBox_GotFocus"></EventSetter>
+ <EventSetter Event="MouseDown" Handler="TextBox_PreviewMouseUp"></EventSetter>
+ </Style>
+ </ResourceDictionary>
+
+ <Style x:Key="CustomCalendarDayButtonStyle" TargetType="{x:Type CalendarDayButton}" BasedOn="{StaticResource MaterialDesignCalendarDayButton}">
+ <Style.Triggers>
+ <DataTrigger Value="True">
+ <DataTrigger.Binding>
+ <MultiBinding Converter="{StaticResource DateIsInListToBooleanConverter}">
+ <Binding />
+ <Binding RelativeSource="{RelativeSource AncestorType=UserControl}" Path="DataContext.Dates" />
+ <Binding RelativeSource="{RelativeSource AncestorType=DatePicker}" Path="IsDropDownOpen" ></Binding>
+ </MultiBinding>
+ </DataTrigger.Binding>
+ <Setter Property="Foreground" Value="{StaticResource AccentColorBrush}" />
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+
+ <Style x:Key="HighlightDatePickerStyle" TargetType="{x:Type Calendar}" BasedOn="{StaticResource {x:Type Calendar}}">
+ <Setter Property="CalendarDayButtonStyle" Value="{StaticResource CustomCalendarDayButtonStyle}" />
+ </Style>
+
+ <ObjectDataProvider x:Key="JobSource" MethodName="GetValues" ObjectType="{x:Type sys:Enum}">
+ <ObjectDataProvider.MethodParameters>
+ <x:Type TypeName="enumerations:JobSource"/>
+ </ObjectDataProvider.MethodParameters>
+ </ObjectDataProvider>
+
+ <ObjectDataProvider x:Key="JobRunStatus" MethodName="GetValues" ObjectType="{x:Type sys:Enum}">
+ <ObjectDataProvider.MethodParameters>
+ <x:Type TypeName="enumerations:JobRunStatus"/>
+ </ObjectDataProvider.MethodParameters>
+ </ObjectDataProvider>
+
+ </UserControl.Resources>
+
+ <Grid IsEnabled="{Binding IsFree}">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="3*"/>
+ <ColumnDefinition Width="1*"/>
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="100"/>
+ <RowDefinition Height="*"/>
+ <RowDefinition Height="Auto"/>
+ </Grid.RowDefinitions>
+ <materialDesign:Card Grid.Row="0" Background="{StaticResource WhiteBackgroundBrush}" Foreground="{StaticResource JobFieldForeground}" Width="Auto" Margin="10 10 0 0" >
+
+ <DockPanel>
+ <StackPanel Orientation="Horizontal" DockPanel.Dock="Left">
+ <StackPanel Margin="30 5 0 20" Orientation="Vertical" >
+ <TextBlock DockPanel.Dock="Top" Text="Machine:" VerticalAlignment="Center" FontSize="10"></TextBlock>
+ <ToggleButton Width="200" Margin="0 10 0 0" x:Name="selectMachineButton" HorizontalAlignment="Left" FontSize="16" VerticalAlignment="Center">
+ <ToggleButton.Template>
+ <ControlTemplate>
+ <Grid>
+ <Border CornerRadius="3" BorderBrush="{StaticResource borderBrush}" BorderThickness="1" TextElement.Foreground="Black" >
+ <DockPanel>
+ <Button Width="18" Padding="0" Height="16" DockPanel.Dock="Right" BorderBrush="{x:Null}" HorizontalAlignment="Left" Click="Button_Click" Style="{StaticResource MaterialDesignFlatButton}" Foreground="{StaticResource MainWindow.Foreground}">
+ <materialDesign:PackIcon Width="16" Height="16" Kind="ChevronDown" VerticalAlignment="Center" Foreground="{StaticResource MainWindow.Foreground}" HorizontalAlignment="Right"/>
+ </Button>
+ <TextBlock VerticalAlignment="Center" Foreground="{StaticResource MainWindow.Foreground}">
+ <Run Text=" Select Machines"></Run>
+ <Run>(</Run><Run Text="{Binding SelectedMachines.SynchedSource.Count,Mode=OneWay}"></Run><Run>)</Run>
+ </TextBlock>
+ </DockPanel>
+ </Border>
+ <Popup StaysOpen="False" IsOpen="{Binding RelativeSource={RelativeSource AncestorType=ToggleButton},Path=IsChecked }" >
+ <Border Padding="5" Background="{DynamicResource ComboBox.Floating.Background}" BorderBrush="{StaticResource AutoCompleteTextBox.Popup.BorderBrush}">
+ <ScrollViewer MaxHeight="600" Background="{DynamicResource ComboBox.Floating.Background}">
+ <ItemsControl ItemsSource="{Binding SelectedMachines}" Foreground="{StaticResource MainWindow.Foreground}">
+ <ItemsControl.ItemTemplate>
+ <DataTemplate>
+ <DockPanel Margin="2">
+ <CheckBox VerticalAlignment="Center" DockPanel.Dock="Left" IsChecked="{Binding IsSelected}" />
+ <TextBlock Margin="5 0 0 0" VerticalAlignment="Center" Text="{Binding Data.SerialNumber}"></TextBlock>
+ </DockPanel>
+ </DataTemplate>
+ </ItemsControl.ItemTemplate>
+ </ItemsControl>
+ </ScrollViewer>
+ </Border>
+ </Popup>
+ </Grid>
+ </ControlTemplate>
+ </ToggleButton.Template>
+ </ToggleButton>
+
+ </StackPanel>
+ <Border Margin="30 10 0 20" Padding="5" BorderBrush="#38696969" BorderThickness="1" >
+ <StackPanel Orientation="Horizontal">
+ <materialDesign:PackIcon Kind="Calendar" Width="24" Height="24" VerticalAlignment="Bottom" Margin="0 0 0 5" />
+ <DatePicker x:Name="datePicker" DisplayDateStart="{Binding MinDate}" DisplayDateEnd="{Binding MaxDate}" CalendarStyle="{StaticResource HighlightDatePickerStyle}" SelectedDate="{Binding SelectedDate}" materialDesign:HintAssist.Hint="Pick Date" Margin="10 0 0 5" Width="100" VerticalAlignment="Bottom" FontSize="16">
+ </DatePicker>
+ </StackPanel>
+ </Border>
+ <StackPanel Margin="30 5 20 20" Orientation="Vertical">
+ <TextBlock Text="Job Name:" VerticalAlignment="Center" FontSize="10"></TextBlock>
+ <TextBox Text="{Binding JobName}" VerticalAlignment="Center" FontSize="16" Margin="0 5 0 0" Width="100"></TextBox>
+ </StackPanel>
+ <StackPanel Margin="30 5 20 0" Orientation="Vertical">
+ <TextBlock Text="Source:" VerticalAlignment="Center" FontSize="10"></TextBlock>
+ <ComboBox Width="100" FontSize="14" Margin="0 5 0 0" ItemsSource="{Binding Source={StaticResource JobSource}}" SelectedItem="{Binding JobRunSource, UpdateSourceTrigger=PropertyChanged}">
+ <ComboBox.ItemContainerStyle>
+ <Style TargetType="ComboBoxItem" BasedOn="{StaticResource {x:Type ComboBoxItem}}">
+ <Setter Property="Background" Value="{StaticResource WhiteBrush100}"></Setter>
+ </Style>
+ </ComboBox.ItemContainerStyle>
+ <ComboBox.ItemTemplate>
+ <DataTemplate>
+ <TextBlock Text="{Binding Converter={StaticResource EnumToDescriptionConverter}}"></TextBlock>
+ </DataTemplate>
+ </ComboBox.ItemTemplate>
+ </ComboBox>
+ </StackPanel>
+ <StackPanel Margin="30 5 20 0" Orientation="Vertical">
+ <TextBlock Text="Gradient:" VerticalAlignment="Center" FontSize="10"></TextBlock>
+ <ComboBox Width="100" FontSize="14" Margin="0 5 0 0" SelectedItem="{Binding IsGradient, Converter={StaticResource StringToBoolYesNoNullConverter}, UpdateSourceTrigger=PropertyChanged, Mode=OneWayToSource}">
+ <ComboBox.ItemContainerStyle>
+ <Style TargetType="ComboBoxItem" BasedOn="{StaticResource {x:Type ComboBoxItem}}">
+ <Setter Property="Background" Value="{StaticResource WhiteBrush100}"></Setter>
+ </Style>
+ </ComboBox.ItemContainerStyle>
+ <ComboBoxItem Content="Yes" />
+ <ComboBoxItem Content="No" />
+ <ComboBoxItem Content="Null" />
+ </ComboBox>
+ </StackPanel>
+ <StackPanel Margin="30 5 20 0" Orientation="Vertical">
+ <TextBlock Text="Length:" VerticalAlignment="Center" FontSize="10"></TextBlock>
+ <mahapps:NumericUpDown Width="100" Margin="0 8.5 0 0" x:Name="numLength" FontSize="21" HideUpDownButtons="True" HorizontalAlignment="Left" FontFamily="{StaticResource digital-7}" StringFormat="{}{0:N1} m" Minimum="0" Maximum="5000" InterceptArrowKeys="True" Background="Transparent" BorderThickness="0 0 0 1" BorderBrush="{StaticResource DimGrayBrush}" InterceptMouseWheel="True" HasDecimals="True" HorizontalContentAlignment="Left" Value="{Binding Length,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
+ <mahapps:NumericUpDown.Resources>
+ <StaticResource ResourceKey="SelectAllTextBoxResource"></StaticResource>
+ </mahapps:NumericUpDown.Resources>
+ </mahapps:NumericUpDown>
+ </StackPanel>
+ <StackPanel Margin="30 5 20 0" Orientation="Vertical">
+ <TextBlock Text="Status:" VerticalAlignment="Center" FontSize="10"></TextBlock>
+ <ComboBox Width="100" FontSize="14" Margin="0 5 0 0" ItemsSource="{Binding Source={StaticResource JobRunStatus}}" SelectedItem="{Binding JobRunStatus, UpdateSourceTrigger=PropertyChanged}">
+ <ComboBox.ItemContainerStyle>
+ <Style TargetType="ComboBoxItem" BasedOn="{StaticResource {x:Type ComboBoxItem}}">
+ <Setter Property="Background" Value="{StaticResource WhiteBrush100}"></Setter>
+ </Style>
+ </ComboBox.ItemContainerStyle>
+ <ComboBox.ItemTemplate>
+ <DataTemplate>
+ <TextBlock Text="{Binding Converter={StaticResource EnumToDescriptionConverter}}"></TextBlock>
+ </DataTemplate>
+ </ComboBox.ItemTemplate>
+ </ComboBox>
+ </StackPanel>
+
+ </StackPanel>
+ <Button HorizontalAlignment="Right" Command="{Binding LoadJobRunsCommand}" DockPanel.Dock="Right" Margin="10">GO</Button>
+ </DockPanel>
+ </materialDesign:Card>
+
+ <DataGrid Grid.Row="1" Margin="20 0 0 10" SelectionMode="Single" SelectionUnit="FullRow" RowHeight="40" BorderBrush="{StaticResource borderBrush}" IsReadOnly="True" BorderThickness="1"
+ Background="{StaticResource TransparentBackgroundBrush}" AlternatingRowBackground="{StaticResource Transparent200}" AutoGenerateColumns="False" CanUserReorderColumns="True"
+ CanUserAddRows="False" CanUserDeleteRows="False" ItemsSource="{Binding JobRuns}"
+ SelectedItem="{Binding SelectedJobRun}" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" FontSize="11">
+ <DataGrid.CellStyle>
+ <Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}">
+ <Setter Property="BorderThickness" Value="0"/>
+ <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
+ <Setter Property="VerticalContentAlignment" Value="Center"></Setter>
+ <Style.Triggers>
+ <Trigger Property="IsSelected" Value="True">
+ <Setter Property="Background" Value="Transparent"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource AccentColorBrush}" />
+ </Trigger>
+ </Style.Triggers>
+ </Style>
+ </DataGrid.CellStyle>
+ <DataGrid.RowStyle>
+ <Style TargetType="DataGridRow" BasedOn="{StaticResource {x:Type DataGridRow}}">
+ <Style.Triggers>
+ <Trigger Property="IsMouseOver" Value="True">
+ <Setter Property="Background" Value="Transparent"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource AccentColorBrush}" />
+ <Setter Property="Cursor" Value="Hand"></Setter>
+ </Trigger>
+ <Trigger Property="IsSelected" Value="True">
+ <Setter Property="Background" Value="Transparent"></Setter>
+ </Trigger>
+ <Trigger Property="IsFocused" Value="True">
+ <Setter Property="Background" Value="Transparent"></Setter>
+ </Trigger>
+ </Style.Triggers>
+ </Style>
+ </DataGrid.RowStyle>
+
+ <DataGrid.Columns>
+ <DataGridTextColumn Header="START DATE" Binding="{Binding JobRun.StartDate, Converter={StaticResource DateTimeUTCToShortDateTimeConverter}}" Width="Auto" />
+ <DataGridTextColumn Header="LENGTH" Binding="{Binding JobRun.JobLength}" Width="Auto" />
+ <DataGridTextColumn Header="STATUS" Binding="{Binding JobRun.JobRunStatus, Converter={StaticResource EnumToDescriptionConverter}}" Width="Auto"/>
+ <DataGridTextColumn Header="DESIGNATION" Binding="{Binding JobRun.Designation, Converter={StaticResource EnumToDescriptionConverter}}" Width="Auto"/>
+ <DataGridTextColumn Header="SOURCE" Binding="{Binding JobRun.Source, Converter={StaticResource EnumToDescriptionConverter}}" Width="Auto" />
+ </DataGrid.Columns>
+ </DataGrid>
+ <Border Grid.Row="1" Grid.Column="1" Margin="20, 0, 20, 10" BorderBrush="{StaticResource borderBrush}" Background="{StaticResource TransparentBackgroundBrush}" BorderThickness="1">
+
+ <StackPanel>
+ <TextBlock Margin="10" Text="{Binding SelectedJobRunsText}"></TextBlock>
+ </StackPanel>
+ </Border>
+ <Border Grid.Row="2" Grid.ColumnSpan="2" Margin="20, 10, 20, 20" BorderBrush="{StaticResource borderBrush}" Background="{StaticResource TransparentBackgroundBrush}" BorderThickness="1">
+ <StackPanel Background="{StaticResource TransparentBackgroundBrush}" >
+ <TextBlock>TOTALS:</TextBlock>
+ <TextBlock>Cyan:</TextBlock>
+ </StackPanel>
+ </Border>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/JobRunsView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/JobRunsView.xaml.cs
new file mode 100644
index 000000000..0966533b9
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/JobRunsView.xaml.cs
@@ -0,0 +1,44 @@
+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.Statistics.Views
+{
+ /// <summary>
+ /// Interaction logic for JobRunsView.xaml
+ /// </summary>
+ public partial class JobRunsView : UserControl
+ {
+ public JobRunsView()
+ {
+ InitializeComponent();
+ }
+ private void Button_Click(object sender, RoutedEventArgs e)
+ {
+ selectMachineButton.IsChecked = true;
+ e.Handled = true;
+ }
+ private async void TextBox_GotFocus(object sender, RoutedEventArgs e)
+ {
+ await Task.Delay(200);
+ TextBox txtBox = sender as TextBox;
+ txtBox.SelectAll();
+ }
+
+ private void TextBox_PreviewMouseUp(object sender, MouseButtonEventArgs e)
+ {
+ e.Handled = true;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/MainView.xaml
index 55804c7b3..170d3276a 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/MainView.xaml
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/MainView.xaml
@@ -11,100 +11,28 @@
xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
mc:Ignorable="d"
d:DesignHeight="1080" d:DesignWidth="1920" Background="Transparent" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}">
- <Grid IsEnabled="{Binding IsFree}">
+ <Grid>
<Grid.RowDefinitions>
- <RowDefinition Height="80"/>
- <RowDefinition Height="337*"/>
+ <RowDefinition Height="1*"/>
+ <RowDefinition Height="20"/>
</Grid.RowDefinitions>
-
- <StackPanel Margin="60 20 0 0" VerticalAlignment="Center" HorizontalAlignment="Left" Orientation="Horizontal">
- <StackPanel>
- <TextBlock FontSize="10">Start Date:</TextBlock>
- <DatePicker DisplayDateStart="{Binding MinDate}" DisplayDateEnd="{Binding MaxDate}" SelectedDate="{Binding StartDate}" materialDesign:HintAssist.Hint="Pick start date" Width="200" VerticalAlignment="Bottom" FontSize="16"></DatePicker>
- </StackPanel>
-
- <StackPanel Margin="40 0 0 0">
- <TextBlock FontSize="10">End Date:</TextBlock>
- <DatePicker DisplayDateStart="{Binding MinDate}" DisplayDateEnd="{Binding MaxDate}" SelectedDate="{Binding EndDate}" materialDesign:HintAssist.Hint="Pick end date" Width="200" VerticalAlignment="Bottom" FontSize="16"></DatePicker>
- </StackPanel>
- </StackPanel>
-
- <UniformGrid Columns="3" Margin="50 20 50 50" Rows="2" Grid.Row="1">
- <Border BorderBrush="{StaticResource Statistics.BorderBrush}" Padding="5" BorderThickness="1" CornerRadius="5" Margin="10">
- <DockPanel>
- <TextBlock DockPanel.Dock="Top" FontSize="16" FontWeight="Bold" HorizontalAlignment="Center" Padding="10" Text="{Binding TimelineJobStatusSeries.Title}"></TextBlock>
- <lvc:CartesianChart Series="{Binding TimelineJobStatusSeries.SeriesCollection}" LegendLocation="Bottom" SeriesColors="{Binding TimelineJobStatusSeries.SeriesColors}">
- <lvc:CartesianChart.DataTooltip>
- <lvc:DefaultTooltip BulletSize="20" Background="{StaticResource TransparentBackgroundBrush450}" Foreground="{StaticResource Dialog.Foreground}"/>
- </lvc:CartesianChart.DataTooltip>
- <lvc:CartesianChart.AxisX>
- <lvc:Axis Title="{Binding TimelineJobStatusSeries.LabelsTitle}" Labels="{Binding TimelineJobStatusSeries.Labels}" Foreground="{StaticResource DarkGrayBrush200}">
- <lvc:Axis.Separator>
- <lvc:Separator Stroke="#A5A5A5" />
- </lvc:Axis.Separator>
- </lvc:Axis>
- </lvc:CartesianChart.AxisX>
- <lvc:CartesianChart.AxisY>
- <lvc:Axis Title="{Binding TimelineJobStatusSeries.ChartTitle}" MinValue="0" Foreground="{StaticResource DarkGrayBrush200}" >
- <lvc:Axis.Separator>
- <lvc:Separator Stroke="#B0B0B0" />
- </lvc:Axis.Separator>
- </lvc:Axis>
- </lvc:CartesianChart.AxisY>
- </lvc:CartesianChart>
- </DockPanel>
- </Border>
-
- <Border BorderBrush="{StaticResource Statistics.BorderBrush}" Padding="5" BorderThickness="1" CornerRadius="5" Margin="10">
- <DockPanel>
- <TextBlock DockPanel.Dock="Top" FontSize="16" FontWeight="Bold" HorizontalAlignment="Center" Padding="10" Text="{Binding PieJobFailedReasons.Title}"></TextBlock>
- <UniformGrid Columns="2">
- <lvc:PieChart DataHover="PieChart_DataHover" Series="{Binding PieJobFailedReasons.SeriesCollection}" LegendLocation="None" SeriesColors="{Binding PieJobFailedReasons.SeriesColors}" Background="Transparent">
- <lvc:PieChart.Resources>
- <Style TargetType="lvc:PieSeries">
- <Setter Property="Stroke" Value="#99F9F9F9"></Setter>
- <Setter Property="StrokeThickness" Value="2"/>
- </Style>
- </lvc:PieChart.Resources>
- <lvc:PieChart.DataTooltip>
- <tooltips:PieChartTooltipControl Visibility="Hidden" />
- </lvc:PieChart.DataTooltip>
- </lvc:PieChart>
-
- <TextBlock x:Name="txtPieTitle" TextWrapping="Wrap"></TextBlock>
- </UniformGrid>
- </DockPanel>
- </Border>
-
- <Border BorderBrush="{StaticResource Statistics.BorderBrush}" Padding="5" BorderThickness="1" CornerRadius="5" Margin="10">
- <DockPanel>
- <TextBlock DockPanel.Dock="Top" FontSize="16" FontWeight="Bold" HorizontalAlignment="Center" Padding="10" Text="{Binding PrintPerWeekSeries.Title}"></TextBlock>
- <lvc:CartesianChart Series="{Binding PrintPerWeekSeries.SeriesCollection}" LegendLocation="Bottom" SeriesColors="{Binding PrintPerWeekSeries.SeriesColors}" >
- <lvc:CartesianChart.Resources>
- <Style TargetType="lvc:ColumnSeries">
- <Setter Property="Foreground" Value="{StaticResource DarkGrayBrush200}"></Setter>
- </Style>
- </lvc:CartesianChart.Resources>
- <lvc:CartesianChart.AxisX>
- <lvc:Axis Title="{Binding PrintPerWeekSeries.LabelsTitle}" Labels="{Binding PrintPerWeekSeries.Labels}" Foreground="{StaticResource DarkGrayBrush200}">
- <lvc:Axis.Separator>
- <lvc:Separator Stroke="#A5A5A5" />
- </lvc:Axis.Separator>
- </lvc:Axis>
- </lvc:CartesianChart.AxisX>
- <lvc:CartesianChart.AxisY>
- <lvc:Axis Title="{Binding PrintPerWeekSeries.ChartTitle}" MinValue="0" Foreground="{StaticResource DarkGrayBrush200}" >
- <lvc:Axis.Separator>
- <lvc:Separator Stroke="#6F6F6F" />
- </lvc:Axis.Separator>
- </lvc:Axis>
- </lvc:CartesianChart.AxisY>
- <lvc:CartesianChart.DataTooltip>
- <lvc:DefaultTooltip BulletSize="20" Background="{StaticResource TransparentBackgroundBrush450}" Foreground="{StaticResource Dialog.Foreground}"/>
- </lvc:CartesianChart.DataTooltip>
- </lvc:CartesianChart>
- </DockPanel>
- </Border>
- </UniformGrid>
+ <Grid Grid.Row="0" IsEnabled="{Binding IsFree}">
+ <TabControl Background="Transparent" Margin="0,40,0,0" x:Name="chartsTabControl" Padding="0 25 0 0">
+ <TabControl.Resources>
+ <Style TargetType="TabPanel">
+ <Setter Property="HorizontalAlignment" Value="Center"/>
+ </Style>
+ <Style TargetType="TabItem" BasedOn="{StaticResource {x:Type TabItem}}">
+ <Setter Property="Padding" Value="20,2"></Setter>
+ </Style>
+ </TabControl.Resources>
+ <TabItem Header="STATS" Margin="-100 0 0 0 ">
+ <local:ChartsView x:Name="processParametersView" DataContext="{Binding ChartsViewVM}"/>
+ </TabItem>
+ <TabItem Header="JOB RUNS" Margin="-100 0 0 0 ">
+ <local:JobRunsView x:Name="jobRunsView" DataContext="{Binding JobRunsViewVM}"/>
+ </TabItem>
+ </TabControl>
+ </Grid>
</Grid>
</UserControl>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/MainView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/MainView.xaml.cs
index 3948c4e5a..f0d1c39a7 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/MainView.xaml.cs
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/MainView.xaml.cs
@@ -28,10 +28,6 @@ namespace Tango.MachineStudio.Statistics.Views
InitializeComponent();
}
- private void PieChart_DataHover(object sender, ChartPoint chartPoint)
- {
- var tooltip = ((chartPoint.ChartView as PieChart).DataTooltip as Tooltips.PieChartTooltipControl).Title;
- txtPieTitle.Text = tooltip;
- }
+
}
}
diff --git a/Software/Visual_Studio/Tango.SharedUI/Controls/MultiSelectComboBox.cs b/Software/Visual_Studio/Tango.SharedUI/Controls/MultiSelectComboBox.cs
new file mode 100644
index 000000000..66eaa4e14
--- /dev/null
+++ b/Software/Visual_Studio/Tango.SharedUI/Controls/MultiSelectComboBox.cs
@@ -0,0 +1,180 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using Tango.Core.Commands;
+using System.ComponentModel;
+
+namespace Tango.SharedUI.Controls
+{
+ public class MultiSelectComboBox : Control
+ {
+ static MultiSelectComboBox()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(MultiSelectComboBox), new FrameworkPropertyMetadata(typeof(MultiSelectComboBox)));
+
+ }
+
+ public MultiSelectComboBox() : base()
+ {
+ RemoveAllCommand = new RelayCommand((() => SelectedItemsList.Clear()), () => SelectedItemsList != null && SelectedItemsList.Count > 0);
+ RemoveItemCommand = new RelayCommand<string>((item) => SelectedItemsList.Remove(item), () => SelectedItemsList != null);
+ AddItemCommand = new RelayCommand<string>((item) => SelectedItemsList.Add(item));
+ SearchText = "";
+ }
+
+ #region Properties
+
+ public ObservableCollection<string> SelectedItemsList
+ {
+ get { return (ObservableCollection<string>)GetValue(SelectedItemsListProperty); }
+ set { SetValue(SelectedItemsListProperty, value); }
+ }
+
+ public static readonly DependencyProperty SelectedItemsListProperty =
+ DependencyProperty.Register("SelectedItemsList", typeof(ObservableCollection<string>), typeof(MultiSelectComboBox), new PropertyMetadata(default(ObservableCollection<string>)));
+
+
+ public ListCollectionView SearchItemsList
+ {
+ get { return (ListCollectionView)GetValue(SearchItemsListProperty); }
+ set { SetValue(SearchItemsListProperty, value); }
+ }
+ /// <summary>
+ /// The search items list property for popup items list
+ /// </summary>
+ public static readonly DependencyProperty SearchItemsListProperty =
+ DependencyProperty.Register("SearchItemsList", typeof(ListCollectionView), typeof(MultiSelectComboBox), new PropertyMetadata(default(ObservableCollection<string>)));
+
+ public ObservableCollection<string> Items
+ {
+ get { return (ObservableCollection<string>)GetValue(ItemsProperty); }
+ set { SetValue(ItemsProperty, value); }
+ }
+
+ public static readonly DependencyProperty ItemsProperty =
+ DependencyProperty.Register("Items", typeof(ObservableCollection<string>), typeof(MultiSelectComboBox), new PropertyMetadata(default(ObservableCollection<string>)));
+
+
+
+ public bool IsToggleChecked
+ {
+ get { return (bool)GetValue(IsToggleCheckedProperty); }
+ set { SetValue(IsToggleCheckedProperty, value); }
+ }
+ public static readonly DependencyProperty IsToggleCheckedProperty =
+ DependencyProperty.Register("IsToggleChecked", typeof(bool), typeof(MultiSelectComboBox), new PropertyMetadata(false));
+
+
+
+ private string _searchText;
+ /// <summary>
+ /// Gets or sets the search text of TextBox.
+ /// </summary>
+ public string SearchText
+ {
+ get { return _searchText; }
+ set {_searchText = value;
+ RaisePropertyChanged("SearchText");
+ OnTextChanged();
+ }
+ }
+
+ void OnTextChanged()
+ {
+ if(SearchItemsList != null)
+ {
+ if (String.IsNullOrEmpty(SearchText))
+ SearchItemsList.Filter = null;
+ else
+ SearchItemsList.Filter = new Predicate<object>(o => ((string)o == SearchText));
+ }
+ }
+ /// <summary>
+ /// Occurs when a property has changed.
+ /// </summary>
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ /// <summary>
+ /// Raises the property changed event.
+ /// </summary>
+ /// <param name="propName">Name of the property.</param>
+ protected virtual void RaisePropertyChanged(String propName)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
+ }
+
+
+ #endregion
+
+ /// <summary>
+ /// When overridden in a derived class, is invoked whenever application code or internal processes call <see cref="M:System.Windows.FrameworkElement.ApplyTemplate" />.
+ /// </summary>
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+ if (SelectedItemsList == null)
+ SelectedItemsList = new ObservableCollection<string>();
+ SearchItemsList = new ListCollectionView(this.Items);
+
+ //ItemsControl iControl = FindName("asd") as ItemsControl;
+ //iControl.ItemContainerGenerator.ItemsChanged += ItemContainerGenerator_ItemsChanged;
+ //iControl.ItemContainerGenerator.ContainerFromItem(null);
+
+ //for (int i = 0; i < iControl.Items.Count; i++)
+ //{
+ // FrameworkElement a = iControl.ItemContainerGenerator.ContainerFromIndex(i) as FrameworkElement;
+ //}
+ }
+
+ private void ItemContainerGenerator_ItemsChanged(object sender, System.Windows.Controls.Primitives.ItemsChangedEventArgs e)
+ {
+
+ }
+
+ #region Commands
+ /// <summary>
+ /// The remove all command property for clear SelectedItemsList
+ /// </summary>
+ public static DependencyProperty RemoveAllCommandProperty = DependencyProperty.Register("RemoveAllCommand", typeof(ICommand), typeof(MultiSelectComboBox));
+ public ICommand RemoveAllCommand
+ {
+ get { return (ICommand)GetValue(RemoveAllCommandProperty); }
+ private set { SetValue(RemoveAllCommandProperty, value); }
+ }
+
+ /// <summary>
+ /// The remove item from SelectedItemsList command property
+ /// </summary>
+ public static DependencyProperty RemoveItemCommandProperty = DependencyProperty.Register("RemoveItemCommand", typeof(RelayCommand<string>), typeof(MultiSelectComboBox));
+ public RelayCommand<string> RemoveItemCommand
+ {
+ get { return (RelayCommand<string>)GetValue(RemoveItemCommandProperty); }
+ private set { SetValue(RemoveItemCommandProperty, value); }
+ }
+
+
+ public static DependencyProperty AddItemCommandProperty = DependencyProperty.Register("AddItemCommand", typeof(RelayCommand<string>), typeof(MultiSelectComboBox));
+ public RelayCommand<string> AddItemCommand
+ {
+ get { return (RelayCommand<string>)GetValue(AddItemCommandProperty); }
+ private set { SetValue(AddItemCommandProperty, value); }
+ }
+ #endregion
+
+
+
+ }
+}
diff --git a/Software/Visual_Studio/Tango.SharedUI/Tango.SharedUI.csproj b/Software/Visual_Studio/Tango.SharedUI/Tango.SharedUI.csproj
index de5ed61f7..ef84d982e 100644
--- a/Software/Visual_Studio/Tango.SharedUI/Tango.SharedUI.csproj
+++ b/Software/Visual_Studio/Tango.SharedUI/Tango.SharedUI.csproj
@@ -74,6 +74,7 @@
<Compile Include="Controls\HiveControl.xaml.cs">
<DependentUpon>HiveControl.xaml</DependentUpon>
</Compile>
+ <Compile Include="Controls\MultiSelectComboBox.cs" />
<Compile Include="Controls\MultiSelectDataGrid.cs" />
<Compile Include="Controls\MultiSelectListBox.cs" />
<Compile Include="Controls\MultiTransitionControl.xaml.cs">
@@ -210,6 +211,10 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
+ <Page Include="Themes\Generic.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
</ItemGroup>
<ItemGroup>
<Resource Include="Images\pubclass.gif" />
@@ -242,7 +247,7 @@
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
<VisualStudio>
- <UserProperties BuildVersion_StartDate="2000/1/1" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" />
+ <UserProperties BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UseGlobalSettings="False" BuildVersion_StartDate="2000/1/1" />
</VisualStudio>
</ProjectExtensions>
</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/Tango.SharedUI/Themes/Generic.xaml b/Software/Visual_Studio/Tango.SharedUI/Themes/Generic.xaml
new file mode 100644
index 000000000..85e9dbb8b
--- /dev/null
+++ b/Software/Visual_Studio/Tango.SharedUI/Themes/Generic.xaml
@@ -0,0 +1,127 @@
+<ResourceDictionary
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:fa="http://schemas.fontawesome.io/icons/"
+ xmlns:local="clr-namespace:Tango.SharedUI.Controls">
+
+
+
+ <Style TargetType="{x:Type local:MultiSelectComboBox}">
+ <Setter Property="Background" Value="Transparent"></Setter>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type local:MultiSelectComboBox}">
+ <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}"
+ BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="3" >
+ <Grid>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="Auto"/>
+ </Grid.ColumnDefinitions>
+ <ToggleButton x:Name="MultiSelToggleButton" Grid.Column="0" MinHeight="40" Height="Auto"
+ VerticalAlignment="Center"
+ HorizontalAlignment="Stretch" Margin="4,0,0,0" SnapsToDevicePixels="True"
+ Foreground="{TemplateBinding Foreground}" BorderBrush="{TemplateBinding BorderBrush}"
+ IsChecked="{Binding RelativeSource={RelativeSource AncestorType=local:MultiSelectComboBox}, Path=IsToggleChecked,Mode=TwoWay}">
+ <ToggleButton.Template>
+ <ControlTemplate TargetType="ToggleButton">
+ <Grid >
+ <WrapPanel>
+ <ItemsControl x:Name="SelectedItems" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=local:MultiSelectComboBox}, Path=SelectedItemsList}">
+ <ItemsControl.Template>
+ <ControlTemplate TargetType="{x:Type ItemsControl}">
+ <ItemsPresenter HorizontalAlignment="Stretch" />
+ </ControlTemplate>
+ </ItemsControl.Template>
+ <ItemsControl.ItemsPanel>
+ <ItemsPanelTemplate>
+ <WrapPanel IsItemsHost="True" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left"/>
+ </ItemsPanelTemplate>
+ </ItemsControl.ItemsPanel>
+ <ItemsControl.ItemTemplate>
+ <DataTemplate>
+ <Button Margin="4,2" Height="25" Width="Auto" Background="Transparent" BorderThickness="0.5" BorderBrush="{Binding RelativeSource={RelativeSource AncestorType=local:MultiSelectComboBox}, Path=BorderBrush}"
+ Command="{Binding RelativeSource={RelativeSource AncestorType=local:MultiSelectComboBox}, Path=RemoveItemCommand}" CommandParameter="{Binding}">
+ <StackPanel Orientation="Horizontal">
+ <TextBlock Text="{Binding}" VerticalAlignment="Center" />
+ <fa:ImageAwesome Icon="Close" Width="12" Margin="2" VerticalAlignment="Center" HorizontalAlignment="Right" RenderTransformOrigin="0.5,0.5"/>
+ </StackPanel>
+ </Button>
+ </DataTemplate>
+ </ItemsControl.ItemTemplate>
+ </ItemsControl>
+ <TextBox x:Name="Edit_PART" Height="25" VerticalAlignment="Top" BorderBrush="Transparent" VerticalContentAlignment="Center" BorderThickness="0"
+ Text="{Binding RelativeSource={RelativeSource AncestorType=local:MultiSelectComboBox},Path=SearchText, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Margin="2"></TextBox>
+ </WrapPanel>
+ </Grid>
+ </ControlTemplate>
+ </ToggleButton.Template>
+ </ToggleButton>
+ <Button Grid.Column=" 1" BorderBrush="Transparent" Opacity="0.05" VerticalContentAlignment="Top" Command="{Binding RelativeSource={RelativeSource AncestorType=local:MultiSelectComboBox}, Path=RemoveAllCommand}">
+ <fa:ImageAwesome Icon="Times" Width="12" Foreground="{TemplateBinding Foreground}" Margin="10" VerticalAlignment="Top">
+ </fa:ImageAwesome>
+ <Button.Style>
+ <Style TargetType="Button">
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type Button}">
+ <Border Background="{TemplateBinding Background}">
+ <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
+ </Border>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ <Style.Triggers>
+ <Trigger Property="IsMouseOver" Value="True">
+ <Setter Property="Background" Value="Transparent" />
+ <Setter Property="BorderBrush" Value="Transparent"/>
+ </Trigger>
+ <Trigger Property="IsMouseOver" Value="False">
+ <Setter Property="Background" Value="Transparent" />
+ <Setter Property="BorderBrush" Value="Transparent"/>
+ </Trigger>
+ <EventTrigger RoutedEvent="Control.MouseEnter">
+ <BeginStoryboard>
+ <Storyboard >
+ <DoubleAnimation Duration="0:0:1" To="1" Storyboard.TargetProperty="Opacity"/>
+ </Storyboard>
+ </BeginStoryboard>
+ </EventTrigger>
+ <EventTrigger RoutedEvent="Control.MouseLeave">
+ <BeginStoryboard>
+ <Storyboard >
+ <DoubleAnimation Duration="0:0:1" To="0.05" Storyboard.TargetProperty="Opacity"/>
+ </Storyboard>
+ </BeginStoryboard>
+ </EventTrigger>
+ </Style.Triggers>
+ </Style>
+ </Button.Style>
+ </Button>
+ <Popup x:Name="MultiSel_Popup" Tag="{Binding RelativeSource={RelativeSource AncestorType=local:MultiSelectComboBox}}" MinHeight="25" MaxHeight="600" HorizontalOffset="0" MinWidth="{TemplateBinding ActualWidth}" MaxWidth="800" Grid.ColumnSpan="2"
+ PlacementTarget="{Binding ElementName=MultiSelToggleButton}" Placement="Bottom" AllowsTransparency="True"
+ IsOpen="{Binding RelativeSource={RelativeSource Self},Path=Tag.IsToggleChecked,Mode=TwoWay}" PopupAnimation="Slide" >
+ <Border Opacity="1" Background="{TemplateBinding Background}" Padding="3" BorderThickness="1" BorderBrush="Beige">
+ <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Hidden">
+ <ItemsControl x:Name="PropertyDisplay" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=local:MultiSelectComboBox}, Path=SearchItemsList}">
+ <ItemsControl.ItemTemplate>
+ <DataTemplate>
+ <Button Margin="4,2" Height="Auto" Width="Auto" Background="Transparent" BorderThickness="0.5" BorderBrush="{Binding RelativeSource={RelativeSource AncestorType=local:MultiSelectComboBox}, Path=BorderBrush}"
+ Command="{Binding RelativeSource={RelativeSource AncestorType=local:MultiSelectComboBox}, Path=AddItemCommand}" CommandParameter="{Binding}">
+ <StackPanel Orientation="Horizontal">
+ <TextBlock Text="{Binding}" VerticalAlignment="Center" />
+ </StackPanel>
+ </Button>
+ </DataTemplate>
+ </ItemsControl.ItemTemplate>
+ </ItemsControl>
+ </ScrollViewer>
+ </Border>
+ </Popup>
+ </Grid>
+ </Border>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+</ResourceDictionary>
diff --git a/Software/Visual_Studio/Utilities/Tango.UITests/MainWindow.xaml b/Software/Visual_Studio/Utilities/Tango.UITests/MainWindow.xaml
index 53fdc25d3..99c5f3259 100644
--- a/Software/Visual_Studio/Utilities/Tango.UITests/MainWindow.xaml
+++ b/Software/Visual_Studio/Utilities/Tango.UITests/MainWindow.xaml
@@ -3,44 +3,11 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:collection="clr-namespace:System.Collections;assembly=mscorlib"
- xmlns:local="clr-namespace:Tango.UITests"
- xmlns:dragAndDrop="clr-namespace:Tango.DragAndDrop;assembly=Tango.DragAndDrop"
- xmlns:components="clr-namespace:Tango.Touch.Components;assembly=Tango.Touch"
xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI"
- xmlns:keyboard="clr-namespace:Tango.Touch.Keyboard;assembly=Tango.Touch"
- xmlns:aero="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
- xmlns:stubs="clr-namespace:Tango.Stubs.Views;assembly=Tango.Stubs"
- xmlns:touch="clr-namespace:Tango.Touch.Controls;assembly=Tango.Touch"
- xmlns:commonControls="clr-namespace:Tango.PPC.Common.Controls;assembly=Tango.PPC.Common"
- xmlns:explorer="clr-namespace:Tango.Explorer;assembly=Tango.Explorer"
mc:Ignorable="d"
Title="MainWindow" Height="700" Width="800" DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
- <touch:TouchPanel>
- <touch:LightTouchScrollViewer>
- <Border Width="500" Height="500" Margin="0 40 0 0">
- <Grid>
- <aero:SystemDropShadowChrome CornerRadius="5" Color="Gray" Margin="-3">
- <aero:SystemDropShadowChrome.RenderTransform>
- <TranslateTransform X="-5" Y="-5"></TranslateTransform>
- </aero:SystemDropShadowChrome.RenderTransform>
- </aero:SystemDropShadowChrome>
- <Border BorderThickness="1" BorderBrush="Gray" Background="White" CornerRadius="5">
-
- </Border>
-
- <StackPanel>
- <touch:TouchNumericTextBox HorizontalAlignment="Center" VerticalAlignment="Center" Width="200"></touch:TouchNumericTextBox>
- <touch:TouchNumericTextBox Margin="0 40 0 0" HorizontalAlignment="Center" VerticalAlignment="Center" Width="200"></touch:TouchNumericTextBox>
-
- <TextBox Margin="0 40 0 0" HorizontalAlignment="Center" VerticalAlignment="Center" Width="200" Height="40"></TextBox>
- <TextBox Margin="0 40 0 0" HorizontalAlignment="Center" VerticalAlignment="Center" Width="200" Height="40"></TextBox>
- </StackPanel>
- </Grid>
- </Border>
- </touch:LightTouchScrollViewer>
- </touch:TouchPanel>
+ <controls:MultiSelectComboBox Width="250" Height="60" x:Name="MSCombobox" BorderBrush="Gainsboro" BorderThickness="0.5"/>
</Grid>
</Window>
diff --git a/Software/Visual_Studio/Utilities/Tango.UITests/MainWindow.xaml.cs b/Software/Visual_Studio/Utilities/Tango.UITests/MainWindow.xaml.cs
index 6c24121ba..7eb688342 100644
--- a/Software/Visual_Studio/Utilities/Tango.UITests/MainWindow.xaml.cs
+++ b/Software/Visual_Studio/Utilities/Tango.UITests/MainWindow.xaml.cs
@@ -20,7 +20,6 @@ using System.Windows.Shapes;
using System.Windows.Threading;
using Tango.BL;
using Tango.BL.Builders;
-using Tango.BL.Catalogs;
using Tango.BL.Entities;
using Tango.Core;
using Tango.Core.Commands;
@@ -47,106 +46,26 @@ namespace Tango.UITests
/// </summary>
public partial class MainWindow : Window
{
- //private ITableDependency _dep;
-
- //private DataSource _dataSource;
-
public MainWindow()
{
- //_dataSource = new DataSource()
- //{
- // Address = "twine.database.windows.net",
- // Catalog = "Tango_DEV",
- // Type = DataSourceType.SQLServer,
- // UserName = "Roy",
- // Password = "Aa123456",
- // IntegratedSecurity = false,
- //};
-
- //InitializeComponent();
- //EntityFrameworkCache.Initialize(new MyMemoryCache() { Expiration = TimeSpan.FromMinutes(1) });
-
-
- //this.Closing += MainWindow_Closing;
-
- //CmdCommand command = new CmdCommand("wmic", "pagefile list /format:list");
- //var result = command.Run().Result;
+ InitializeComponent();
+ MSCombobox.Items = new ObservableCollection<string>
+ {
+ "item1",
+ "item2",
+ "item3"
- //Regex regEx = new Regex("Name=(.+)");
- //var pageFiles = regEx.Matches(result.StandardOutput).OfType<Match>().Select(x => x.Groups.OfType<Group>().LastOrDefault()).ToList().Select(x => x.Value.Replace("\n", "").Replace("\r", "")).ToList();
-
-
-
- //var matches = matches.OfType<Match>().Select(x => x.Groups.OfType<Group>().Last().Value.Replace("\n","").Replace("\r","")).ToList();
+ };
+ MSCombobox.SelectedItemsList = new ObservableCollection<string>
+ {
+ "item1",
+ "item2",
+ "item3",
+ "item2",
+ "item3"
+ };
}
-
- //private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
- //{
- // //if (_dep != null)
- // //{
- // // _dep.Stop();
- // // _dep.Dispose();
- // //}
- //}
-
-
- //private void btnStart_Click(object sender, RoutedEventArgs e)
- //{
- // Stopwatch watch = Stopwatch.StartNew();
-
- // using (ObservablesContext db = ObservablesContext.CreateDefault(_dataSource))
- // {
- // var users = db.Users.ToList();
- // var jobs = new JobsCollectionBuilder(db).SetAll().WithSegments().WithBrushStops().Build();
- // var first_job = jobs.First();
-
- // if (first_job.Name == "Changed Name 2")
- // {
- // Debug.WriteLine("Changed and cached !!!");
- // }
- // else
- // {
- // Debug.WriteLine("Not working.");
- // }
- // }
-
- // Debug.WriteLine($"Time to complete: {watch.Elapsed.TotalSeconds} seconds");
- //}
-
- //private void btnChange_Click(object sender, RoutedEventArgs e)
- //{
- // using (ObservablesContext db = ObservablesContext.CreateDefault(_dataSource))
- // {
- // var jobs = new JobsCollectionBuilder(db).SetAll().WithSegments().WithBrushStops().Build();
- // var first_job = jobs.First();
- // first_job.Name = "Changed Name 2";
- // db.SaveChanges();
- // }
- //}
-
- //private void btnListen_Click(object sender, RoutedEventArgs e)
- //{
- // String str = _dataSource.ToConnection().ConnectionString;
-
- // var dep = new SqlTableDependency<DAL.Remote.DB.USER>(str, "USERS", "dbo");
- // dep.TraceLevel = TraceLevel.Verbose;
- // dep.TraceListener = new TextWriterTraceListener(Console.Out);
-
- // dep.OnChanged += Changed;
- // dep.Start();
-
- // _dep = dep;
- //}
-
- //private void Changed(object sender, RecordChangedEventArgs<DAL.Remote.DB.USER> e)
- //{
- // var changedEntity = e.Entity;
-
- // Console.WriteLine("DML operation: " + e.ChangeType);
-
- // Console.WriteLine(changedEntity.ToJsonString());
- //}
}
}