Files
2026-04-17 14:55:32 -04:00

1183 lines
51 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Xml.Linq;
using DTS.Common;
using DTS.Common.Base;
using DTS.Common.Classes.Viewer.TestMetadata;
using DTS.Common.Enums.Sensors;
using DTS.Common.Events;
using DTS.Common.Interactivity;
using DTS.Common.Interface;
using DTS.Common.Interface.TestDefinition;
using DTS.Common.Strings;
using DTS.Common.Utilities.Logging;
using DTS.Common.Utils;
using Prism.Events;
using Prism.Regions;
using Unity;
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Local
// ReSharper disable CheckNamespace
// ReSharper disable NotAccessedField.Local
// ReSharper disable InconsistentNaming
// ReSharper disable UnusedMember.Local
// ReSharper disable RedundantDefaultMemberInitializer
// ReSharper disable RedundantAssignment
namespace DTS.Viewer.GraphList
{
public class ExportGraphMainViewModel : BaseViewModel<IExportGraphMainViewModel>, IExportGraphMainViewModel
{
public IFilterView FilterView { get; private set; }
public IExportGraphMainView View { get; set; }
public IBaseViewModel Parent { get; set; }
public bool SettingChildNodesToTrue { get; set; }
public bool SettingOrResettingChildNodes { get; set; }
public bool SettingPeerNodeToTrue { get; set; }
public bool SettingItemsBetween { get; set; }
public bool ResettingAllItems { get; set; }
private IEventAggregator _eventAggregator { get; set; }
private IUnityContainer _unityContainer { get; set; }
private bool _showIsoCodes = false;
public InteractionRequest<Notification> NotificationRequest { get; private set; }
public new InteractionRequest<Confirmation> ConfirmationRequest { get; private set; }
/// <summary>
/// Creates a new instance of the ExportGraphMainViewModel.
/// </summary>
/// <param name="view">The ExportGraphMainView interface.</param>
/// <param name="regionManager">The logical placeholder defined within the application's UI (in the shell or within views) into which views are displayed.</param>
/// <param name="eventAggregator">The EventAggregator which allows different components to publish/subscribe to events without being coupled to each other.</param>
/// <param name="unityContainer">The unityContainer.</param>
public ExportGraphMainViewModel(IExportGraphMainView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)
: base(regionManager, eventAggregator, unityContainer)
{
View = view;
View.DataContext = this;
NotificationRequest = new InteractionRequest<Notification>();
ConfirmationRequest = new InteractionRequest<Confirmation>();
_eventAggregator = eventAggregator;
_unityContainer = unityContainer;
}
#region Const
private const string testChannels = "Test Channels";
private const string EventNumber = "Event Number";
private const string calculatedChannels = "Calculated Channels";
private const string graphChannels = "Graph Channels: ";
#endregion
#region Colors
private readonly List<Color> _graphColors = new List<Color> { Colors.Transparent, Colors.Blue, Colors.Red, Colors.Green, Colors.BlueViolet, Colors.Brown, Colors.Aqua, Colors.Lime, Colors.Gray, Colors.YellowGreen, Colors.Black };
/// <summary>
/// Assign unused color to selected/locked channel
/// </summary>
/// <returns></returns>
private Color GetNextColor()
{
var nextColor = Colors.Transparent;
var channelCount = (LockedChannelList.Any() ? LockedChannelList.Count : 0) + (SelectedChannelList.Any() ? SelectedChannelList.Count : 0);
if (channelCount >= _graphColors.Count)
{
var nextColorIndex = channelCount % _graphColors.Count + 1;
if (nextColorIndex >= _graphColors.Count) { nextColorIndex = 1; }
nextColor = _graphColors[nextColorIndex];
}
else
{
var usedColors = new List<Color>();
usedColors.AddRange(LockedChannelList.Select(ch => ch.ChannelColor).ToList());
usedColors.AddRange(SelectedChannelList.Select(ch => ch.ChannelColor).ToList());
nextColor = _graphColors.Find(c1 => usedColors.TrueForAll(c2 => c2 != c1));
}
return nextColor;
}
#endregion
#region Methods
public override void Initialize()
{
}
private bool _lockedOnly = false; //only published locked channels
public override void Initialize(object parameter)
{
Parent = (IBaseViewModel)parameter;
if (Parent is IPSDReportMainViewModel) { _lockedOnly = true; } // only put checked channels in the report
FilterView = GetFilterView(this);
Subscribe();
}
/// <summary>
/// Reset all lists and publish changes
/// </summary>
private void CleanSelection()
{
LockedChannelList = new List<ITestChannel>();
ChannelList = new ObservableCollection<ITestChannel>();
FilteredChannelList = new ObservableCollection<ITestChannel>();
SelectedChannelList = new List<ITestChannel>();
_lastIndexChecked = 0;
_eventAggregator.GetEvent<GraphClearNotification>().Publish(new GraphClearNotificationArg { GraphClear = true, ParentVM = Parent });
PublishSelectedChannels();
SelectedGroupName = string.Empty;
GC.Collect();
}
/// <summary>
/// Format the Channel Display Name based on the isoCode setting
/// </summary>
/// <param name="channelName2"></param>
/// <param name="channelDescriptionString"></param>
/// <param name="isoCode"></param>
/// <returns></returns>
private string FormatChannelDisplayName(string channelName2, string channelDescriptionString, string isoCode)
{
return _showIsoCodes ? $"{channelName2} {channelDescriptionString} {Environment.NewLine} {isoCode}" : $"{channelName2} {channelDescriptionString}";
}
//hold onto the test summaries for reloads
private List<ITestSummary> testSummaries;
/// <summary>
/// Read all graphs, calculated channels and channels for the selected test
/// and select and display first group or channel
/// </summary>
/// <param name="list"></param>
private void OnTestSummaryChanged(TestSummaryChangeNotificationArg arg)
{
if (Parent != arg?.ParentVM) return;
//43387 Don't build the TestId tree until all of the tests have been selected
if (arg?.SummaryList.Count() != arg?.TotalSummaryCount) return;
var list = arg?.SummaryList;
testSummaries = list;
CleanSelection(); //clean every time, otherwise channels weren't being removed on test deselection
var total = 0;
//this list will hold test setups we want to remove
var listToRemove = new List<ITestSummary>();
if (list != null && list.Any())
{
foreach (var l in list)
{
//for now if there are no modules, remove the test from the list
if (l.TestMetadata == null || null == l.TestMetadata.TestRun || 0 == l.TestMetadata.TestRun.Modules.Count)
{
APILogger.Log($"Test {l.SetupName} - {l.TestMetadata.TestRun.FilePath} has no modules, skipping");
listToRemove.Add(l);
continue;
}
if (l.Channels.Any() && l.Channels.FirstOrDefault() == null)
{
// LOAD NOW!
Utils.SetChannelInfo(l.TestMetadata, Path.GetDirectoryName(l.TestMetadata.TestRun.FilePath), DTS.Serialization.SliceRaw.File.PersistentChannel.GetIsoCode);
l.Channels = l.TestMetadata.TestRun.Channels;
l.Graphs = l.TestMetadata.TestSetup.TestGraphs;
l.CalculatedChannels = l.TestMetadata.TestRun.CalculatedChannels;
}
foreach (var graph in l.Graphs)
{
//12017 Viewer shows "Graphs 1/2" when there is only 1 channel
//this issue was caused by an included graph with no channels.
if (graph.ChannelIds.Any())
{
total++;
}
}
if (null != l.CalculatedChannels)
{
total += l.CalculatedChannels.Count;
}
}
}
if (listToRemove.Any())
{
foreach( var l in listToRemove) { list?.Remove(l); }
}
if (list != null && list.Count <= 0) return;
var summaryList = list.ToList();
foreach (var ts in summaryList)
{
var testName = ts.Id + " " + ts.SetupName + " " + ts.DataType + " " + Utils.FormatTimeStamp(ts.TimeStamp);
if (ts.Graphs.Count > 0)
{
foreach (var graph in ts.Graphs)
{
foreach (var gch in graph.Channels.OrderBy(gch => gch.AbsoluteDisplayOrder).ThenBy(gch => gch.Number))
{
if (ChannelList.Any(x => x.Equals(gch))) continue;
gch.Group = testName;
gch.SubGroup = graphChannels + graph.Name;
gch.IsGraphChannel = true;
gch.GraphName = graph.Name;
gch.ChannelDisplayName = gch.ChannelName2 + " " + gch.ChannelDescriptionString;
gch.Parent = this;
gch.ChannelColor = Colors.Transparent;
gch.CanSelectChannel = false; gch.IsSelected = false; gch.IsLocked = false; gch.CanSelectChannel = true;
//Select first group
if (ChannelList.Count == 0) { SelectedGroupName = gch.SubGroup.Trim(); }
ChannelList.Add(gch);
}
}
}
if ((ts.CalculatedChannels != null) && (ts.CalculatedChannels.Count > 0))
{
foreach (var cch in ts.CalculatedChannels.OrderBy(cch => cch.AbsoluteDisplayOrder).ThenBy(cch => cch.Number))
{
if (ChannelList.Any(x => x.Equals(cch))) continue;
cch.Group = testName;
cch.SubGroup = calculatedChannels;
cch.IsGraphChannel = false;
cch.GraphName = string.Empty;
cch.ChannelDisplayName = cch.ChannelName2 + " " + cch.ChannelDescriptionString;
cch.IsCalculatedChannel = true;
cch.Parent = this;
cch.ChannelColor = Colors.Transparent;
cch.CanSelectChannel = false; cch.IsSelected = false; cch.IsLocked = false; cch.CanSelectChannel = true;
//Or select first calculated channel
if (ChannelList.Count == 0) { cch.IsSelected = true; }
ChannelList.Add(cch);
}
}
if (ts.Channels.Count > 0)
{
var tsChannels = ts.Channels.OrderBy(ch => ch.AbsoluteDisplayOrder).ThenBy(ch => ch.Number).ToList();
for (int i = 0; i < tsChannels.Count - 1; i++)
{
if (tsChannels[i].AbsoluteDisplayOrder == tsChannels[i + 1].AbsoluteDisplayOrder &&
tsChannels[i].Number == tsChannels[i + 1].Number)
{
switch (calibrationBehaviorSetting)
{
case CalibrationBehaviors.LinearIfAvailable:
tsChannels.RemoveAt(i);
i--;
break;
case CalibrationBehaviors.NonLinearIfAvailable:
tsChannels.RemoveAt(i + 1);
break;
case CalibrationBehaviors.UseBothIfAvailable:
tsChannels[i].ChannelDescriptionString += " (NonLinear)";
tsChannels[i + 1].ChannelDescriptionString += " (Linear)";
break;
}
}
}
total += tsChannels.Count;
foreach (var ch in tsChannels)
{
if (ChannelList.Any(x => x.Equals(ch))) continue;
ch.Group = testName;
ch.SubGroup = testChannels;
ch.IsGraphChannel = false;
ch.GraphName = string.Empty;
var channelDescription = ch.ChannelDescriptionString;
if (SensorConstants.IsTestSpecificEmbedded(channelDescription))
{
channelDescription = Strings.Table_NA;
}
ch.ChannelDisplayName = FormatChannelDisplayName(ch.ChannelName2, channelDescription, ch.IsoCode);
ch.Parent = this;
ch.ChannelColor = Colors.Transparent;
ch.CanSelectChannel = false; ch.IsSelected = false; ch.IsLocked = false; ch.CanSelectChannel = true;
//Or select first channel
if (ChannelList.Count == 0) { ch.IsSelected = true; }
ChannelList.Add(ch);
}
}
}
ChannelList.CollectionChanged += GraphList_CollectionChanged;
FilteredChannelList = new ObservableCollection<ITestChannel>(ChannelList);
TestChannelsTree.CollectionChanged += TestChannelsTree_CollectionChanged;
_eventAggregator.GetEvent<GraphLoadedCountNotification>().Publish(new GraphLoadedCountNotificationArg { LoadedCount = total, ParentVM = Parent });
if (ChannelList.Any())
{
var treeChannels = ChannelList.ToList();
TestChannelsTree = GetTestChannelsTree(treeChannels);
TestIdsTree = GetTestIdsTree(TestChannelsTree, summaryList);
foreach (var treeViewChannels in TestChannelsTree)
{
treeViewChannels.IsExpanded = false;
}
//temp
var parent = TestChannelsTree?.FirstOrDefault()?.Groups?.FirstOrDefault()?.Parent;
foreach (var testId in TestIdsTree)
{
testId.Parent = parent;
foreach (var group in testId.Events)
{
group.Parent = parent;
}
}
if (!string.IsNullOrEmpty(SelectedGroupName))
{
var group = (from t in TestChannelsTree from g in t.Groups where g.Name == SelectedGroupName.Replace(graphChannels, string.Empty) select g).FirstOrDefault();
if (group != null) { AddSelectedGroup(group); }
}
}
IsFilterEnabled = _channelList.Count > 0;
}
/// <summary>
/// Check changes to Test Modifications to see whether we need to withhold user input
/// </summary>
private void OnTestModificationsChanged(ITestModificationModel testModificationModel)
{
if (testModificationModel != null)
{
TestModified = testModificationModel.IsModified;
}
}
/// <summary>
/// Subscribe for events
/// </summary>
private void Subscribe()
{
_eventAggregator.GetEvent<RaiseNotification>().Subscribe(OnRaiseNotification);
_eventAggregator.GetEvent<FilterParameterChangedEvent>().Subscribe(OnFilterChanged);
_eventAggregator.GetEvent<TestSummaryChangeNotification>().Subscribe(OnTestSummaryChanged);
_eventAggregator.GetEvent<TestModificationChangedEvent>().Subscribe(OnTestModificationsChanged);
_eventAggregator.GetEvent<ExportCalibrationBehaviorSettingChangedEvent>().Subscribe(OnCalibrationBehaviorSettingChanged);
_eventAggregator.GetEvent<CalibrationBehaviorSettableInViewerChangedEvent>().Subscribe(OnCalibrationBehaviorSettableInViewerChanged);
_eventAggregator.GetEvent<ChannelCodesViewChangedEvent>().Subscribe(OnChannelCodesViewChangedEvent);
_eventAggregator.GetEvent<ClearSelectedExportsEvent>().Subscribe(OnClearSelectedExports);
}
private void OnCalibrationBehaviorSettableInViewerChanged(bool cbSettable)
{
}
private void OnChannelCodesViewChangedEvent(DTS.Common.Enums.IsoViewMode viewMode) => _showIsoCodes = (viewMode == Common.Enums.IsoViewMode.ISOAndUserCode
|| viewMode == Common.Enums.IsoViewMode.ISOOnly);
private CalibrationBehaviors calibrationBehaviorSetting { get; set; } = CalibrationBehaviors.NonLinearIfAvailable;
private void OnCalibrationBehaviorSettingChanged(CalibrationBehaviors cb)
{
calibrationBehaviorSetting = cb;
if (null != testSummaries)
{
OnTestSummaryChanged(new TestSummaryChangeNotificationArg { SummaryList = testSummaries, ParentVM = Parent });
}
}
#region Filter
/// <summary>
/// Filter Data Event
/// </summary>
/// <param name="args">Filter value</param>
public void OnFilterChanged(FilterParameterArgs args)
{
if (((IFilterViewModel)FilterView.DataContext).Parent == this)
{
FilteredTestIdsTree = string.IsNullOrEmpty(args.Param) ? new ObservableCollection<TreeViewIds>(TestIdsTree)
: new ObservableCollection<TreeViewIds>((from x in TestIdsTree where x.Name.ToLower().Contains(args.Param.ToLower()) select x).ToList());
}
}
#endregion Filter
#region Override
/// <summary>
/// Private Event handler for RaiseNotification event.
/// </summary>
private void OnRaiseNotification(NotificationContentEventArgs eventArgsWithTitle)
{
// Notification object expects a NotificationContentEventArgsWithoutTitle object and a Title string.
var eventArgsWithoutTitle = new NotificationContentEventArgs(eventArgsWithTitle.Message, eventArgsWithTitle.MessageDetails, eventArgsWithTitle.Image);
NotificationRequest.Raise(new Notification
{
Content = eventArgsWithoutTitle,
Title = eventArgsWithTitle.Title
});
}
/// <summary>
/// ? I thik it's not beed used
/// </summary>
public override void Activated()
{
var fp = new FilterParameterArgs
{
Param = string.Empty,
Requester = this
};
_eventAggregator.GetEvent<FilterParameterChangedEvent>().Publish(fp);
}
#endregion Override
/// <summary>
/// Publish Locked Channels
/// </summary>
/// <summary>
/// Publish Selected and/or locked Channels
/// </summary>
public void PublishSelectedChannels()
{
var list = new List<ITestChannel>();
if (LockedChannelList.Any()) list.AddRange(LockedChannelList);
if (!_lockedOnly && SelectedChannelList.Any()) list.AddRange(SelectedChannelList);
var count = list.Count;
_eventAggregator.GetEvent<GraphSelectedChannelCountNotification>().Publish(new GraphSelectedChannelCountNotificationArg { SelectedChannelCount = count, ParentVM = Parent });
_eventAggregator.GetEvent<GraphSelectedChannelsNotification>().Publish(new GraphSelectedChannelsNotificationArg { SelectedChannels = list, ParentVM = Parent });
}
/// <summary>
/// Publish Selected and/or locked Events
/// </summary>
public void PublishSelectedEvents()
{
var list = new BindingList<ITestEvent>();
if (!_lockedOnly && SelectedEventList.Any())
{
foreach (var sel in SelectedEventList)
{
list.Add(sel);
}
}
var count = list.Count;
_eventAggregator.GetEvent<GraphSelectedEventCountNotification>().Publish(new GraphSelectedEventCountNotificationArg { SelectedEventCount = count, ParentVM = Parent });
_eventAggregator.GetEvent<GraphSelectedEventsNotification>().Publish(new GraphSelectedEventsNotificationArg { SelectedEvents = list, ParentVM = Parent });
}
/// <summary>
/// Load Filter View
/// </summary>
/// <param name="parent"></param>
/// <returns></returns>
private IFilterView GetFilterView(IBaseViewModel parent)
{
var view = _unityContainer.Resolve<IFilterView>();
var viewModel = _unityContainer.Resolve<IFilterViewModel>();
view.DataContext = viewModel;
viewModel.Initialize(parent);
return view;
}
#endregion
#region Reset Functions
private void ResetSelectedChannelColor()
{
foreach (var ch in SelectedChannelList) { if (ch.IsLocked) continue; ch.ChannelColor = Colors.Transparent; ch.CanSelectChannel = true; }
}
/// <summary>
/// Reset all selected channels prior to selecting new channel or group
/// </summary>
private void ResetSelected() { ResetSelected(string.Empty); }
private void ResetSelected(string eventName)
{
foreach (var test in TestIdsTree)
{
foreach (var e in test.Events)
{
if (!string.IsNullOrEmpty(eventName) && e.Name == eventName) continue;
e.IsSelected = false;
}
}
}
#endregion Reset Functions
#region Add Selected/Locked Channel
#region Locked Channel
public void AddLockedGroupChannels(string testName, string groupName, List<ITestChannel> channels, bool isLocked)
{
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>().Publish(true);
foreach (var channel in channels)
{
if (isLocked)
{
if (SelectedChannelList.Contains(channel)) { SelectedChannelList.Remove(channel); }
if (LockedChannelList.Contains(channel)) continue;
channel.CanSelectChannel = false;
channel.IsLocked = true;
channel.CanSelectChannel = true;
LockedChannelList.Add(channel);
if (channel.ChannelColor == Colors.Transparent) { channel.ChannelColor = GetNextColor(); }
}
else
{
if (!LockedChannelList.Contains(channel)) continue;
LockedChannelList.Remove(channel);
}
}
PublishSelectedChannels();
if (!LockedChannelList.Any() && !SelectedChannelList.Any())
{
var group = (from t in TestChannelsTree from g in t.Groups where g.TestName == testName && g.Name == groupName select g).FirstOrDefault();
if (group != null) { group.IsSelected = true; }
}
else { if (SelectedChannelList.Any()) { PublishSelectedChannels(); } }
UpdateChannelLocks();
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>().Publish(false);
}
public void AddLockedChannel(ITestChannel channel, bool isLocked)
{
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>().Publish(true);
if (isLocked)
{
if (SelectedChannelList.Contains(channel)) { SelectedChannelList.Remove(channel); }
if (!LockedChannelList.Contains(channel))
{
channel.CanSelectChannel = false;
channel.IsLocked = true;
channel.CanSelectChannel = true;
LockedChannelList.Add(channel);
if (channel.ChannelColor == Colors.Transparent) { channel.ChannelColor = GetNextColor(); }
}
}
else
{
if (LockedChannelList.Contains(channel))
{
LockedChannelList.Remove(channel);
}
// if there are no selected or locked channels add unlocked channel to selected list
if (!SelectedChannelList.Any())
{
if (!LockedChannelList.Exists(x => x.IsSelected)) { AddSelectedChannel(channel, true); }
}
}
UpdateChannelLocks();
PublishSelectedChannels();
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>().Publish(false);
}
private const int MAX_LOCKED_CHANNELS = 8;
private void UpdateChannelLocks()
{
var canLock = LockedChannelList.Count < MAX_LOCKED_CHANNELS;
foreach (var treeChannel in TestChannelsTree)
{
foreach (var group in treeChannel.Groups)
{
if (group.IsGraph)
{
if (group.IsLocked)
{
continue;
}
group.CanLock = group.Channels.Count + LockedChannelList.Count <= MAX_LOCKED_CHANNELS;
}
foreach (var channel in group.Channels)
{
if (channel.IsLocked) { continue; }
channel.CanLock = canLock;
}
}
}
}
#endregion Locked Channel
#region Selected Channel
public void AddSelectedGroupChannels(string groupName, List<ITestChannel> channels)
{
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>().Publish(true);
ResetSelectedChannelColor();
ResetSelected(groupName);
SelectedChannelList = new List<ITestChannel>();
foreach (var channel in channels)
{
SelectedChannelList.Add(channel);
if (channel.ChannelColor == Colors.Transparent) { channel.ChannelColor = GetNextColor(); }
}
PublishSelectedChannels();
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>().Publish(false);
}
public void AddSelectedGroup(TestGroup group)
{
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>().Publish(true);
group.IsSelected = true;
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>().Publish(false);
}
/// <summary>
/// Add selected channel to the list or select a group (graph) of channels
/// </summary>
/// <param name="channel"></param>
/// <param name="reset"></param>
public void AddSelectedChannel(ITestChannel channel, bool reset)
{
if (channel.IsLocked && LockedChannelList.Contains(channel))
{
ResetSelectedChannelColor();
SelectedChannelList = new List<ITestChannel>();
PublishSelectedChannels();
return;
}
if (channel.IsSelected && SelectedChannelList.Contains(channel)) return;
if (channel.IsGraphChannel)
{
var group = (from t in TestChannelsTree from g in t.Groups where g.TestName == channel.Group && g.Name == channel.GraphName select g).FirstOrDefault();
if (group != null) { AddSelectedGroup(group); }
}
else
{
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>().Publish(true);
if (reset)
{
SelectedChannelList = new List<ITestChannel>();
ResetSelected();
SelectedGroupName = string.Empty;
}
SelectedChannelList.Add(channel);
if (channel.ChannelColor == Colors.Transparent) { channel.ChannelColor = GetNextColor(); }
PublishSelectedChannels();
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>().Publish(false);
}
}
public void AddSelectedChannel(ITestChannel channel)
{
if (channel.IsLocked && LockedChannelList.Contains(channel))
{
//ResetSelected();
SelectedChannelList = new List<ITestChannel>();
PublishSelectedChannels();
return;
}
if (channel.IsSelected && SelectedChannelList.Contains(channel)) return;
if (channel.IsGraphChannel)
{
var group = (from t in TestChannelsTree from g in t.Groups where g.TestName == channel.Group && g.Name == channel.GraphName select g).FirstOrDefault();
if (group != null) { AddSelectedGroup(group); }
}
else
{
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>().Publish(true);
SelectedChannelList = new List<ITestChannel>();
ResetSelected();
SelectedGroupName = string.Empty;
SelectedChannelList.Add(channel);
if (channel.ChannelColor == Colors.Transparent) { channel.ChannelColor = GetNextColor(); }
PublishSelectedChannels();
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>().Publish(false);
}
}
#endregion Selected Channel
#region Locked Event
public void AddLockedEvents(string testName, string groupName, List<ITestEvent> events, bool isLocked)
{
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>().Publish(true);
foreach (var evnt in events)
{
if (isLocked)
{
if (SelectedEventList.Contains(evnt)) { SelectedEventList.Remove(evnt); }
if (LockedEventList.Contains(evnt)) continue;
//evnt.CanSelectEvent = false;
evnt.IsLocked = true;
//evnt.CanSelectEvent = true;
LockedEventList.Add(evnt);
//if (evnt.EventColor == Colors.Transparent) { evnt.EventColor = GetNextColor(); }
}
else
{
if (!LockedEventList.Contains(evnt)) continue;
LockedEventList.Remove(evnt);
}
}
PublishSelectedEvents();
if (!LockedEventList.Any() && !SelectedEventList.Any())
{
var group = (from t in TestChannelsTree from g in t.Groups where g.TestName == testName && g.Name == groupName select g).FirstOrDefault();
if (group != null) { group.IsSelected = true; }
}
else { if (SelectedEventList.Any()) { PublishSelectedEvents(); } }
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>().Publish(false);
}
#endregion Locked Event
#region Id Event
private void OnClearSelectedExports(ClearSelectedExportsArg arg)
{
SelectedEventList.Clear();
}
public void AddToSelectedEvents(string groupName, List<ITestEvent> events)
{
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>().Publish(true);
foreach (var e in events)
{
if (!SelectedEventList.Exists(item => item.TestItem == e.TestItem && item.Name == e.Name))
{
SelectedEventList.Add(e);
}
}
PublishSelectedEvents();
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>().Publish(false);
}
public void RemoveFromSelectedEvents(string groupName, List<ITestEvent> events)
{
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>().Publish(true);
foreach (var e in events)
{
var match = SelectedEventList.Find(item => item.TestItem == e.TestItem && item.Name == e.Name);
if (null != match)
{
SelectedEventList.Remove(match);
}
}
PublishSelectedEvents();
_eventAggregator.GetEvent<BusyIndicatorChangeNotification>().Publish(false);
}
public void SetItemsBetween(int startTreeIndex, int endTreeIndex)
{
foreach (var testId in TestIdsTree)
{
foreach (var e in testId.Events)
{
if (((e.TreeIndex >= startTreeIndex) && (e.TreeIndex <= endTreeIndex)) ||
((e.TreeIndex <= startTreeIndex) && (e.TreeIndex >= endTreeIndex)))
{
e.IsSelected = true;
}
}
}
}
public void ResetAllItems()
{
foreach (var testId in TestIdsTree)
{
foreach (var e in testId.Events)
{
//Don't bother setting it to False if it is already
if (e.IsSelected)
{
e.IsSelected = false;
}
}
}
}
public void SetLastIndexChecked(int index)
{
_lastIndexChecked = index;
}
#endregion Id Event
#endregion Add Selected/Locked Channel
#region ContextRegion
public object ContextGraphMainRegion
{
get => ((ExportGraphMainView)View).GraphMainRegion.DataContext;
set { ((ExportGraphMainView)View).GraphMainRegion.DataContext = value; OnPropertyChanged("ContextGraphMainRegion"); }
}
#endregion
#region Properties
private bool _isFilterEnabled = false;
public bool IsFilterEnabled
{
get => _isFilterEnabled;
set { _isFilterEnabled = value; OnPropertyChanged("IsFilterEnabled"); }
}
#region Selected/Locked Group
private string _selectedGroupName = string.Empty;
public string SelectedGroupName
{
get => _selectedGroupName;
set { _selectedGroupName = value; OnPropertyChanged("SelectedGroupName"); }
}
private string _lockedGroupName = string.Empty;
public string LockedGroupName
{
get => _lockedGroupName;
set { _lockedGroupName = value; OnPropertyChanged("LockedGroupName"); }
}
#endregion Selected/Locked Group
#region Lists
private List<ITestChannel> _lockedChannelList = new List<ITestChannel>();
public List<ITestChannel> LockedChannelList
{
get => _lockedChannelList;
set { _lockedChannelList = value; OnPropertyChanged("LockedChannelList"); }
}
private List<ITestEvent> _lockedEventList = new List<ITestEvent>();
public List<ITestEvent> LockedEventList
{
get => _lockedEventList;
set { _lockedEventList = value; OnPropertyChanged("LockedEventList"); }
}
private List<ITestChannel> _selectedChannelList = new List<ITestChannel>();
public List<ITestChannel> SelectedChannelList
{
get => _selectedChannelList;
set { _selectedChannelList = value; OnPropertyChanged("SelectedChannelList"); }
}
private List<ITestEvent> _selectedEventList = new List<ITestEvent>();
public List<ITestEvent> SelectedEventList
{
get => _selectedEventList;
set { _selectedEventList = value; OnPropertyChanged("SelectedEventList"); }
}
private int _lastIndexChecked = 0;
public int LastIndexChecked
{
get
{
return _lastIndexChecked;
}
}
#endregion Lists
#region ObservableCollection
private ObservableCollection<ITestChannel> _channelList = new ObservableCollection<ITestChannel>();
public ObservableCollection<ITestChannel> ChannelList
{
get => _channelList;
set { _channelList = value; IsFilterEnabled = _channelList.Count > 0; FilteredChannelList = new ObservableCollection<ITestChannel>(_channelList); OnPropertyChanged("ChannelList"); }
}
private ObservableCollection<ITestChannel> _filteredChannelList = new ObservableCollection<ITestChannel>();
public ObservableCollection<ITestChannel> FilteredChannelList
{
get => _filteredChannelList;
set { _filteredChannelList = value; TestChannelsTree = GetTestChannelsTree(_filteredChannelList.ToList()); OnPropertyChanged("FilteredChannelList"); }
}
private ObservableCollection<TreeViewChannels> _testChannelsTree = new ObservableCollection<TreeViewChannels>();
/// <summary>
/// Main treeview object
/// </summary>
public ObservableCollection<TreeViewChannels> TestChannelsTree
{
get => _testChannelsTree;
set { _testChannelsTree = value; OnPropertyChanged("TestChannelsTree"); }
}
private ObservableCollection<TreeViewIds> _testIdsTree = new ObservableCollection<TreeViewIds>();
/// <summary>
/// Main treeview object
/// </summary>
public ObservableCollection<TreeViewIds> TestIdsTree
{
get => _testIdsTree;
set { _testIdsTree = value; FilteredTestIdsTree = _testIdsTree; OnPropertyChanged("TestIdsTree"); }
}
private ObservableCollection<TreeViewIds> _filteredTestIdsTree = new ObservableCollection<TreeViewIds>();
public ObservableCollection<TreeViewIds> FilteredTestIdsTree
{
get => _filteredTestIdsTree;
set { _filteredTestIdsTree = value; OnPropertyChanged("FilteredTestIdsTree"); }
}
#endregion ObservableCollection
#region ObservableCollection Extension
public void TestChannelsTree_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.OldItems != null) { foreach (INotifyPropertyChanged item in e.OldItems) item.PropertyChanged -= TestChannelsTree_PropertyChanged; }
if (e.NewItems != null) { foreach (INotifyPropertyChanged item in e.NewItems) { item.PropertyChanged += TestChannelsTree_PropertyChanged; } }
}
private void TestChannelsTree_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName != "TestChannelsTree") { }
}
public void GraphList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.OldItems != null) { foreach (INotifyPropertyChanged item in e.OldItems) item.PropertyChanged -= GraphList_PropertyChanged; }
if (e.NewItems != null) { foreach (INotifyPropertyChanged item in e.NewItems) { item.PropertyChanged += GraphList_PropertyChanged; } }
}
private void GraphList_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName != "ChannelList") { } }
#endregion ObservableCollection Extension
#region PropertyChanged
///<summary>
///Occurs when a property value changes.
///</summary>
public new event PropertyChangedEventHandler PropertyChanged;
private new void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); }
#endregion PropertyChanged
/// <summary>
/// Gets the HeaderInfo.
/// </summary>
public string HeaderInfo => "GraphRegion";
public new bool IsBusy { get; set; }
public new bool IsDirty { get; set; }
private bool _testModified = false;
public bool TestModified { get => _testModified; set { _testModified = value; OnPropertyChanged("TestModified"); } }
#endregion
/// <summary>
/// Build the tree form list
/// </summary>
/// <param name="list">Test Channel list</param>
/// <returns>tree</returns>
private ObservableCollection<TreeViewChannels> GetTestChannelsTree(List<ITestChannel> list)
{
if (!list.Any()) return new ObservableCollection<TreeViewChannels>();
var result = (from t in list
group t.TestSetupName by t.Group into test
select new TreeViewChannels
{
Name = test.Key,
Groups = new ObservableCollection<TestGroup>(from t in list
where t.Group == test.Key
group t.Group by t.SubGroup into g
select new TestGroup
{
TestName = test.Key,
DisplayName = g.Key + " [ " + list.Count(ch => ch.Group == test.Key && ch.SubGroup == g.Key) + " Channels]",
Path = test.Key + "|" + g.Key + " [ " + list.Count(ch => ch.Group == test.Key && ch.SubGroup == g.Key) + " Channels]",
Name = g.Key.Replace(graphChannels, string.Empty),
IsGraph = g.Key.StartsWith("Graph"),
Channels = new ObservableCollection<ITestChannel>(list.Where(ch => ch.Group == test.Key && ch.SubGroup == g.Key).OrderBy(ch => ch.AbsoluteDisplayOrder).ThenBy(ch => ch.Number)),
Parent = this
})
}).ToList();
foreach (var tvc in result)
{
foreach (var g in tvc.Groups)
{
g.DTSFile = $"{g.Channels[0].BinaryFilePath}\\{g.Channels[0].TestId}.dts";
}
}
return new ObservableCollection<TreeViewChannels>(result);
}
private ObservableCollection<TreeViewIds> GetTestIdsTree(ObservableCollection<TreeViewChannels> treeViewChannelsList, List<ITestSummary> summaryList)
{
if (!treeViewChannelsList.Any()) return new ObservableCollection<TreeViewIds>();
var result = new ObservableCollection<TreeViewIds>();
var orderedTreeViewChannelsList = treeViewChannelsList.OrderBy(c => c.Name);
var treeIndex = 0;
double eventLength = 0;
foreach (var testId in orderedTreeViewChannelsList)
{
var testIdEnd = testId.Name.LastIndexOf(EventNumber) - 1;
var testIdName = testId.Name.Substring(0, testIdEnd);
//See if we already have an event with this TestId
var testIdFound = false;
foreach (var element in result)
{
if ((element.Events[0].TestId == testIdName))
{
testIdFound = true;
AddEvent(testId, element, treeIndex, eventLength);
treeIndex++;
break;
}
}
if (!testIdFound)
{
var tvi = new TreeViewIds();
tvi.TreeIndex = treeIndex;
treeIndex++;
var numEvents = orderedTreeViewChannelsList.Count(n => (n.Name.LastIndexOf(EventNumber) - 1 == testIdName.Length) && n.Name.StartsWith(testIdName));
tvi.Name = $"{testIdName} ({numEvents} events)";
//This is a new TestId, so re-calculate the event length
eventLength = CalculateEventLength(testIdName, summaryList);
AddEvent(testId, tvi, treeIndex, eventLength);
treeIndex++;
result.Add(tvi);
tvi.IsExpanded = false;
}
}
return new ObservableCollection<TreeViewIds>(result);
}
private static double CalculateEventLength(string testIdName, List<ITestSummary> summaryList)
{
double eventLength = 0.0D;
try
{
var testMetaData = summaryList.Where(t => t.Id.StartsWith(testIdName));
if (null == testMetaData) { return eventLength; }
var meta = testMetaData.FirstOrDefault();
if (null == meta ||
null == meta.TestMetadata ||
null == meta.TestMetadata.TestRun ||
null == meta.TestMetadata.TestRun.Modules ||
0 == meta.TestMetadata.TestRun.Modules.Count) { return eventLength; }
var module = testMetaData.FirstOrDefault().TestMetadata.TestRun.Modules[0];
double numberOfSamplesStr = module.NumberOfSamples;
double samplesPerSecondStr = module.SampleRateHz;
if (samplesPerSecondStr.Equals(0D)) { return eventLength; }
eventLength = Convert.ToDouble(numberOfSamplesStr) / Convert.ToDouble(samplesPerSecondStr);
}
catch( Exception ex)
{
APILogger.Log(ex);
}
return eventLength;
}
private static string ParseTestSetupName(string name)
{
var result = string.Empty;
var splitUpName = name.Split(' ');
var index = 0;
foreach (var word in splitUpName)
{
if (word == "ROI" || word == "ALL")
{
result = splitUpName[index - 1]; //It's the one before ROI or ALL
}
index++;
}
return result;
}
private string ParseROIOrAll(string name)
{
var result = string.Empty;
var splitUpName = name.Split(' ');
foreach (var word in splitUpName)
{
if (word == "ROI" || word == "ALL")
{
result = word;
break;
}
}
return result;
}
private static string ParseTestId(string name)
{
var result = string.Empty;
var testIdLength = name.IndexOf(Constants.EventNumber);
result = name.Substring(0, testIdLength);
return result;
}
private void AddEvent(TreeViewChannels testId, TreeViewIds tvi, int treeIndex, double eventLength)
{
foreach (var group in testId.Groups)
{
var e = new TestEvent();
e.TreeIndex = treeIndex;
var eventNumberStart = testId.Name.IndexOf(EventNumber);
var actualEventNumberStart = eventNumberStart + EventNumber.Length + 1;
var actualEventNumberEnd = 0;
actualEventNumberEnd = testId.Name.IndexOf(' ', actualEventNumberStart); //Look for space after "Event Number 0001" (TSR AIR Go)
var actualEventNumberLength = actualEventNumberEnd - actualEventNumberStart;
var eventLengthStr = new DateTime(TimeSpan.FromSeconds(eventLength).Ticks).ToString("HH:mm:ss.fff");
e.Name = $"{testId.Name.Substring(eventNumberStart, EventNumber.Length + 1 + actualEventNumberLength)} {eventLengthStr}";
e.TestId = ParseTestId(testId.Name);
e.TestSetupName = ParseTestSetupName(testId.Name);
e.DataType = ParseROIOrAll(testId.Name);
var roiSuffixString = string.Empty;
e.TestItem = $"{e.TestSetupName}:{ e.TestId}:({e.DataType}){roiSuffixString}";
e.DTSFile = group.DTSFile;
e.IsExpanded = false;
tvi.Events.Add(e);
}
}
#region Commands
#endregion Commands
}
}