833 lines
36 KiB
C#
833 lines
36 KiB
C#
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.Collections.ObjectModel;
|
|||
|
|
using System.Collections.Specialized;
|
|||
|
|
using System.ComponentModel;
|
|||
|
|
using System.IO;
|
|||
|
|
using System.Linq;
|
|||
|
|
using System.Threading.Tasks;
|
|||
|
|
using System.Windows.Media;
|
|||
|
|
using DTS.Common.Base;
|
|||
|
|
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.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 GraphMainViewModel : BaseViewModel<IGraphMainViewModel>, IGraphMainViewModel
|
|||
|
|
{
|
|||
|
|
public IFilterView FilterView { get; private set; }
|
|||
|
|
public IGraphMainView View { get; set; }
|
|||
|
|
public IBaseViewModel Parent { 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 GraphMainViewModel.
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="view">The GraphMainView 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 GraphMainViewModel(IGraphMainView 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 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>();
|
|||
|
|
_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;
|
|||
|
|
var list = arg?.SummaryList;
|
|||
|
|
testSummaries = list;
|
|||
|
|
CleanSelection(); //clean every time, otherwise channels weren't being removed on test deselection
|
|||
|
|
|
|||
|
|
var total = 0;
|
|||
|
|
if (list != null && list.Any())
|
|||
|
|
{
|
|||
|
|
foreach (var l in list)
|
|||
|
|
{
|
|||
|
|
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 (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);
|
|||
|
|
|
|||
|
|
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<GraphChannelsReadCompletedNotification>().Subscribe(OnReadCompletedNotification); // commented out: was noted "It does not work"
|
|||
|
|
_eventAggregator.GetEvent<TestModificationChangedEvent>().Subscribe(OnTestModificationsChanged);
|
|||
|
|
_eventAggregator.GetEvent<CalibrationBehaviorSettingChangedEvent>().Subscribe(OnCalibrationBehaviorSettingChanged);
|
|||
|
|
_eventAggregator.GetEvent<CalibrationBehaviorSettableInViewerChangedEvent>().Subscribe(OnCalibrationBehaviorSettableInViewerChanged);
|
|||
|
|
_eventAggregator.GetEvent<ChannelCodesViewChangedEvent>().Subscribe(OnChannelCodesViewChangedEvent);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
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)
|
|||
|
|
{
|
|||
|
|
FilteredChannelList = string.IsNullOrEmpty(args.Param) ? new ObservableCollection<ITestChannel>(ChannelList)
|
|||
|
|
: new ObservableCollection<ITestChannel>((from x in ChannelList where x.ChannelDisplayName.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>
|
|||
|
|
/// 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 groupName)
|
|||
|
|
{
|
|||
|
|
foreach (var test in TestChannelsTree)
|
|||
|
|
{
|
|||
|
|
foreach (var group in test.Groups)
|
|||
|
|
{
|
|||
|
|
if (!string.IsNullOrEmpty(groupName) && group.Name == groupName) continue;
|
|||
|
|
|
|||
|
|
group.IsSelected = false;
|
|||
|
|
foreach (var channel in group.Channels)
|
|||
|
|
{
|
|||
|
|
if (channel.IsLocked) continue;
|
|||
|
|
channel.CanSelectChannel = true;
|
|||
|
|
channel.ChannelColor = Colors.Transparent;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#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
|
|||
|
|
|
|||
|
|
#endregion Add Selected/Locked Channel
|
|||
|
|
|
|||
|
|
#region ContextRegion
|
|||
|
|
|
|||
|
|
public object ContextGraphMainRegion
|
|||
|
|
{
|
|||
|
|
get => ((GraphMainView)View).GraphMainRegion.DataContext;
|
|||
|
|
set { ((GraphMainView)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<ITestChannel> _selectedChannelList = new List<ITestChannel>();
|
|||
|
|
|
|||
|
|
public List<ITestChannel> SelectedChannelList
|
|||
|
|
{
|
|||
|
|
get => _selectedChannelList;
|
|||
|
|
set { _selectedChannelList = value; OnPropertyChanged("SelectedChannelList"); }
|
|||
|
|
}
|
|||
|
|
#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"); }
|
|||
|
|
}
|
|||
|
|
#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();
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
return new ObservableCollection<TreeViewChannels>(result);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#region Commands
|
|||
|
|
|
|||
|
|
#endregion Commands
|
|||
|
|
}
|
|||
|
|
}
|