using GalaSoft.MvvmLight.Ioc; using RealTimeGraphEx.Controllers; using RealTimeGraphEx.DataSeries; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Media; using Tango.Core.Commands; using Tango.Integration.Observables; using Tango.MachineStudio.Common.Controls; using Tango.MachineStudio.Common.Notifications; using Tango.MachineStudio.Common.StudioApplication; using Tango.SharedUI; namespace Tango.MachineStudio.Developer.ViewModels { /// /// Represents the developer module main view, view model. /// /// public class MainViewVM : ViewModel { private INotificationProvider _notification; #region Properties /// /// Gets or sets the application manager. /// public IStudioApplicationManager ApplicationManager { get; set; } /// /// Gets or sets observable entites database the adapter. /// public ObservablesEntitiesAdapter Adapter { get; set; } protected Machine _selectedMachine; /// /// Gets or sets the selected machine. /// public Machine SelectedMachine { get { return _selectedMachine; } set { _selectedMachine = value; OnMachineChanged(); RaisePropertyChangedAuto(); InvalidateRelayCommands(); if (_selectedMachine != null) { _selectedMachine.Saved -= SelectedMachine_Saved; _selectedMachine.Saved += SelectedMachine_Saved; } } } private List _liquidTypesRmls; /// /// Gets or sets the liquid types RMLS. /// public List LiquidTypesRmls { get { return _liquidTypesRmls; } set { _liquidTypesRmls = value; RaisePropertyChangedAuto(); } } private ProcessParametersTablesGroup _rmlProcessParametersTablesGroup; /// /// Gets or sets the RML process parameters table group (cloned). /// public ProcessParametersTablesGroup RmlProcessParametersTableGroup { get { return _rmlProcessParametersTablesGroup; } set { _rmlProcessParametersTablesGroup = value; RaisePropertyChangedAuto(); OnProcessParametersTableGroupChanged(); } } private ObservableCollection _groupsHistory; /// /// Gets or sets the RML process parameters groups history. /// public ObservableCollection GroupsHistory { get { return _groupsHistory; } set { _groupsHistory = value; RaisePropertyChangedAuto(); } } private ProcessParametersTablesGroup _selectedGroupHistory; /// /// Gets or sets the selected process parameters tables group history. /// public ProcessParametersTablesGroup SelectedGroupHistory { get { return _selectedGroupHistory; } set { _selectedGroupHistory = value; RaisePropertyChangedAuto(); OnSelectedGroupHistoryChanged(); } } private ProcessParametersTable _selectedProcessParametersTable; /// /// Gets or sets the selected process parameters table. /// public ProcessParametersTable SelectedProcessParametersTable { get { return _selectedProcessParametersTable; } set { _selectedProcessParametersTable = value; RaisePropertyChangedAuto(); } } private Job _selectedJob; /// /// Gets or sets the selected machine job. /// public Job SelectedJob { get { return _selectedJob; } set { _selectedJob = value; RaisePropertyChangedAuto(); OnSelectedJobChanged(); } } private Segment _selectedSegment; /// /// Gets or sets the job selected segment. /// public Segment SelectedSegment { get { return _selectedSegment; } set { _selectedSegment = value; RaisePropertyChangedAuto(); OnSelectedSegmentChanged(); } } private BrushStop _selectedBrushStop; /// /// Gets or sets the selected segment selected brush stop. /// public BrushStop SelectedBrushStop { get { return _selectedBrushStop; } set { _selectedBrushStop = value; RaisePropertyChangedAuto(); } } private Rml _selectedRML; /// /// Gets or sets the selected RML. /// public Rml SelectedRML { get { return _selectedRML; } set { _selectedRML = value; InvalidateLiquidFactorsAndProcessTables(); RaisePropertyChangedAuto(); InvalidateRelayCommands(); } } private bool _isSideBarOpened; /// /// Gets or sets a value indicating whether the configuration panels are opened. /// public bool IsSideBarOpened { get { return _isSideBarOpened; } set { _isSideBarOpened = value; RaisePropertyChangedAuto(); } } private ObservableCollection _availableSensors; /// /// Gets or sets the available sensors. /// public ObservableCollection AvailableSensors { get { return _availableSensors; } set { _availableSensors = value; RaisePropertyChangedAuto(); } } private ObservableCollection _graphs; /// /// Gets or sets the collection of displayed graph controls. /// public ObservableCollection Graphs { get { return _graphs; } set { _graphs = value; RaisePropertyChangedAuto(); } } private TimeSpan _estimatedDuration; /// /// Gets or sets the estimated duration for the selected job. /// public TimeSpan EstimatedDuration { get { return _estimatedDuration; } set { _estimatedDuration = value; RaisePropertyChangedAuto(); } } #endregion #region Commands /// /// Gets or sets the edit machine command. /// public RelayCommand EditMachineCommand { get; set; } /// /// Gets or sets the edit RML command. /// public RelayCommand EditRMLCommand { get; set; } /// /// Gets or sets the toggle side bar command. /// public RelayCommand ToggleSideBarCommand { get; set; } /// /// Gets or sets the save process parameters command. /// public RelayCommand SaveProcessParametersCommand { get; set; } /// /// Gets or sets the save liquid factors command. /// public RelayCommand SaveLiquidFactorsCommand { get; set; } /// /// Gets or sets the add segment command. /// public RelayCommand AddSegmentCommand { get; set; } /// /// Gets or sets the remove segment command. /// public RelayCommand RemoveSegmentCommand { get; set; } /// /// Gets or sets the add job command. /// public RelayCommand AddJobCommand { get; set; } /// /// Gets or sets the remove job command. /// public RelayCommand RemoveJobCommand { get; set; } /// /// Gets or sets the add brush stop command. /// public RelayCommand AddBrushStopCommand { get; set; } /// /// Gets or sets the remove brush stop command. /// public RelayCommand RemoveBrushStopCommand { get; set; } #endregion #region Constructors /// /// Initializes a new instance of the class. /// public MainViewVM() { IsSideBarOpened = true; if (!this.DesignMode) { Adapter = ObservablesEntitiesAdapter.Instance; AvailableSensors = Adapter.Sensors.ToObservableCollection(); } Graphs = new ObservableCollection(); } /// /// Initializes a new instance of the class. /// /// The application manager. /// The notification provider. [PreferredConstructor] public MainViewVM(IStudioApplicationManager applicationManager, INotificationProvider notificationProvider) : this() { _notification = notificationProvider; EditMachineCommand = new RelayCommand(EditMachine, (x) => SelectedMachine != null); ApplicationManager = applicationManager; EditRMLCommand = new RelayCommand(EditRML, (x) => SelectedRML != null); ToggleSideBarCommand = new RelayCommand(() => IsSideBarOpened = !IsSideBarOpened); SaveProcessParametersCommand = new RelayCommand(SaveProcessParameters); SaveLiquidFactorsCommand = new RelayCommand(SaveLiquidFactors); AddSegmentCommand = new RelayCommand(AddSegment); RemoveSegmentCommand = new RelayCommand(RemoveSegment); AddJobCommand = new RelayCommand(AddJob); RemoveJobCommand = new RelayCommand(RemoveJob); AddBrushStopCommand = new RelayCommand(AddBrushStop); RemoveBrushStopCommand = new RelayCommand(RemoveBrushStop); } #endregion #region Event Handlers /// /// Handles the Saved event of the SelectedMachine. /// /// The source of the event. /// The instance containing the event data. private void SelectedMachine_Saved(object sender, EventArgs e) { InvalidateLiquidFactorsAndProcessTables(); } private void SelectedJob_LengthChanged(object sender, EventArgs e) { UpdateEstimatedDuration(); } private void SelectedProcessParametersTable_DyeingSpeedChanged(object sender, EventArgs e) { UpdateEstimatedDuration(); } #endregion #region Virtual Methods /// /// Called when the process parameters table group has been changed /// /// private void OnProcessParametersTableGroupChanged() { if (RmlProcessParametersTableGroup != null && RmlProcessParametersTableGroup.ProcessParametersTables.Count > 0) { SelectedProcessParametersTable = RmlProcessParametersTableGroup.ProcessParametersTables.First(); SelectedProcessParametersTable.DyeingSpeedChanged -= SelectedProcessParametersTable_DyeingSpeedChanged; SelectedProcessParametersTable.DyeingSpeedChanged += SelectedProcessParametersTable_DyeingSpeedChanged; } UpdateEstimatedDuration(); } /// /// Called when the selected segment has been changed /// protected virtual void OnSelectedSegmentChanged() { if (SelectedSegment != null) { SetSegmentBrushStopsLiquidVolumes(SelectedSegment); SelectedBrushStop = SelectedSegment.BrushStops.FirstOrDefault(); } } /// /// Called when the selected job has been changed. /// protected virtual void OnSelectedJobChanged() { if (SelectedJob != null) { SelectedSegment = SelectedJob.Segments.FirstOrDefault(); SelectedJob.LengthChanged -= SelectedJob_LengthChanged; SelectedJob.LengthChanged += SelectedJob_LengthChanged; UpdateEstimatedDuration(); } } /// /// Called when the selected group history has been changed /// protected virtual void OnSelectedGroupHistoryChanged() { if (SelectedGroupHistory != null) { RmlProcessParametersTableGroup = SelectedGroupHistory.CloneGroup(); } } /// /// Called when the machine has been changed /// protected virtual void OnMachineChanged() { InvalidateLiquidFactorsAndProcessTables(); } #endregion #region Private Methods private void UpdateEstimatedDuration() { if (SelectedJob != null && SelectedProcessParametersTable != null) { EstimatedDuration = TimeSpan.FromSeconds(SelectedJob.Length / (SelectedProcessParametersTable.DyeingSpeed / 100d)); } } private void SetSegmentBrushStopsLiquidVolumes(Segment segment) { if (!DesignMode) { foreach (var stop in segment.BrushStops) { stop.SetLiquidVolumes(SelectedMachine.Configuration, SelectedRML); } } } /// /// Saves the liquid factors. /// private async void SaveLiquidFactors() { if (SelectedRML != null) { using (_notification.PushTaskItem("Saving Liquid Factors...")) { await SelectedRML.SaveAsync(); InvalidateLiquidFactorsAndProcessTables(); } } } /// /// Navigates to the DB Module in order to edit the selected RML. /// private void EditRML() { ApplicationManager.RequestModule("Data Base", SelectedRML); } /// /// Navigates to the Machine Designer Module in order to edit the selected machine. /// private void EditMachine() { ApplicationManager.RequestModule("Machine Designer", SelectedMachine); } /// /// Saves the process parameters group. /// private async void SaveProcessParameters() { var response = _notification.ShowTextInput("Enter Group Name", "Group Name"); if (response == null) return; using (_notification.PushTaskItem("Saving Parameters Group...")) { ProcessParametersTablesGroup group = new ProcessParametersTablesGroup(); List tables = new List(); foreach (var table in RmlProcessParametersTableGroup.ProcessParametersTables) { var newTable = table.CloneEntity(); newTable.ProcessParametersTablesGroup = group; tables.Add(newTable); } group.Active = true; group.ProcessParametersTables = tables.ToObservableCollection(); group.Rml = SelectedRML; group.Name = response; group.SaveDate = DateTime.UtcNow; foreach (var g in SelectedRML.ProcessParametersTablesGroups) { g.Active = false; } //String machineGuid = SelectedMachine.Guid; //String rmlGuid = SelectedRML.Guid; SelectedRML.ProcessParametersTablesGroups.Add(group); await SelectedRML.SaveAsync(); //SelectedMachine = Adapter.Machines.SingleOrDefault(x => x.Guid == machineGuid); //SelectedRML = Adapter.Rmls.SingleOrDefault(x => x.Guid == rmlGuid); InvalidateLiquidFactorsAndProcessTables(); } } /// /// Invalidates the liquid factors and process parameters tables. /// private void InvalidateLiquidFactorsAndProcessTables() { if (SelectedRML != null && SelectedMachine != null) { LiquidTypesRmls = SelectedMachine.Configuration.IdsPacks.OrderBy(x => x.PackIndex).Select(x => x.LiquidType).SelectMany(x => x.LiquidTypesRmls).Where(x => x.Rml.Guid == SelectedRML.Guid).ToList(); RmlProcessParametersTableGroup = SelectedRML.ProcessParametersTablesGroups.SingleOrDefault(x => x.Active); if (RmlProcessParametersTableGroup != null) { RmlProcessParametersTableGroup = RmlProcessParametersTableGroup.CloneGroup(); RmlProcessParametersTableGroup.ProcessParametersTables = RmlProcessParametersTableGroup.ProcessParametersTables.OrderBy(x => x.TableIndex).ToObservableCollection(); } GroupsHistory = SelectedRML.ProcessParametersTablesGroups.OrderByDescending(x => x.SaveDate).OrderBy(x => !x.Active).ToObservableCollection(); } } /// /// Removes the selected segment. /// private void RemoveSegment() { if (SelectedJob != null && SelectedSegment != null) { SelectedSegment.DefferedDelete(); SelectedJob.Segments.Remove(SelectedSegment); } } /// /// Adds a new segment. /// private void AddSegment() { if (SelectedJob != null) { Segment seg = new Segment(); seg.Name = "Untitled Segment"; seg.Length = 1; SelectedJob.Segments.Add(seg); SelectedSegment = seg; AddBrushStop(); } } /// /// Removes the selected job. /// private void RemoveJob() { if (SelectedMachine != null && SelectedJob != null) { SelectedJob.Delete(); SelectedMachine.Jobs.Remove(SelectedJob); } } /// /// Adds a new job to the selected machine. /// private void AddJob() { if (SelectedMachine != null) { SelectedMachine.Jobs.Add(new Job() { Name = "Untitled Job", CreationDate = DateTime.UtcNow, }); } } /// /// Removes the selected brush stop. /// private void RemoveBrushStop() { if (SelectedBrushStop != null && SelectedSegment != null) { SelectedSegment.BrushStops.Remove(SelectedBrushStop); } } /// /// Adds a new brush stop to the selected segment. /// private void AddBrushStop() { if (SelectedSegment != null) { var stop = new BrushStop(); stop.ColorSpace = Adapter.ColorSpaces.FirstOrDefault(); stop.Color = Colors.Black; stop.SetLiquidVolumes(SelectedMachine.Configuration, SelectedRML); SelectedSegment.BrushStops.Add(stop); } } #endregion #region Public Events /// /// Add sensor graph from available sensors to displayed graphs. /// /// The sensor. public void OnDropAvailableSensor(Sensor sensor) { if (Graphs.Count < 8) { IRealTimeGraph graphControl = null; if (!sensor.MultiChannel) { graphControl = new RealTimeGraphControl(); } else { graphControl = new RealTimeGraphMultiControl(); GraphMultiController controller = new GraphMultiController(); for (int i = 0; i < sensor.ChannelCount; i++) { controller.AddSeries(new DataYSeries() { Name = sensor.Description.First().ToString() + (i + 1), UseFillAndStroke = true, Stroke = new SolidColorBrush(Core.Helpers.ColorHelper.GetRandomColor()) }); } graphControl.Controller = controller; } graphControl.Tag = sensor; graphControl.SensorName = sensor.Description; graphControl.SensorUnits = sensor.Units; graphControl.InnerGraph.Minimum = sensor.Min; graphControl.InnerGraph.Maximum = sensor.Max; graphControl.InnerGraph.MaxPoints = Common.Helpers.GraphsHelper.GetMaxPoints(sensor.PointsPerFrame); graphControl.GraphRemoveButtonPressed += (sender, __) => { RemoveGraph(sender as IRealTimeGraph); }; Graphs.Add(graphControl); AvailableSensors.Remove(sensor); } else { _notification.ShowInfo("The maximum number of real-time graphs is eight. Please remove a graph to add another."); } } /// /// Switch the brush stop position in the segment. /// /// The dragged stop. /// The dropped stop. public void OnDropBrushStop(BrushStop draggedStop, BrushStop droppedStop) { int tmpIndex = draggedStop.StopIndex; draggedStop.StopIndex = droppedStop.StopIndex; droppedStop.StopIndex = tmpIndex; SelectedSegment.BrushStops.Swap(draggedStop, droppedStop); } /// /// Removes the graph. /// /// The graph. public void RemoveGraph(IRealTimeGraph graph) { Graphs.Remove(graph); AvailableSensors.Insert(0, graph.Tag as Sensor); } #endregion } }