aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio
diff options
context:
space:
mode:
authorAvi Levkovich <avi@twine-s.com>2020-08-25 10:08:01 +0300
committerAvi Levkovich <avi@twine-s.com>2020-08-25 10:08:01 +0300
commit338edba081dba2a2aefb634811be1cc84ec93d64 (patch)
tree0021538796c254a8eab8527e8461a2e831e68c1c /Software/Visual_Studio
parent49ddda1cc22d6cbb72f499b37e5db32c95252dfa (diff)
downloadTango-338edba081dba2a2aefb634811be1cc84ec93d64.tar.gz
Tango-338edba081dba2a2aefb634811be1cc84ec93d64.zip
merge
Diffstat (limited to 'Software/Visual_Studio')
-rw-r--r--Software/Visual_Studio/Advanced Installer Projects/FSE Installer.aip87
-rw-r--r--Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Controls/WebAppPropertiesControl.xaml.cs11
-rw-r--r--Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/ColorCalibrator.cpp4
-rw-r--r--Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/ColorConverter.cpp1861
-rw-r--r--Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/ColorConverter.h83
-rw-r--r--Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Tango.ColorLib_v4.vcxproj6
-rw-r--r--Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Tango.ColorLib_v4.vcxproj.filters18
-rw-r--r--Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/CT_Header.cpp83
-rw-r--r--Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/CT_Header.h57
-rw-r--r--Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/ColorTable.cpp645
-rw-r--r--Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/ColorTable.h76
-rw-r--r--Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/Gradient.cpp35
-rw-r--r--Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/Gradient.h37
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsViewVM.cs35
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/diagnostics.tdp2
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Controls/RemoteDesktopControl.xaml2
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/RemoteDesktopView.xaml7
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Content/VersionHistory/VersionHistory.aml33
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Content/VersionHistory/v1.0.0.0.aml28
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Content/Welcome.aml111
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/ContentLayout.content8
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Help/proc-doc.chmbin0 -> 212099 bytes
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Help/proc-doc.chwbin0 -> 45575 bytes
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Tango.FSE.Procedures.Documentation.shfbproj229
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/icons/Help.pngbin0 -> 4942 bytes
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/icons/machine_48px.pngbin0 -> 3171 bytes
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ArrayParsingStyle.cs10
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/BreakPointRequestEventArgs.cs31
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Contracts/IProcedureDesignerView.cs9
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Controls/ObjectInTreeView.xaml27
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Controls/ObjectInTreeView.xaml.cs50
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Controls/TreeNode.cs98
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/DebugNode.cs256
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Dialogs/BreakPointValueDialogView.xaml24
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Dialogs/BreakPointValueDialogView.xaml.cs28
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Dialogs/BreakPointValueDialogViewVM.cs60
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/AddResult/Program.cs91
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/Connection/Program.cs38
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/Csv/Program.cs63
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/Diagnostics/Program.cs44
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/RequestUserInputFor/Program.cs48
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/Send/Program.cs47
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/SendContinuous/Program.cs66
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/Sql/Program.cs78
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ExtensionMethods/TreeViewExtensions.cs40
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Helpers/ProcedureExceptionHelper.cs36
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/IDialogController.cs17
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/IProcedureContext.cs458
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Navigation/RunProcedureNavigationObject.cs14
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ProcedureContext.cs74
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Resources/main_template.csx1
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Result.cs14
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ResultType.cs12
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/SqlResult.cs19
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Tango.FSE.Procedures.csproj37
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Themes/Generic.xaml221
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/UserInput.cs11
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ViewModels/ProcedureDesignerViewVM.cs294
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ViewModels/ProcedureRunnerViewVM.cs86
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Views/ProcedureDesignerView.xaml145
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Views/ProcedureDesignerView.xaml.cs126
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/ApplicationUpgradeGeneratedViewVM.cs5
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/FirmwareUpgradeGeneratedViewVM.cs46
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/ApplicationUpgradeGeneratedView.xaml14
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeGeneratedView.xaml10
-rw-r--r--Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeView.xaml2
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/BugReporting/ApplicationStartedAfterCrashException.cs16
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/Connection/IMachineProvider.cs3
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/Connection/MachineConnectionTypes.cs19
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/Diagnostics/DiagnosticsPackage.cs35
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/FSEApplication/IFSEApplicationManager.cs5
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/FSESettings.cs12
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs7
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/FileAssociation/FileAssociationPackage.cs14
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/FileAssociation/IFileAssociationProvider.cs14
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/FileSystem/IFileSystemProvider.cs3
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/Helpers/LogsHelper.cs24
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/Navigation/INavigationManager.cs5
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/SQL/IRemoteSqlProvider.cs22
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/SQL/RemoteSqlCommand.cs25
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/SQL/RemoteSqlCommandMode.cs10
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/SQL/RemoteSqlCommandResult.cs50
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj8
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml.cs106
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/BugReporting/DefaultBugReporter.cs2
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs5
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionLostViewVM.cs11
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineWaitForConnectionView.xaml2
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineWaitForConnectionViewVM.cs20
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/FSEApplication/DefaultFSEApplicationManager.cs20
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/FileAssociation/DefaultFileAssociationProvider.cs136
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs14
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Navigation/DefaultNavigationManager.cs10
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/LogViewerPane.xaml98
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/LogViewerPaneVM.cs8
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/MachineConnectionPaneVM.cs41
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Properties/AssemblyInfo.cs2
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/SQL/DefaultRemoteSqlProvider.cs2
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj4
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/Tiles/RemoteJob/RemoteJobTile.cs7
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs4
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs8
-rw-r--r--Software/Visual_Studio/FSE/Tango.FSE.UI/packages.config1
-rw-r--r--Software/Visual_Studio/Installers/Sandcastle/SHFBInstaller_v2020.3.6.0.zipbin0 -> 48579276 bytes
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/Views/MainView.xaml31
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Tango.MachineStudio.ColorCapture.csproj4
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/JobView.xaml2
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/MachineJobSelectionView.xaml2
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.HardwareDesigner/Views/MainView.xaml7
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/MainViewVM.cs3
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlsView.xaml2
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Tango.MachineStudio.Statistics.csproj1
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/JobRunsViewVM.cs45
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/JobRunsView.xaml86
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/JobRunsView.xaml.cs17
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Converters/RoleEnumToVisibleConverter.cs (renamed from Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/HeadCleaningConverter.cs)15
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Tango.MachineStudio.UsersAndRoles.csproj4
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Views/UserManagementView.xaml6
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Resources/MaterialDesign.xaml143
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml.cs25
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Images/remote_connections.pngbin0 -> 4186 bytes
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Tango.PPC.Technician.csproj11
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModelLocator.cs12
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/LoggingViewVM.cs8
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/RemoteConnectionsViewVM.cs64
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/CatalogView.xaml12
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/MainView.xaml1
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/RemoteConnectionsView.xaml88
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/RemoteConnectionsView.xaml.cs28
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Helpers/LogsHelper.cs24
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Insights/DefaultInsightsService.cs45
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Insights/IInsightsService.cs13
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PPCPublisher.cs32
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishOptions.cs3
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Resources/Merged.xaml1
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj7
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Web/LatestVersionResponse.cs1
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Publisher.UI/MainWindow.xaml10
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Publisher.UI/MainWindowVM.cs26
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Shared/SQL/RemoteSqlColumn.cs28
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Shared/SQL/RemoteSqlColumnCollection.cs31
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Shared/SQL/RemoteSqlDataSet.cs35
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Shared/SQL/RemoteSqlRow.cs55
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Shared/Tango.PPC.Shared.csproj4
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/App.xaml.cs25
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs3
-rw-r--r--Software/Visual_Studio/Project Templates/Tango FSE Procedure Example.zipbin0 -> 6123 bytes
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Project.cs178
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Core/BreakPoint.cs14
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Core/ScriptBreakPoint.cs23
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Core/ScriptBreakPointSymbol.cs16
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Core/Tango.Scripting.Core.csproj3
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Editors/BreakPointSymbolPressedEventArgs.cs16
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Editing/BreakPointMargin.cs285
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/Resources/CSharp-Mode.xshd2
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Images/break_point_arrow.pngbin0 -> 453 bytes
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/HideIntellisenseAttribute.cs12
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/KnownType.cs11
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ScriptEditor.cs302
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Tango.Scripting.Editors.csproj6
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Tango.Scripting.Editors_di35u2uj_wpftmp.csproj628
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Editors/TextEditor.cs2343
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting/Parsing/ScriptParser.cs23
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting/Parsing/ScriptSymbol.cs4
-rw-r--r--Software/Visual_Studio/Tango.BL/Entities/HardwareVersion.cs9
-rw-r--r--Software/Visual_Studio/Tango.ColorLib.GradientTest.CLI/Program.cs41
-rw-r--r--Software/Visual_Studio/Tango.Insights/InsightsFrame.cs64
-rw-r--r--Software/Visual_Studio/Tango.Insights/InsightsHelper.cs85
-rw-r--r--Software/Visual_Studio/Tango.Insights/InsightsListener.cs121
-rw-r--r--Software/Visual_Studio/Tango.Insights/InsightsManager.cs81
-rw-r--r--Software/Visual_Studio/Tango.Insights/Properties/AssemblyInfo.cs7
-rw-r--r--Software/Visual_Studio/Tango.Insights/Tango.Insights.csproj80
-rw-r--r--Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeReceiver.cs12
-rw-r--r--Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeService.cs18
-rw-r--r--Software/Visual_Studio/Tango.Integration/ExternalBridge/IExternalBridgeService.cs6
-rw-r--r--Software/Visual_Studio/Tango.Logging/GlobalExceptionTrapper.cs50
-rw-r--r--Software/Visual_Studio/Tango.Logging/LogManager.cs9
-rw-r--r--Software/Visual_Studio/Tango.Logging/LogSafe.cs39
-rw-r--r--Software/Visual_Studio/Tango.Logging/Tango.Logging.csproj3
-rw-r--r--Software/Visual_Studio/Tango.PMR/Common/ErrorCode.cs19
-rw-r--r--Software/Visual_Studio/Tango.PMR/Insights/InsightsMonitors.cs2936
-rw-r--r--Software/Visual_Studio/Tango.PMR/Tango.PMR.csproj3
-rw-r--r--Software/Visual_Studio/Tango.SharedUI/Components/SelectedObject.cs6
-rw-r--r--Software/Visual_Studio/Tango.SharedUI/Controls/AllSelectedCheckboxList.cs144
-rw-r--r--Software/Visual_Studio/Tango.SharedUI/Controls/PopupWithKeyboardFocus.cs42
-rw-r--r--Software/Visual_Studio/Tango.SharedUI/Controls/SearchComboBox.cs317
-rw-r--r--Software/Visual_Studio/Tango.SharedUI/Tango.SharedUI.csproj2
-rw-r--r--Software/Visual_Studio/Tango.sln45
-rw-r--r--Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analysis/AnalyzerResultBase.cs2
-rw-r--r--Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analysis/IAnalyzer.cs2
-rw-r--r--Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analysis/IAnalyzerResult.cs4
-rw-r--r--Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/DynamicSealingAnalyzer.cs2
-rw-r--r--Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/FlowAnalyser.cs34
-rw-r--r--Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/PressureBuildUpAnalyser.cs2
-rw-r--r--Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/PrimingAnalyzer.cs2
-rw-r--r--Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/SealingAnalyzer.cs2
-rw-r--r--Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/App.xaml.cs13
-rw-r--r--Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/MainWindow.xaml.cs22
-rw-r--r--Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Tango.DispenserAnalyzer.UI.csproj2
-rw-r--r--Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/ViewModels/MainWindowVM.cs146
-rw-r--r--Software/Visual_Studio/Utilities/Tango.PMRGenerator.CLI/Program.cs31
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs2
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs5
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Properties/AssemblyInfo.cs2
204 files changed, 12937 insertions, 3282 deletions
diff --git a/Software/Visual_Studio/Advanced Installer Projects/FSE Installer.aip b/Software/Visual_Studio/Advanced Installer Projects/FSE Installer.aip
index 44331055f..901fd1a05 100644
--- a/Software/Visual_Studio/Advanced Installer Projects/FSE Installer.aip
+++ b/Software/Visual_Studio/Advanced Installer Projects/FSE Installer.aip
@@ -24,10 +24,10 @@
<ROW Property="CompanyLogo" Value="blue.jpg" MultiBuildValue="DefaultBuild:twine_logo_installer_.png_1" Type="1" MsiKey="CompanyLogo"/>
<ROW Property="LogoIcon" Value="externalui.ico" MultiBuildValue="DefaultBuild:machine_full_0UZ_icon.ico_1" Type="1" MsiKey="LogoIcon"/>
<ROW Property="Manufacturer" Value="Twine Solutions LTD"/>
- <ROW Property="ProductCode" Value="1033:{C0D30B97-331F-48CE-9765-261B3B67D63B} " Type="16"/>
+ <ROW Property="ProductCode" Value="1033:{94308FC7-FF32-4E30-94C3-A22722A47325} " Type="16"/>
<ROW Property="ProductLanguage" Value="1033"/>
<ROW Property="ProductName" Value="Tango FSE"/>
- <ROW Property="ProductVersion" Value="1.0.7.0" Type="32"/>
+ <ROW Property="ProductVersion" Value="1.0.8.0" Type="32"/>
<ROW Property="RUNAPPLICATION" Value="1" Type="4"/>
<ROW Property="SecureCustomProperties" Value="OLDPRODUCTS;AI_NEWERPRODUCTFOUND;AI_SETUPEXEPATH;SETUPEXEDIR"/>
<ROW Property="UpgradeCode" Value="{0E13CB0D-89F7-465E-9F56-F1CBD6773E6E}"/>
@@ -267,7 +267,7 @@
<ROW Component="Tango.ColorPicker.dll" ComponentId="{4DC739B9-5960-4CF4-9911-BF25E7CC7308}" Directory_="APPDIR" Attributes="0" KeyPath="Tango.ColorPicker.dll"/>
<ROW Component="Tango.Console.dll" ComponentId="{EA15B4D4-5171-4747-8F7D-0D21CF8CAFD3}" Directory_="APPDIR" Attributes="0" KeyPath="Tango.Console.dll"/>
<ROW Component="Tango.Core.dll" ComponentId="{FEA537DB-7B1F-4B88-940A-9911A4D29057}" Directory_="APPDIR" Attributes="0" KeyPath="Tango.Core.dll"/>
- <ROW Component="Tango.DAL.Remote.dll" ComponentId="{97065CAF-4EA6-4A2A-B379-98C60649AD7C}" Directory_="APPDIR" Attributes="0" KeyPath="Tango.DAL.Remote.dll"/>
+ <ROW Component="Tango.DAL.Remote.dll" ComponentId="{62700DCA-5334-45BB-9B3F-1E60D8E1CB51}" Directory_="APPDIR" Attributes="0" KeyPath="Tango.DAL.Remote.dll"/>
<ROW Component="Tango.Documents.dll" ComponentId="{FB9E5160-6481-4879-AFC6-89C3D7E21ED6}" Directory_="APPDIR" Attributes="0" KeyPath="Tango.Documents.dll"/>
<ROW Component="Tango.DragAndDrop.dll" ComponentId="{E660863F-2225-48FE-B966-E7375A48FBF1}" Directory_="APPDIR" Attributes="0" KeyPath="Tango.DragAndDrop.dll"/>
<ROW Component="Tango.Emulations.dll" ComponentId="{87B4BB2B-DA02-47A4-B738-F0D388ED5B03}" Directory_="APPDIR" Attributes="0" KeyPath="Tango.Emulations.dll"/>
@@ -310,16 +310,20 @@
<ROW Component="Z.EntityFramework.Plus.EF6.dll" ComponentId="{9813A841-45DE-422F-8CD5-41A2D4750803}" Directory_="APPDIR" Attributes="0" KeyPath="Z.EntityFramework.Plus.EF6.dll"/>
<ROW Component="Z.Expressions.Eval.dll" ComponentId="{FD15C66D-61BF-4E9D-AE0F-240D0EA1D78C}" Directory_="APPDIR" Attributes="0" KeyPath="Z.Expressions.Eval.dll"/>
<ROW Component="ZSpitz.Util.dll" ComponentId="{3476B9F6-18D9-41B1-89D8-9774E8DB91A6}" Directory_="APPDIR" Attributes="0" KeyPath="ZSpitz.Util.dll"/>
+ <ROW Component="ZetaIpc.dll" ComponentId="{4FF5B07F-434F-4E8E-A469-B0218EDE0805}" Directory_="APPDIR" Attributes="0" KeyPath="ZetaIpc.dll"/>
<ROW Component="ffmpeg.exe" ComponentId="{D6862E01-A64B-40FD-847E-A35B561EFD1D}" Directory_="APPDIR" Attributes="0" KeyPath="ffmpeg.exe"/>
<ROW Component="mscoree.dll" ComponentId="{B7304190-8E59-45C3-B972-4611DEB9DE60}" Directory_="APPDIR" Attributes="0" KeyPath="mscoree.dll"/>
<ROW Component="msvcp140d.dll" ComponentId="{6B725C2A-71DF-44D3-A761-EB3D28379956}" Directory_="APPDIR" Attributes="0" KeyPath="msvcp140d.dll"/>
<ROW Component="netstandard.dll" ComponentId="{27E9F013-8E50-4251-9C63-C53A5AA66DD1}" Directory_="APPDIR" Attributes="0" KeyPath="netstandard.dll"/>
+ <ROW Component="procdoc.chm" ComponentId="{A1ADA8CA-C7F6-4C05-BC9A-E2F821E002DC}" Directory_="APPDIR" Attributes="0" KeyPath="procdoc.chm" Type="1"/>
<ROW Component="protobufnet.dll" ComponentId="{ED37672F-F343-44FB-8FBD-F9003BD20D52}" Directory_="APPDIR" Attributes="0" KeyPath="protobufnet.dll"/>
+ <ROW Component="turbojpeg.dll" ComponentId="{D884024D-FA37-4526-90AC-37963E621CDB}" Directory_="win7x64_Dir" Attributes="256" KeyPath="turbojpeg.dll"/>
+ <ROW Component="turbojpeg.dll.meta" ComponentId="{F34DC99A-4629-4622-8221-3DDA06EEE754}" Directory_="win7x64_Dir" Attributes="0" KeyPath="turbojpeg.dll.meta" Type="0"/>
+ <ROW Component="turbojpeg.dll.meta_1" ComponentId="{0E539245-AA97-440F-BFF5-F399D510517A}" Directory_="win7x86_Dir" Attributes="0" KeyPath="turbojpeg.dll.meta_1" Type="0"/>
+ <ROW Component="turbojpeg.dll_1" ComponentId="{0B2FC31A-CCF6-4A85-B86F-1DFA98ED149D}" Directory_="win7x86_Dir" Attributes="0" KeyPath="turbojpeg.dll_1"/>
<ROW Component="ucrtbased.dll" ComponentId="{4188BB88-A714-488A-A02D-98710ACC94F5}" Directory_="APPDIR" Attributes="0" KeyPath="ucrtbased.dll"/>
<ROW Component="vcruntime140.dll" ComponentId="{078A42AF-E964-4CA3-8A9C-CBE6D0FD76AA}" Directory_="APPDIR" Attributes="0" KeyPath="vcruntime140.dll"/>
<ROW Component="vcruntime140d.dll" ComponentId="{AF42196B-67BB-4EBA-8C3A-38B9527F9775}" Directory_="APPDIR" Attributes="0" KeyPath="vcruntime140d.dll"/>
- <ROW Component="win7x64" ComponentId="{D48A5332-9CFF-49FB-B679-B019D1EB1E0E}" Directory_="win7x64_Dir" Attributes="0"/>
- <ROW Component="win7x86" ComponentId="{37DE9DBF-8269-454F-A73A-785A098EFAF6}" Directory_="win7x86_Dir" Attributes="0"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatsComponent">
<ROW Feature="D17D1EE3B5447079AEF0A1CF58498F1" Title="SQL Server Express LocalDB 2017 (required for remote upgrade)" Description="SQL Server Express LocalDB 2017 (required for TUP package generation)" Display="3" Level="1" Attributes="0"/>
@@ -649,35 +653,21 @@
<ROW File="Tango.FSE.Procedures.dll.config" Component_="Dragablz.xml" FileName="TANGOF~9.CON|Tango.FSE.Procedures.dll.config" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\Tango.FSE.Procedures.dll.config" SelfReg="false"/>
<ROW File="Tango.FSE.Procedures.pdb" Component_="Tango.FSE.Procedures.dll" FileName="TANGO~11.PDB|Tango.FSE.Procedures.pdb" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\Tango.FSE.Procedures.pdb" SelfReg="false"/>
<ROW File="Tango.FSE.Procedures.xml" Component_="Dragablz.xml" FileName="TANGOF~2.XML|Tango.FSE.Procedures.xml" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\Tango.FSE.Procedures.xml" SelfReg="false"/>
- <ROW File="Tango.DAL.Remote.dll" Component_="Tango.DAL.Remote.dll" FileName="TANGOD~1.DLL|Tango.DAL.Remote.dll" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\Tango.DAL.Remote.dll" SelfReg="false"/>
- <ROW File="Tango.DAL.Remote.dll.config" Component_="Dragablz.xml" FileName="TANGOD~1.CON|Tango.DAL.Remote.dll.config" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\Tango.DAL.Remote.dll.config" SelfReg="false"/>
- <ROW File="Tango.DAL.Remote.pdb" Component_="Tango.DAL.Remote.dll" FileName="TANGOD~1.PDB|Tango.DAL.Remote.pdb" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\Tango.DAL.Remote.pdb" SelfReg="false"/>
- <ROW File="ColorMine.pdb" Component_="ColorMine.dll" FileName="COLORM~1.PDB|ColorMine.pdb" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\ColorMine.pdb" SelfReg="false"/>
- <ROW File="ControlzEx.pdb" Component_="ControlzEx.dll" FileName="CONTRO~1.PDB|ControlzEx.pdb" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\ControlzEx.pdb" SelfReg="false"/>
- <ROW File="DocumentFormat.OpenXml.xml" Component_="Dragablz.xml" FileName="DOCUME~1.XML|DocumentFormat.OpenXml.xml" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\DocumentFormat.OpenXml.xml" SelfReg="false"/>
- <ROW File="EntityFramework.SqlServer.xml" Component_="Dragablz.xml" FileName="ENTITY~1.XML|EntityFramework.SqlServer.xml" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\EntityFramework.SqlServer.xml" SelfReg="false"/>
- <ROW File="EntityFramework.xml" Component_="Dragablz.xml" FileName="ENTITY~2.XML|EntityFramework.xml" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\EntityFramework.xml" SelfReg="false"/>
- <ROW File="LiteDB.xml" Component_="Dragablz.xml" FileName="LiteDB.xml" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\LiteDB.xml" SelfReg="false"/>
- <ROW File="MahApps.Metro.pdb" Component_="MahApps.Metro.dll" FileName="MAHAPP~1.PDB|MahApps.Metro.pdb" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\MahApps.Metro.pdb" SelfReg="false"/>
- <ROW File="MahApps.Metro.xml" Component_="Dragablz.xml" FileName="MAHAPP~1.XML|MahApps.Metro.xml" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\MahApps.Metro.xml" SelfReg="false"/>
- <ROW File="MaterialDesignColors.pdb" Component_="MaterialDesignColors.dll" FileName="MATERI~1.PDB|MaterialDesignColors.pdb" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\MaterialDesignColors.pdb" SelfReg="false"/>
- <ROW File="MaterialDesignThemes.Wpf.pdb" Component_="MaterialDesignThemes.Wpf.dll" FileName="MATERI~2.PDB|MaterialDesignThemes.Wpf.pdb" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\MaterialDesignThemes.Wpf.pdb" SelfReg="false"/>
- <ROW File="MaterialDesignThemes.Wpf.xml" Component_="Dragablz.xml" FileName="MATERI~1.XML|MaterialDesignThemes.Wpf.xml" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\MaterialDesignThemes.Wpf.xml" SelfReg="false"/>
- <ROW File="Microsoft.AspNet.SignalR.Client.pdb" Component_="Microsoft.AspNet.SignalR.Client.dll" FileName="MICROS~1.PDB|Microsoft.AspNet.SignalR.Client.pdb" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\Microsoft.AspNet.SignalR.Client.pdb" SelfReg="false"/>
- <ROW File="Microsoft.AspNet.SignalR.Client.xml" Component_="Dragablz.xml" FileName="MICROS~1.XML|Microsoft.AspNet.SignalR.Client.xml" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\Microsoft.AspNet.SignalR.Client.xml" SelfReg="false"/>
<ROW File="Microsoft.Data.Edm.dll" Component_="Microsoft.Data.Edm.dll" FileName="MICROS~2.DLL|Microsoft.Data.Edm.dll" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\Microsoft.Data.Edm.dll" SelfReg="false"/>
<ROW File="Microsoft.Data.OData.dll" Component_="Microsoft.Data.OData.dll" FileName="MICRO~21.DLL|Microsoft.Data.OData.dll" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\Microsoft.Data.OData.dll" SelfReg="false"/>
<ROW File="Microsoft.Data.Services.Client.dll" Component_="Microsoft.Data.Services.Client.dll" FileName="MICRO~24.DLL|Microsoft.Data.Services.Client.dll" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\Microsoft.Data.Services.Client.dll" SelfReg="false"/>
- <ROW File="Newtonsoft.Json.xml" Component_="Dragablz.xml" FileName="NEWTON~1.XML|Newtonsoft.Json.xml" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\Newtonsoft.Json.xml" SelfReg="false"/>
- <ROW File="protobufnet.xml" Component_="Dragablz.xml" FileName="PROTOB~1.XML|protobuf-net.xml" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\protobuf-net.xml" SelfReg="false"/>
- <ROW File="RealTimeGraphX.pdb" Component_="RealTimeGraphX.dll" FileName="REALTI~1.PDB|RealTimeGraphX.pdb" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\RealTimeGraphX.pdb" SelfReg="false"/>
- <ROW File="RealTimeGraphX.WPF.pdb" Component_="RealTimeGraphX.WPF.dll" FileName="REALTI~2.PDB|RealTimeGraphX.WPF.pdb" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\RealTimeGraphX.WPF.pdb" SelfReg="false"/>
- <ROW File="System.Data.SQLite.xml" Component_="Dragablz.xml" FileName="SYSTEM~1.XML|System.Data.SQLite.xml" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\System.Data.SQLite.xml" SelfReg="false"/>
- <ROW File="System.Reactive.Core.xml" Component_="Dragablz.xml" FileName="SYSTEM~2.XML|System.Reactive.Core.xml" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\System.Reactive.Core.xml" SelfReg="false"/>
- <ROW File="System.Reactive.Interfaces.xml" Component_="Dragablz.xml" FileName="SYSTEM~3.XML|System.Reactive.Interfaces.xml" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\System.Reactive.Interfaces.xml" SelfReg="false"/>
- <ROW File="System.Reactive.Linq.xml" Component_="Dragablz.xml" FileName="SYSTEM~4.XML|System.Reactive.Linq.xml" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\System.Reactive.Linq.xml" SelfReg="false"/>
- <ROW File="System.Reactive.PlatformServices.xml" Component_="Dragablz.xml" FileName="SYSTEM~5.XML|System.Reactive.PlatformServices.xml" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\System.Reactive.PlatformServices.xml" SelfReg="false"/>
<ROW File="System.Spatial.dll" Component_="System.Spatial.dll" FileName="SYSTEM~2.DLL|System.Spatial.dll" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\System.Spatial.dll" SelfReg="false"/>
+ <ROW File="turbojpeg.dll" Component_="turbojpeg.dll" FileName="TURBOJ~1.DLL|turbojpeg.dll" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\win7-x64\turbojpeg.dll" SelfReg="false"/>
+ <ROW File="turbojpeg.dll.meta" Component_="turbojpeg.dll.meta" FileName="TURBOJ~1.MET|turbojpeg.dll.meta" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\win7-x64\turbojpeg.dll.meta" SelfReg="false"/>
+ <ROW File="turbojpeg.dll_1" Component_="turbojpeg.dll_1" FileName="TURBOJ~1.DLL|turbojpeg.dll" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\win7-x86\turbojpeg.dll" SelfReg="false"/>
+ <ROW File="turbojpeg.dll.meta_1" Component_="turbojpeg.dll.meta_1" FileName="TURBOJ~1.MET|turbojpeg.dll.meta" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\win7-x86\turbojpeg.dll.meta" SelfReg="false"/>
+ <ROW File="procdoc.chm" Component_="procdoc.chm" FileName="proc-doc.chm" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\proc-doc.chm" SelfReg="false"/>
+ <ROW File="Tango.DAL.Remote.dll" Component_="Tango.DAL.Remote.dll" FileName="TANGOD~1.DLL|Tango.DAL.Remote.dll" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\Tango.DAL.Remote.dll" SelfReg="false"/>
+ <ROW File="Tango.DAL.Remote.dll.config" Component_="Dragablz.xml" FileName="TANGOD~1.CON|Tango.DAL.Remote.dll.config" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\Tango.DAL.Remote.dll.config" SelfReg="false"/>
+ <ROW File="Tango.DAL.Remote.pdb" Component_="Tango.DAL.Remote.dll" FileName="TANGOD~1.PDB|Tango.DAL.Remote.pdb" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\Tango.DAL.Remote.pdb" SelfReg="false"/>
+ <ROW File="Tango.FSE.Common.xml" Component_="Dragablz.xml" FileName="TANGOF~1.XML|Tango.FSE.Common.xml" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\Tango.FSE.Common.xml" SelfReg="false"/>
+ <ROW File="Tango.PPC.Shared.xml" Component_="Dragablz.xml" FileName="TANGOP~1.XML|Tango.PPC.Shared.xml" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\Tango.PPC.Shared.xml" SelfReg="false"/>
+ <ROW File="ZetaIpc.dll" Component_="ZetaIpc.dll" FileName="ZetaIpc.dll" Version="65535.65535.65535.65535" Attributes="0" SourcePath="..\Build\FSE\Release\ZetaIpc.dll" SelfReg="false"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.AiRemoveFileComponent">
<ROW RemoveFile="_" Options="3"/>
@@ -689,7 +679,7 @@
<ROW Action="AI_DetectSoftware" Sequence="101"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.BuildComponent">
- <ROW BuildKey="DefaultBuild" BuildName="DefaultBuild" BuildOrder="1" BuildType="0" PackageFolder="..\Build\Installers\FSE\Release" PackageFileName="Tango FSE v1.0.2" Languages="en" InstallationType="4" CabsLocation="1" PackageType="1" FilesInsideExe="true" ExtractionFolder="[AppDataFolder][|Manufacturer]\[|ProductName] [|ProductVersion]\install" ExtUI="true" UseLargeSchema="true" ExeName="Tango FSE v1.0.7"/>
+ <ROW BuildKey="DefaultBuild" BuildName="DefaultBuild" BuildOrder="1" BuildType="0" PackageFolder="..\Build\Installers\FSE\Release" PackageFileName="Tango FSE v1.0.2" Languages="en" InstallationType="4" CabsLocation="1" PackageType="1" FilesInsideExe="true" ExtractionFolder="[AppDataFolder][|Manufacturer]\[|ProductName] [|ProductVersion]\install" ExtUI="true" UseLargeSchema="true" ExeName="Tango FSE v1.0.8"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.DictionaryComponent">
<ROW Path="&lt;AI_DICTS&gt;ui.ail"/>
@@ -776,8 +766,6 @@
<COMPONENT cid="caphyon.advinst.msicomp.MsiCreateFolderComponent">
<ROW Directory_="SHORTCUTDIR" Component_="SHORTCUTDIR" ManualDelete="false"/>
<ROW Directory_="APPDIR" Component_="APPDIR" ManualDelete="true"/>
- <ROW Directory_="win7x64_Dir" Component_="win7x64" ManualDelete="false"/>
- <ROW Directory_="win7x86_Dir" Component_="win7x86" ManualDelete="false"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiCustActComponent">
<ROW Action="AI_AiRemoveFilesCommit" Type="11777" Source="ResourceCleaner.dll" Target="OnAiRemoveFilesCommit" WithoutSeq="true"/>
@@ -822,6 +810,12 @@
<ROW Action="SET_SHORTCUTDIR" Type="307" Source="SHORTCUTDIR" Target="[ProgramMenuFolder][ProductName]"/>
<ROW Action="SET_TARGETDIR_TO_APPDIR" Type="51" Source="TARGETDIR" Target="[APPDIR]"/>
</COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiExtComponent">
+ <ROW Extension="pproj" Component_="Tango.FSE.UI.exe" ProgId_="[|Manufacturer].[|ProductName].ppro" Feature_="TangoFSE" Options="32"/>
+ <ROW Extension="tdp" Component_="Tango.FSE.UI.exe" ProgId_="[|Manufacturer].[|ProductName].tdp" Feature_="TangoFSE" Options="32"/>
+ <ROW Extension="tfp" Component_="Tango.FSE.UI.exe" ProgId_="[|Manufacturer].[|ProductName].tfp" Feature_="TangoFSE" Options="32"/>
+ <ROW Extension="tup" Component_="Tango.FSE.UI.exe" ProgId_="[|Manufacturer].[|ProductName].tup" Feature_="TangoFSE" Options="32"/>
+ </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiFeatCompsComponent">
<ROW Feature_="TangoFSE" Component_="AI_ExePath"/>
<ROW Feature_="TangoFSE" Component_="ColorMine.dll"/>
@@ -1081,15 +1075,23 @@
<ROW Feature_="TangoFSE" Component_="ffmpeg.exe"/>
<ROW Feature_="TangoFSE" Component_="Tango.CSV.dll"/>
<ROW Feature_="TangoFSE" Component_="Tango.FSE.Procedures.dll"/>
- <ROW Feature_="TangoFSE" Component_="Tango.DAL.Remote.dll"/>
<ROW Feature_="TangoFSE" Component_="Microsoft.Data.Edm.dll"/>
<ROW Feature_="TangoFSE" Component_="Microsoft.Data.OData.dll"/>
<ROW Feature_="TangoFSE" Component_="Microsoft.Data.Services.Client.dll"/>
<ROW Feature_="TangoFSE" Component_="System.Spatial.dll"/>
- <ROW Feature_="TangoFSE" Component_="win7x64"/>
- <ROW Feature_="TangoFSE" Component_="win7x86"/>
+ <ROW Feature_="TangoFSE" Component_="turbojpeg.dll"/>
+ <ROW Feature_="TangoFSE" Component_="turbojpeg.dll.meta"/>
+ <ROW Feature_="TangoFSE" Component_="turbojpeg.dll_1"/>
+ <ROW Feature_="TangoFSE" Component_="turbojpeg.dll.meta_1"/>
+ <ROW Feature_="TangoFSE" Component_="ZetaIpc.dll"/>
+ <ROW Feature_="TangoFSE" Component_="procdoc.chm"/>
+ <ROW Feature_="TangoFSE" Component_="Tango.DAL.Remote.dll"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiIconsComponent">
+ <ROW Name="ext.exe" SourcePath="..\..\Graphics\FSE\File Associations\procedure_dde.ico" Index="0"/>
+ <ROW Name="ext_1.exe" SourcePath="..\..\Graphics\FSE\File Associations\tdp_dde.ico" Index="0"/>
+ <ROW Name="ext_2.exe" SourcePath="..\..\Graphics\FSE\File Associations\tfp_dde.ico" Index="0"/>
+ <ROW Name="ext_3.exe" SourcePath="..\..\Graphics\FSE\File Associations\tup_dde.ico" Index="0"/>
<ROW Name="machine_full.exe" SourcePath="..\..\Graphics\FSE\Installer\machine_full.ico" Index="0"/>
</COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiInstExSeqComponent">
@@ -1145,6 +1147,12 @@
<ROW Condition="SETUPEXEDIR OR (REMOVE=&quot;ALL&quot;)" Description="This package can only be run from a bootstrapper." DescriptionLocId="AI.LaunchCondition.RequireBootstrapper" IsPredefined="true" Builds="DefaultBuild"/>
<ROW Condition="VersionNT" Description="[ProductName] cannot be installed on [WindowsType9XDisplay]." DescriptionLocId="AI.LaunchCondition.No9X" IsPredefined="true" Builds="DefaultBuild"/>
</COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiProgIdComponent">
+ <ROW ProgId="[|Manufacturer].[|ProductName].ppro" Description="Tango FSE Procedure" Icon_="ext.exe"/>
+ <ROW ProgId="[|Manufacturer].[|ProductName].tdp" Description="Tango FSE Diagnostics Project" Icon_="ext_1.exe"/>
+ <ROW ProgId="[|Manufacturer].[|ProductName].tfp" Description="Tango Firmware Package" Icon_="ext_2.exe"/>
+ <ROW ProgId="[|Manufacturer].[|ProductName].tup" Description="Tango Update Package" Icon_="ext_3.exe"/>
+ </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.MsiRegLocatorComponent">
<ROW Signature_="AI_EXE_PATH_CU" Root="1" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="AI_ExePath" Type="2"/>
<ROW Signature_="AI_EXE_PATH_LM" Root="2" Key="Software\Caphyon\Advanced Installer\LZMA\[ProductCode]\[ProductVersion]" Name="AI_ExePath" Type="2"/>
@@ -1168,6 +1176,13 @@
<ROW UpgradeCode="[|UpgradeCode]" VersionMin="0.0.1" VersionMax="[|ProductVersion]" Attributes="257" ActionProperty="OLDPRODUCTS"/>
<ROW UpgradeCode="[|UpgradeCode]" VersionMin="[|ProductVersion]" Attributes="2" ActionProperty="AI_NEWERPRODUCTFOUND"/>
</COMPONENT>
+ <COMPONENT cid="caphyon.advinst.msicomp.MsiVerbComponent">
+ <ROW Extension_="pproj" Component_="Tango.FSE.UI.exe" Verb="open" Sequence="0" Command="&amp;Run Procedure" Argument="-file procedure &quot;%1&quot;"/>
+ <ROW Extension_="pproj" Component_="Tango.FSE.UI.exe" Verb="open #1" Sequence="1" Command="&amp;Open in Procedure Designer" Argument="-file designer &quot;%1&quot;"/>
+ <ROW Extension_="tdp" Component_="Tango.FSE.UI.exe" Verb="open" Sequence="0" Command="&amp;Open" Argument="-file diagnostics &quot;%1&quot;"/>
+ <ROW Extension_="tfp" Component_="Tango.FSE.UI.exe" Verb="open" Sequence="0" Command="&amp;Perform Upgrade" Argument="-file tfp &quot;%1&quot;"/>
+ <ROW Extension_="tup" Component_="Tango.FSE.UI.exe" Verb="open" Sequence="0" Command="&amp;Perform Upgrade" Argument="&quot;%1&quot;"/>
+ </COMPONENT>
<COMPONENT cid="caphyon.advinst.msicomp.PreReqComponent">
<ROW PrereqKey="ActiveDirectoryAut" DisplayName="Active Directory Authentication Library for SQL Server" VersionMin="13.0.1300.275" SetupFileUrl="..\Installers\Active Directory Authentication\adalsql.msi" Location="0" ExactSize="0" Operator="1" Options="y" TargetName="adalsql.msi"/>
<ROW PrereqKey="BB9062A4604BB61146D7C9AA49D" DisplayName=".NET Framework 4.6.1 (web installer)" SetupFileUrl="http://download.microsoft.com/download/3/5/9/35980F81-60F4-4DE3-88FC-8F962B97253B/NDP461-KB3102438-Web.exe" Location="1" ExactSize="1424328" WinNTVersions="Windows XP SP3 x86, Windows Server 2003 SP2 x86, Windows Vista x86, Windows Server 2008 x86, Windows 7 RTM x86, Windows 10 version 1511 x86, Windows 10 version 1607 x86, Windows 10 version 1703 x86, Windows 10 version 1709 x86, Windows 10 version 1803 x86, Windows 10 version 1809 x86" WinNT64Versions="Windows XP SP2 x64, Windows Server 2003 SP2 x64, Windows Vista x64, Windows Server 2008 x64, Windows 7 RTM x64, Windows Server 2008 R2 RTM x64, Windows 10 version 1511 x64, Windows 10 version 1607 x64, Windows 10 version 1703 x64, Windows 10 version 1709 x64, Windows 10 version 1803 x64, Windows 10 version 1809 x64, Windows Server 2016 x64" Operator="1" NoUiComLine="/q /norestart" Options="xy" MD5="4d1bb86d0eee168e1da91a36350c1c21" TargetName=".NET Framework 4.6.1"/>
diff --git a/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Controls/WebAppPropertiesControl.xaml.cs b/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Controls/WebAppPropertiesControl.xaml.cs
index 129550d14..aab9361f8 100644
--- a/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Controls/WebAppPropertiesControl.xaml.cs
+++ b/Software/Visual_Studio/Azure/Tango.AzureUtils.UI/Controls/WebAppPropertiesControl.xaml.cs
@@ -1,6 +1,7 @@
using Microsoft.Azure.Management.AppService.Fluent;
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -99,6 +100,11 @@ namespace Tango.AzureUtils.UI.Controls
{
IsBusy = true;
+ TangoVersion = null;
+ MachineStudioVersion = null;
+ FseVersion = null;
+ MachineServiceVersion = null;
+
HostNames = app.HostNames.Select(x => x).ToList();
Settings = await app.GetMachineServiceSettingsAsync(false);
@@ -112,7 +118,10 @@ namespace Tango.AzureUtils.UI.Controls
FtpManager ftpManager = new FtpManager(azure);
MachineServiceVersion = await ftpManager.GetMachineServiceVersion(app);
}
- catch { }
+ catch (Exception ex)
+ {
+ Debug.WriteLine(ex);
+ }
finally
{
IsBusy = false;
diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/ColorCalibrator.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/ColorCalibrator.cpp
index 2f53f4ae2..3d66f2d1e 100644
--- a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/ColorCalibrator.cpp
+++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/ColorCalibrator.cpp
@@ -182,7 +182,7 @@ void Tango::ColorLib::ColorCalibrator::InitData(const CalibrationMeasurement** m
m_targetVal[1] = targeta;
m_targetVal[2] = targetb;
- int m_CalIndex = 0;
+ m_CalIndex = 0;
if (m_inkChannel == 2)
m_CalIndex = 2;
}
@@ -395,7 +395,7 @@ void Tango::ColorLib::ColorCalibrator::LinearizationInitData(const Linearizatio
m_targetVal[1] = targeta;
m_targetVal[2] = targetb;
- int m_CalIndex = 0;
+ m_CalIndex = 0;
if (m_inkChannel == 2)
m_CalIndex = 2;
}
diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/ColorConverter.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/ColorConverter.cpp
index e34a276ed..096d85bce 100644
--- a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/ColorConverter.cpp
+++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/ColorConverter.cpp
@@ -59,53 +59,20 @@
#define GradientEndThr 0.95
-Tango::ColorLib::ColorConverter::ColorConverter() : m_A2BTransform(NULL), m_B2ATransform(NULL),
-m_GBD(NULL), m_A2BRTransform(NULL), m_B2ARTransform(NULL),
-m_GBDR(NULL), m_CalibCurves(NULL), m_Conv02(NULL), m_GamutRegionMaxLim(NULL),
-m_maxNlPerCM(NULL), m_nA2BnSepIn(0), m_nA2BnSepOut(0), m_nB2AnSepIn(0), m_nB2AnSepOut(0),
-m_nInks(0), m_nVolumes(0), m_nGamutRegions(0), m_LinCurves(NULL),
-m_nProcessRanges(0), m_ProcessRangesMaxP(NULL), m_GradStops(NULL), m_nGradStops(0), m_NormFactor(-1.0),
-m_InvNormFactor(-1.0), m_TableVersion(1)
-//m_ProcessRangesMinInkUptake(NULL),m_ProcessRangesMinP(NULL),
-//m_ProcessRangesMaxInkUptake(NULL)
+Tango::ColorLib::ColorConverter::ColorConverter() :
+ m_CalibCurves(NULL), m_Conv02(NULL),
+m_maxNlPerCM(NULL),
+m_nInks(0), m_nVolumes(0),
+ m_GradStops(NULL), m_nGradStops(0), m_colortable(NULL), m_ProcessRangesMaxP(NULL),
+ m_nProcessRanges(0), m_NormGamutRegionMaxLim(NULL)
{
m_whitepointLab.Set(-1, -1, -1);
m_whitepointXYZ_Strip.Set(-1, -1, -1);
- m_whitepointXYZ_CT.Set(-1, -1, -1);
+ m_WP.Set(-1, -1, -1);
}
Tango::ColorLib::ColorConverter::~ColorConverter()
{
- if (m_A2BTransform != NULL)
- {
- delete m_A2BTransform;
- m_A2BTransform = NULL;
- }
- if (m_B2ATransform != NULL)
- {
- delete m_B2ATransform;
- m_B2ATransform = NULL;
- }
- if (m_GBD != NULL)
- {
- delete m_GBD;
- m_GBD = NULL;
- }
- if (m_A2BRTransform != NULL)
- {
- delete m_A2BRTransform;
- m_A2BRTransform = NULL;
- }
- if (m_B2ARTransform != NULL)
- {
- delete m_B2ARTransform;
- m_B2ARTransform = NULL;
- }
- if (m_GBDR != NULL)
- {
- delete m_GBDR;
- m_GBDR = NULL;
- }
if (m_Conv02 != NULL)
{
delete m_Conv02;
@@ -116,26 +83,26 @@ Tango::ColorLib::ColorConverter::~ColorConverter()
delete[] m_CalibCurves;
m_CalibCurves = NULL;
}
- if (m_GamutRegionMaxLim != NULL)
+ if(m_GradStops != NULL)
+ {
+ delete [] m_GradStops;
+ m_GradStops = NULL;
+ }
+ if (m_colortable != NULL)
{
- delete[] m_GamutRegionMaxLim;
- m_GamutRegionMaxLim = NULL;
+ delete m_colortable;
+ m_colortable = NULL;
}
- if (m_LinCurves != NULL)
+ if (m_NormGamutRegionMaxLim != NULL)
{
- delete m_LinCurves;
- m_LinCurves = NULL;
+ delete[] m_NormGamutRegionMaxLim;
+ m_NormGamutRegionMaxLim = NULL;
}
if (m_ProcessRangesMaxP != NULL)
{
delete[] m_ProcessRangesMaxP;
m_ProcessRangesMaxP = NULL;
}
- if (m_GradStops != NULL)
- {
- delete[] m_GradStops;
- m_GradStops = NULL;
- }
/* if (m_ProcessRangesMinP != NULL)
{
delete[] m_ProcessRangesMinP;
@@ -172,6 +139,7 @@ void Tango::ColorLib::ColorConverter::ProcessHiveNeighbors(ConversionInput *conv
hue = 0.0;
else
hue = atan2(Lab(2), Lab(1));
+
double d1 = dC;
double de = 0;
MatrixXd Lab1(nHive, 3);
@@ -229,7 +197,6 @@ void Tango::ColorLib::ColorConverter::ProcessHiveNeighbors(ConversionInput *conv
//double *tmpRGB = DBG_NEW double[3];
double *InkOut = new double[m_nInks];
//double *InkOut = DBG_NEW double[m_nInks];
-
int *GamutRegion = new int[nHive + 1];
//int *GamutRegion = DBG_NEW int[nHive + 1];
double *Lab1P = new double[3];
@@ -240,7 +207,7 @@ void Tango::ColorLib::ColorConverter::ProcessHiveNeighbors(ConversionInput *conv
//double * LabInFinal1 = DBG_NEW double[3];
double * LabInFinal2 = new double[3];
double * LabOnGamut = new double[3];
- double *InkOutP = new double[m_nB2AnSepOut];
+ double *InkOutP = new double[m_nInks];
bool InGamut = true;
for (int i = 0; i < nHive; ++i)
{
@@ -257,19 +224,19 @@ void Tango::ColorLib::ColorConverter::ProcessHiveNeighbors(ConversionInput *conv
*/
// ColConv.ChangeWP(Lab1P, Lab1P, m_WP, m_whitepointXYZ_CT); //to Relative
ColConv.ChangeWP(Lab1P, Lab1P, m_WP, m_whitepointXYZ_Strip); //to Relative
- m_B2ATransform->evalLab2InkP(Lab1P, InkOut, GamutRegion[i]); //InkOut is in units of 16 bits
- for (int i = 0; i < m_nB2AnSepOut; ++i)
+ m_colortable->m_B2ATransform->evalLab2InkP(Lab1P, InkOut, GamutRegion[i]); //InkOut is in units of 16 bits
+ for (int i = 0; i <m_nInks; ++i)
{
- InkOut[i] *= m_NormFactor;
- if (InkOut[i] <= m_GamutRegionMaxLim[0])
+ InkOut[i] *= m_colortable->GetNormFactor();
+ if (InkOut[i] <= m_NormGamutRegionMaxLim[0])
{
- m_LinCurves->m_InterpCurves[i].Eval(InkOut[i] * 655.35, InkOut[i]);
+ m_colortable->m_LinCurves->m_InterpCurves[i].Eval(InkOut[i] * 655.35, InkOut[i]);
InkOut[i] /= 655.35;
}
}
InGamut = IsInGamut(Lab1P, sur, CS, LabOnGamut);
LimitLab(LabOnGamut);
- VectorXd NLInkOut(m_nB2AnSepOut);
+ VectorXd NLInkOut(m_nInks);
ConvertToNLInks(DoubleToVector(InkOut, m_nInks), NLInkOut);
//Limit inks based on m_maxNlpercm
@@ -469,9 +436,6 @@ void Tango::ColorLib::ColorConverter::ArrangeHiveData(MatrixXd LabHive, MatrixX
}
-
-
-
void Tango::ColorLib::ColorConverter::fillVolume(OutputCoordinates *&outputCoords, VectorXd Volume)
{
int i = 0;
@@ -528,8 +492,8 @@ void Tango::ColorLib::ColorConverter::readColorTransformations(ConversionInput*
bool has_forwarddata = conversionInput->has_forwarddata;
uint8_t *data = conversionInput->forwarddata.data;
int nprocessranges = conversionInput->n_processranges;
- readColorTables(has_forwarddata, data, nprocessranges);
-
+ m_colortable->InitColorTables(has_forwarddata, data, nprocessranges);
+ SetNumberofInks(m_colortable->GetnA2BnSepOut());
}
void Tango::ColorLib::ColorConverter::SetStripWhitepoint(double threadl, double threada, double threadb)
@@ -543,293 +507,6 @@ void Tango::ColorLib::ColorConverter::SetStripWhitepoint(double threadl, double
m_whitepointXYZ_Strip.Set(tmpW.Get_x(), tmpW.Get_y(), tmpW.Get_z());
}
-void Tango::ColorLib::ColorConverter::readColorTables(bool has_data, uint8_t * data, int nprocessranges)
-{
- //parse Color Tansformations, placed in forward data
- int bytesread = 0;
- NumConversions conv;
- int tag_count = 0;
- if (has_data)
- {
- //Read Header
- CT_Header header = read_header(data, bytesread);
- SetnGamutRegions((int)header.nGamutRegions);
- SetTableVersion((int)header.Version[0]);
- if (m_nGamutRegions != nprocessranges)
- {
- throw std::exception("Number of gamut regions in table does not match STRIP\0");
- return;
- }
- m_GamutRegionMaxLim = new double[m_nGamutRegions];
- for (int i = 0; i < m_nGamutRegions; ++i)
- m_GamutRegionMaxLim[i] = header.GRegMaxLim[i];
- m_nProcessRanges = (int)(nprocessranges);
-
- /* for (int i = 0; i < m_nGamutRegions; ++i)
- {
- if (abs(m_GamutRegionMaxLim[i] - conversionInput->processranges[i]->maxinkuptake)> eps)
- throw std::exception(" Gamut Region Limit does not match MaxInkUptake in STRIP\0");
- }
- */
- if (header.GRegMaxLim != NULL)
- {
- delete[]header.GRegMaxLim;
- header.GRegMaxLim = NULL;
- }
-
-
- uint32_t tmp;
- uint8_t *buff =data;
- tmp = conv.ByteToInt(buff, bytesread);
- tag_count = (int)tmp;
- bytesread += 4;
- //read Tag Table
- char **TagNames = new char*[tag_count];
- //char **TagNames = DBG_NEW char*[tag_count];
- int **TagSize = new int*[tag_count];
- //int **TagSize = DBG_NEW int*[tag_count];
- char *tmpC = NULL;
- int n = 0;
- int i, j;
- for (i = 0; i < tag_count; ++i)
- {
- TagSize[i] = new int[3];
- //TagSize[i] = DBG_NEW int[3];
- tmp = conv.ByteToInt(buff, bytesread);
- n = sizeof((char*)&tmp);
- delete[] tmpC;
- tmpC = NULL;
- tmpC = new char[n];
- //tmpC = DBG_NEW char[n];
- conv.getchar(tmp, n, tmpC);
- //TagNames[i] = DBG_NEW char[n];
- TagNames[i] = new char[n];
- for (j = 0; j < n; ++j)
- TagNames[i][j] = tmpC[j];
- bytesread += 4;
- TagSize[i][0] = conv.ByteToInt(buff, bytesread);
- bytesread += 4;
- TagSize[i][1] = conv.ByteToInt(buff, bytesread);
- bytesread += 4;
- }
- delete[] tmpC;
- int *TList = new int[tag_count];
- //int *TList = DBG_NEW int[tag_count];
- for (int k = 0; k < tag_count; ++k)
- {
- if (strncmp(TagNames[k], "A2B ", 4) == 0)
- TList[k] = A2B;
- else if (strncmp(TagNames[k], "A2BR", 4) == 0)
- TList[k] = A2BR;
- else if (strncmp(TagNames[k], "B2A ", 4) == 0)
- TList[k] = B2A;
- else if (strncmp(TagNames[k], "B2AR ", 4) == 0)
- TList[k] = B2AR;
- else if (strncmp(TagNames[k], "wtpt", 4) == 0)
- TList[k] = wtpt;
- else if (strncmp(TagNames[k], "desc", 4) == 0)
- TList[k] = desc;
- else if (strncmp(TagNames[k], "gbd ", 4) == 0)
- TList[k] = gbd;
- else if (strncmp(TagNames[k], "gbdR", 4) == 0)
- TList[k] = gbdR;
- else if (strncmp(TagNames[k], "cprt", 4) == 0)
- TList[k] = cprt;
- else if (strncmp(TagNames[k], "lcrv", 4) == 0)
- TList[k] = lcrv;
- // else if (strncmp(TagNames[k], "GReg", 2) == 0)
- // TList[k] = GReg;
- else
- throw std::exception("Unknown Tag in Color Tables");
- }
- for (int k = 0; k < tag_count; ++k)
- {
- switch (TList[k])
- {
- case A2B:
- {
- uint8_t *A2BLUT = &(data[TagSize[k][0]]);
- int A2BLutsize = TagSize[k][1];
- m_A2BTransform = new ColorTransf();
- //m_A2BTransform = DBG_NEW ColorTransf();
- m_A2BTransform->InitData(A2BLUT, A2BLutsize);
- break;
- }
- case A2BR:
- {
- uint8_t *A2BRLUT = &(data[TagSize[k][0]]);
- int A2BRLutsize = TagSize[k][1];
- m_A2BRTransform = new ColorTransf();
- //m_A2BTransform = DBG_NEW ColorTransf();
- m_A2BRTransform->InitData(A2BRLUT, A2BRLutsize);
- break;
- }
- case B2A:
- {
- uint8_t *B2ALUT = &(data[TagSize[k][0]]);
- int B2ALutsize = TagSize[k][1];
- m_B2ATransform = new ColorTransf();
- //m_B2ATransform = DBG_NEW ColorTransf();
- m_B2ATransform->InitData(B2ALUT, B2ALutsize);
- break;
- }
- case B2AR:
- {
- uint8_t *B2ARLUT = &(data[TagSize[k][0]]);
- int B2ARLutsize = TagSize[k][1];
- m_B2ARTransform = new ColorTransf();
- //m_B2ATransform = DBG_NEW ColorTransf();
- m_B2ARTransform->InitData(B2ARLUT, B2ARLutsize);
- break;
- }
- /* case GReg:
- {
- uint8_t *GRegLUT = &(conversionInput->forwarddata.data[TagSize[k][0]]);
- int GRegLutsize = TagSize[k][1];
- m_GRegTransform = new ColorTransf();
- //m_B2ATransform = DBG_NEW ColorTransf();
- m_GRegTransform->InitData(GRegLUT, GRegLutsize);
- break;
- } */
- case gbd:
- {
- uint8_t *GBDList = &(data[TagSize[k][0]]);
- m_GBD = new GBD();
- //m_GBD = DBG_NEW GBD();
- int GBDSize = TagSize[k][1];
- m_GBD->InitData(GBDList, GBDSize);
- break;
- }
- case gbdR:
- {
- uint8_t *GBDRList = &(data[TagSize[k][0]]);
- m_GBDR = new GBD();
- //m_GBD = DBG_NEW GBD();
- int GBDRSize = TagSize[k][1];
- m_GBDR->InitData(GBDRList, GBDRSize);
- break;
- }
- case lcrv:
- {
- uint8_t *CurvesData = &(data[TagSize[k][0]]);
- m_LinCurves = new Curves();
- int CurvesSize = TagSize[k][1];
- m_LinCurves->InitData(CurvesData, CurvesSize);
- break;
- }
- case wtpt:
- {
- read_xyz_type(TagSize[k][0], TagSize[k][1], &m_whitepointXYZ_CT, data);
-
- break;
- }
- case cprt:
- {
- std::string textstr;
- read_text_type(TagSize[k][0], TagSize[k][1], &textstr, data);
- break;
- }
- case desc:
- {
- std::string textdescstr;
- read_text_description_type(TagSize[k][0], TagSize[k][1], textdescstr, data);
- break;
- }
- default:
- {
- throw std::exception("Unresolved Tag in Color Tables");
- return;
- }
-
- }
- }
- if (TagNames != NULL)
- {
- for (int i = 0; i < tag_count; ++i)
- {
- delete[] TagNames[i];
- TagNames[i] = NULL;
- }
- delete[]TagNames;
- TagNames = NULL;
- }
- if (TagSize != NULL)
- {
- for (int i = 0; i < tag_count; ++i)
- {
- delete[] TagSize[i];
- TagSize[i] = NULL;
- }
- delete[]TagSize;
- TagSize = NULL;
- }
- if (TList != NULL)
- {
- delete[] TList;
- TList = NULL;
- }
-
- if (header.ColorSpace != NULL)
- {
- delete header.ColorSpace;
- header.ColorSpace = NULL;
- }
- if (header.ConnectionSpace != NULL)
- {
- delete header.ConnectionSpace;
- header.ConnectionSpace = NULL;
- }
- if (header.DeviceManufacturer != NULL)
- {
- delete header.DeviceManufacturer;
- header.DeviceManufacturer = NULL;
- }
- }
-
-
- //Verify all relevant tags had been read
- if (m_A2BTransform == NULL)
- {
- throw std::exception("Missing Forward Transform in Color Tables");
- return;
- }
- if (m_A2BRTransform == NULL)
- {
- throw std::exception("Missing Reduced Forward Transform in Color Tables");
- return;
- }
- if (m_B2ATransform == NULL)
- {
- throw std::exception("Missing Inverse Transform in Color Tables");
- return;
- }
- if (m_B2ARTransform == NULL)
- {
- throw std::exception("Missing Reduced Inverse Transform in Color Tables");
- return;
- }
- if (m_GBD == NULL)
- {
- throw std::exception("Missing Gamut Boundary Descriptor in Color Tables");
- return;
- }
- if (m_GBDR == NULL)
- {
- throw std::exception("Missing Reduced Gamut Boundary Descriptor in Color Tables");
- return;
- }
- if ((m_whitepointXYZ_CT.Get_x() == -1) && (m_whitepointXYZ_CT.Get_y() == -1) && (m_whitepointXYZ_CT.Get_z() == -1))
- {
- throw std::exception("Missing Whitepoint in Color Tables");
- return;
- }
- if (m_LinCurves == NULL)
- {
- throw std::exception("Missing Linear Curves in Color Tables");
- return;
- }
- return; // OK
-}
void Tango::ColorLib::ColorConverter::readCalibrationTables(InputLiquid **inputliquid, int n_inputliquid)
@@ -909,20 +586,133 @@ void Tango::ColorLib::ColorConverter::SetCalibData(CalibrationData *calibrationD
return;
}
-void Tango::ColorLib::ColorConverter::ConvertColorToLinearInks(InputCoordinates* inputcoordinates, ColorSpace colorspace,
+void Tango::ColorLib::ColorConverter:: ConvertLabColorToLinearInks(InputCoordinates* inputcoordinates,
VectorXd &InkOut, VectorXd &RGBOut,
- VectorXd &LabOut, int &GamutRegion, bool &InGamut)
+ VectorXd &LabOut, int &GamutRegion, bool &InGamut, SURROUND sur, CAM02CS CS)
{
- size_t nInks = 0;
+ // Basic assumption: Lab data has the same whitepoint as the STRIP thread.
+ //The workflow is a follows:
+ //1. Convert Lab to Relative colorimetric. check if there is a match between STRIP and Color Tables
+ //2. Convert Lab to Inks (B2A tables), Inks to Volume
+ //3. Map the Lab value onto the gamut surface, if it is out of gamut
+ //4. Convert Lab to Absolute colorimetric taking into account the Strip and CT whitepoints
+ //5. Use the Relative Colorimetric Lab to obtain RGB
+ double *LabIn = new double[3];
+ //double *LabIn = DBG_NEW double[3];
+ LabIn[0] = inputcoordinates->l; //Absolute Colorimetric
+ LabIn[1] = inputcoordinates->a;
+ LabIn[2] = inputcoordinates->b;
+ //the assumption is that the color space has illumination that matches the whitepoint of the Strip
+ ColorConvert CConvertD65(D65, D65); //Destination, source
+ // double *LabInFinal1 = new double[3];
+ //double *LabInFinal1 = DBG_NEW double[3];
+ // for (int i = 0; i < 3; ++i)
+ // LabInFinal1[i] = LabIn[i];
+ //LabInFinal1 = LabIn;
+ // Lab is assumed to match the color of the STRIP, however the tables could have a different WP
+ //Check if Color Tables and Strip whitepoints are the same, otherwise convert
+/*
+if (m_AdaptWP)
+ {
+ CConvertD65.ChangeWP(LabInFinal1, LabInFinal1, m_whitepointXYZ_CT, m_whitepointXYZ_Strip); //to Color Tables
+ for (int i = 0; i < 3; ++i)
+ LabIn[i] = LabInFinal1[i];
+ }
+ */
+ double *LabInFinal2 = new double[3];
+ double *LabOnGamut = new double[3];
+ //double *LabInFinal2 = DBG_NEW double[3];
+ // CConvertD65.ChangeWP(LabIn, LabInFinal2, m_WP, m_whitepointXYZ_CT); //LabInFinal2 is in Relative Colorimetric Space
+ CConvertD65.ChangeWP(LabIn, LabInFinal2, m_WP, m_whitepointXYZ_Strip); //LabInFinal2 is in Relative Colorimetric Space
+ InGamut = IsInGamut(LabInFinal2, sur, CS, LabOnGamut);
+ LimitLab(LabOnGamut);
- C_RGB_XYZ_Lab DataLab;
- SURROUND sur = m_Conv02->getSurround();
- CAM02CS CS = m_Conv02->getCAM02CS();
- switch (colorspace)
+ //convert to Inks
+ double *InkOutP = new double[m_nInks];
+ //double *InkOutP = DBG_NEW double[m_nB2AnSepOut];
+ m_colortable->m_B2ATransform->evalLab2InkP(LabOnGamut, InkOutP, GamutRegion); //InkOut is in units of 16 bits
+ //Convert Inks to Lab to get the Gamut Mapped Lab
+//m_A2BTransform->evalInkP2Lab(InkOutP, LabIn, GamutRegion);
+//LabOut = DoubleToVector(LabIn, 3);
+//Convert InkOutP to linear in the m_GamutRegionMaxLim[0] range
+ for (int i = 0; i < m_nInks; ++i)
{
- case (COLOR_SPACE__RGB):
+ InkOutP[i] *= m_colortable->GetNormFactor();
+ if (InkOutP[i] <= m_NormGamutRegionMaxLim[0])
+ {
+ m_colortable->m_LinCurves->m_InterpCurves[i].Eval(InkOutP[i] * 655.35, InkOutP[i]);
+ InkOutP[i] /= 655.35;
+ }
+ }
+ InkOut = DoubleToVector(InkOutP, m_nInks);
+ double *LabOutFinal = new double[3];
+ //double *LabOutFinal = DBG_NEW double[3];
+ for (int i = 0; i < 3; ++i)
+ LabOutFinal[i] = LabOnGamut[i];
+ //LabOutFinal is in Relative Colorimetric
+ //Reverse the conversion process to bring back Lab to STRIP white point
+ // CConvertD65.ChangeWP(LabOutFinal, LabOutFinal, m_whitepointXYZ_CT, m_WP);
+ CConvertD65.ChangeWP(LabOutFinal, LabOutFinal, m_whitepointXYZ_Strip, m_WP);
+/*
+ if (m_AdaptWP)
+ {
+ CConvertD65.ChangeWP(LabOutFinal, LabOutFinal, m_whitepointXYZ_Strip, m_whitepointXYZ_CT);
+ }
+ */
+ LabOut = DoubleToVector(LabOutFinal, 3);
+ CConvertD65.SetReferenceWhite(D65);
+ //Convert to RGB
+ double *RGBOutP = new double[3];
+ // double *RGBOutP = DBG_NEW double[3];
+ //Use Relative colorimetric to get RGB
+ CConvertD65.LabtoRGB(LabOnGamut, RGBOutP);
+ //CConvertD65.LabtoRGB(LabIn, RGBOutP);
+ RGBOut = DoubleToVector(RGBOutP, 3);
+ if (LabOnGamut != NULL)
{
- // Basic assumption: if data is given in RGB space, conversion should be in relative colorimetric,
+ delete[] LabOnGamut;
+ LabOnGamut = NULL;
+ }
+ if (InkOutP != NULL)
+ {
+ delete[] InkOutP;
+ InkOutP = NULL;
+ }
+ if (LabIn != NULL)
+ {
+ delete[] LabIn;
+ LabIn = NULL;
+ }
+ /* if (LabInFinal1 != NULL)
+ {
+ delete[]LabInFinal1;
+ LabInFinal1 = NULL;
+ }
+ */
+ if (LabInFinal2 != NULL)
+ {
+ delete[]LabInFinal2;
+ LabInFinal2 = NULL;
+ }
+ if (LabOutFinal != NULL)
+ {
+ delete[]LabOutFinal;
+ LabOutFinal = NULL;
+ }
+
+ if (RGBOutP != NULL)
+ {
+ delete[] RGBOutP;
+ RGBOutP = NULL;
+ }
+}
+
+
+void Tango::ColorLib::ColorConverter::ConvertRGBColorToLinearInks(InputCoordinates* inputcoordinates,
+ VectorXd &InkOut, VectorXd &RGBOut,
+ VectorXd &LabOut, int &GamutRegion, bool &InGamut, SURROUND sur, CAM02CS CS)
+{
+ // Basic assumption: if data is given in RGB space, conversion should be in relative colorimetric,
//We expect that [255,255,255](white) will be mapped to the thread white, meaning all inks should be zero
// and the coverted RGB will refect the color of the thread, but will be shown in Relative Colorimetric to the user
//The workflow is a follows:
@@ -932,263 +722,145 @@ void Tango::ColorLib::ColorConverter::ConvertColorToLinearInks(InputCoordinates*
//4. Convert Lab to Absolute colorimetric taking into account the Strip and Color Table whitepoints
//5. Use the Relative Colorimetric Lab to obtain RGB
- RGBOut(0) = inputcoordinates->red;
- RGBOut(1) = inputcoordinates->green;
- RGBOut(2) = inputcoordinates->blue;
- //convert to Lab
- ColorConvert CConvertD65(D65, D65); //Destination, source
- double *LabIn = new double[3];
- double *RGBOutP = new double[3];
- //double *LabIn = DBG_NEW double[3];
- //double *RGBOutP = DBG_NEW double[3];
- VectorToDouble(RGBOut, RGBOutP);
- //RGB to Lab
- CConvertD65.RGBtoLab(RGBOutP, LabIn); //Values are in Relative Colorimetric, D65
- LimitLab(LabIn);
- //Is In Gamut?
- double *LabInFinal = new double[3];
- double *LabOnGamut = new double[3];
- InGamut = IsInGamut(LabIn, sur, CS, LabOnGamut);
- LimitLab(LabOnGamut);
+ RGBOut(0) = inputcoordinates->red;
+ RGBOut(1) = inputcoordinates->green;
+ RGBOut(2) = inputcoordinates->blue;
+ //convert to Lab
+ ColorConvert CConvertD65(D65, D65); //Destination, source
+ double *LabIn = new double[3];
+ double *RGBOutP = new double[3];
+ //double *LabIn = DBG_NEW double[3];
+ //double *RGBOutP = DBG_NEW double[3];
+ VectorToDouble(RGBOut, RGBOutP);
+ //RGB to Lab
+ CConvertD65.RGBtoLab(RGBOutP, LabIn); //Values are in Relative Colorimetric, D65
+ LimitLab(LabIn);
+ //Is In Gamut?
+ double *LabInFinal = new double[3];
+ double *LabOnGamut = new double[3];
+ InGamut = IsInGamut(LabIn, sur, CS, LabOnGamut);
+ LimitLab(LabOnGamut);
- //convert to inks
- int GamutRegion;
- double *InkOutP = new double[m_nB2AnSepOut];
- //double *InkOutP = DBG_NEW double[m_nB2AnSepOut];
- //LabInFinal is in Relative Colorimetric, just like the Color Tables
- m_B2ATransform->evalLab2InkP(LabOnGamut, InkOutP, GamutRegion); //InkOut is inthe [0-100] interval
+ //convert to inks
- //Convert to Lab to get the actual in Gamut Lab
- //double *LabInP = new double[3];
- //double *LabInP = DBG_NEW double[3];
- //m_A2BTransform->evalInkP2Lab(InkOutP, LabInP, GamutRegion); //Lab is in Relative Colorimetric
- //Convert InkOut to Linear via initial calibration Tables
- //Initial calibration tables are the ones that were included in the color table
- for (int i = 0; i < m_nB2AnSepOut; ++i)
- {
- InkOutP[i] *= m_NormFactor;
- if (InkOutP[i] <= m_GamutRegionMaxLim[0])
- {
- m_LinCurves->m_InterpCurves[i].Eval(InkOutP[i] * 655.35, InkOutP[i]);
- InkOutP[i] /= 655.35;
- }
- }
- InkOut = DoubleToVector(InkOutP, m_nInks);
+ double *InkOutP = new double[m_nInks];
+ //double *InkOutP = DBG_NEW double[m_nB2AnSepOut];
+ //LabInFinal is in Relative Colorimetric, just like the Color Tables
+ m_colortable->m_B2ATransform->evalLab2InkP(LabOnGamut, InkOutP, GamutRegion); //InkOut is inthe [0-100] interval
- //Convert to CT thread, LabOnGamut is in Relative Colorimetric Space
- //CConvertD65.ChangeWP(LabOnGamut, LabInFinal, m_whitepointXYZ_CT, m_WP);
- CConvertD65.ChangeWP(LabOnGamut, LabInFinal, m_whitepointXYZ_Strip, m_WP);
- //check if the thread to be used is the same as the one in the color tables
- /*
- if (m_AdaptWP)
- {
- //Convert to Strip White Point
- CConvertD65.ChangeWP(LabInFinal, LabInFinal, m_whitepointXYZ_Strip, m_whitepointXYZ_CT);
- }
- */
- LabOut = DoubleToVector(LabInFinal, 3);
- CConvertD65.SetReferenceWhite(D65);
- double *RGBOutP1 = new double[3];
- //double *RGBOutP1 = DBG_NEW double[3];
- CConvertD65.LabtoRGB(LabOnGamut, RGBOutP1);
- //CConvertD65.LabtoRGB(LabInP, RGBOutP1);
- RGBOut = DoubleToVector(RGBOutP1, 3);
- if (LabOnGamut != NULL)
- {
- delete[] LabOnGamut;
- LabOnGamut = NULL;
- }
- if (InkOutP != NULL)
- {
- delete[] InkOutP;
- InkOutP = NULL;
- }
- if (LabIn != NULL)
- {
- delete[] LabIn;
- LabIn = NULL;
- }
- if (RGBOutP != NULL)
- {
- delete[] RGBOutP;
- RGBOutP = NULL;
- }
- if (RGBOutP1 != NULL)
- {
- delete[] RGBOutP1;
- RGBOutP1 = NULL;
- }
- if (LabInFinal != NULL)
- {
- delete[] LabInFinal;
- LabInFinal = NULL;
- }
- break;
- }
- case (COLOR_SPACE__LAB):
+ //Convert to Lab to get the actual in Gamut Lab
+ //double *LabInP = new double[3];
+ //double *LabInP = DBG_NEW double[3];
+ //m_A2BTransform->evalInkP2Lab(InkOutP, LabInP, GamutRegion); //Lab is in Relative Colorimetric
+ //Convert InkOut to Linear via initial calibration Tables
+ //Initial calibration tables are the ones that were included in the color table
+ for (int i = 0; i < m_nInks; ++i)
{
- // Basic assumption: Lab data has the same whitepoint as the STRIP thread.
- //The workflow is a follows:
- //1. Convert Lab to Relative colorimetric. check if there is a match between STRIP and Color Tables
- //2. Convert Lab to Inks (B2A tables), Inks to Volume
- //3. Map the Lab value onto the gamut surface, if it is out of gamut
- //4. Convert Lab to Absolute colorimetric taking into account the Strip and CT whitepoints
- //5. Use the Relative Colorimetric Lab to obtain RGB
- double *LabIn = new double[3];
- //double *LabIn = DBG_NEW double[3];
- LabIn[0] = inputcoordinates->l; //Absolute Colorimetric
- LabIn[1] = inputcoordinates->a;
- LabIn[2] = inputcoordinates->b;
- //the assumption is that the color space has illumination that matches the whitepoint of the Strip
- ColorConvert CConvertD65(D65, D65); //Destination, source
- // double *LabInFinal1 = new double[3];
- //double *LabInFinal1 = DBG_NEW double[3];
- // for (int i = 0; i < 3; ++i)
- // LabInFinal1[i] = LabIn[i];
- //LabInFinal1 = LabIn;
- // Lab is assumed to match the color of the STRIP, however the tables could have a different WP
- //Check if Color Tables and Strip whitepoints are the same, otherwise convert
- /*
- if (m_AdaptWP)
+ InkOutP[i] *= m_colortable->GetNormFactor();
+ if (InkOutP[i] <= m_NormGamutRegionMaxLim[0])
{
- CConvertD65.ChangeWP(LabInFinal1, LabInFinal1, m_whitepointXYZ_CT, m_whitepointXYZ_Strip); //to Color Tables
- for (int i = 0; i < 3; ++i)
- LabIn[i] = LabInFinal1[i];
+ m_colortable->m_LinCurves->m_InterpCurves[i].Eval(InkOutP[i] * 655.35, InkOutP[i]);
+ InkOutP[i] /= 655.35;
}
- */
- double *LabInFinal2 = new double[3];
- double *LabOnGamut = new double[3];
- //double *LabInFinal2 = DBG_NEW double[3];
-// CConvertD65.ChangeWP(LabIn, LabInFinal2, m_WP, m_whitepointXYZ_CT); //LabInFinal2 is in Relative Colorimetric Space
- CConvertD65.ChangeWP(LabIn, LabInFinal2, m_WP, m_whitepointXYZ_Strip); //LabInFinal2 is in Relative Colorimetric Space
- InGamut = IsInGamut(LabInFinal2, sur, CS, LabOnGamut);
- LimitLab(LabOnGamut);
+ }
+ InkOut = DoubleToVector(InkOutP, m_nInks);
- //convert to Inks
- int GamutRegion;
- double *InkOutP = new double[m_nB2AnSepOut];
- //double *InkOutP = DBG_NEW double[m_nB2AnSepOut];
- m_B2ATransform->evalLab2InkP(LabOnGamut, InkOutP, GamutRegion); //InkOut is in units of 16 bits
- //Convert Inks to Lab to get the Gamut Mapped Lab
- //m_A2BTransform->evalInkP2Lab(InkOutP, LabIn, GamutRegion);
- //LabOut = DoubleToVector(LabIn, 3);
- //Convert InkOutP to linear in the m_GamutRegionMaxLim[0] range
- for (int i = 0; i < m_nB2AnSepOut; ++i)
- {
- InkOutP[i] *= m_NormFactor;
- if (InkOutP[i] <= m_GamutRegionMaxLim[0])
- {
- m_LinCurves->m_InterpCurves[i].Eval(InkOutP[i] * 655.35, InkOutP[i]);
- InkOutP[i] /= 655.35;
- }
- }
- InkOut = DoubleToVector(InkOutP, m_nInks);
- double *LabOutFinal = new double[3];
- //double *LabOutFinal = DBG_NEW double[3];
- for (int i = 0; i < 3; ++i)
- LabOutFinal[i] = LabOnGamut[i];
- //LabOutFinal is in Relative Colorimetric
- //Reverse the conversion process to bring back Lab to STRIP white point
-// CConvertD65.ChangeWP(LabOutFinal, LabOutFinal, m_whitepointXYZ_CT, m_WP);
- CConvertD65.ChangeWP(LabOutFinal, LabOutFinal, m_whitepointXYZ_Strip, m_WP);
+ //Convert to CT thread, LabOnGamut is in Relative Colorimetric Space
+ //CConvertD65.ChangeWP(LabOnGamut, LabInFinal, m_whitepointXYZ_CT, m_WP);
+ CConvertD65.ChangeWP(LabOnGamut, LabInFinal, m_whitepointXYZ_Strip, m_WP);
+ //check if the thread to be used is the same as the one in the color tables
/*
- if (m_AdaptWP)
- {
- CConvertD65.ChangeWP(LabOutFinal, LabOutFinal, m_whitepointXYZ_Strip, m_whitepointXYZ_CT);
- }
- */
- LabOut = DoubleToVector(LabOutFinal, 3);
- CConvertD65.SetReferenceWhite(D65);
- //Convert to RGB
- double *RGBOutP = new double[3];
- // double *RGBOutP = DBG_NEW double[3];
- //Use Relative colorimetric to get RGB
- CConvertD65.LabtoRGB(LabOnGamut, RGBOutP);
- //CConvertD65.LabtoRGB(LabIn, RGBOutP);
- RGBOut = DoubleToVector(RGBOutP, 3);
- if (LabOnGamut != NULL)
- {
- delete[] LabOnGamut;
- LabOnGamut = NULL;
- }
- if (InkOutP != NULL)
- {
- delete[] InkOutP;
- InkOutP = NULL;
- }
- if (LabIn != NULL)
- {
- delete[] LabIn;
- LabIn = NULL;
- }
-/* if (LabInFinal1 != NULL)
- {
- delete[]LabInFinal1;
- LabInFinal1 = NULL;
- }
- */
- if (LabInFinal2 != NULL)
- {
- delete[]LabInFinal2;
- LabInFinal2 = NULL;
- }
- if (LabOutFinal != NULL)
- {
- delete[]LabOutFinal;
- LabOutFinal = NULL;
- }
-
- if (RGBOutP != NULL)
- {
- delete[] RGBOutP;
- RGBOutP = NULL;
- }
- break;
+ if (m_AdaptWP)
+ {
+ //Convert to Strip White Point
+ CConvertD65.ChangeWP(LabInFinal, LabInFinal, m_whitepointXYZ_Strip, m_whitepointXYZ_CT);
+ }
+ */
+ LabOut = DoubleToVector(LabInFinal, 3);
+ CConvertD65.SetReferenceWhite(D65);
+ double *RGBOutP1 = new double[3];
+ //double *RGBOutP1 = DBG_NEW double[3];
+ CConvertD65.LabtoRGB(LabOnGamut, RGBOutP1);
+ //CConvertD65.LabtoRGB(LabInP, RGBOutP1);
+ RGBOut = DoubleToVector(RGBOutP1, 3);
+ if (LabOnGamut != NULL)
+ {
+ delete[] LabOnGamut;
+ LabOnGamut = NULL;
+ }
+ if (InkOutP != NULL)
+ {
+ delete[] InkOutP;
+ InkOutP = NULL;
+ }
+ if (LabIn != NULL)
+ {
+ delete[] LabIn;
+ LabIn = NULL;
+ }
+ if (RGBOutP != NULL)
+ {
+ delete[] RGBOutP;
+ RGBOutP = NULL;
+ }
+ if (RGBOutP1 != NULL)
+ {
+ delete[] RGBOutP1;
+ RGBOutP1 = NULL;
+ }
+ if (LabInFinal != NULL)
+ {
+ delete[] LabInFinal;
+ LabInFinal = NULL;
+ }
}
- case(COLOR_SPACE__CMYK):
- {//no conversion
+void Tango::ColorLib::ColorConverter::ConvertCMYKColorToLinearInks(InputCoordinates* inputcoordinates,
+ VectorXd &InkOut, VectorXd &RGBOut,
+ VectorXd &LabOut, int &GamutRegion, bool &InGamut, SURROUND sur, CAM02CS CS)
+{
+ //no conversion
//missing from structure light inks or special colors
// just convert Lab for rgb display
- double *outData = new double[m_nA2BnSepIn];
- //double *outData = DBG_NEW double[m_nA2BnSepIn];
- size_t CountSep = 0;
- outData[0] = (double)(inputcoordinates->cyan);
- outData[1] = (double)(inputcoordinates->magenta);
- outData[2] = (double)(inputcoordinates->yellow);
- outData[3] = (double)(inputcoordinates->key);
- CountSep = 4;
- if (CountSep != m_nA2BnSepIn)
- {
- //mismatch between table and sent data
- throw std::exception("Mismatch between table and sent data");
- return;
- }
- //Convert to RGB
- int GamutRegion = 0;
- double *InkOutP = new double[m_nA2BnSepIn];
- //double *InkOutP = DBG_NEW double[m_nA2BnSepIn];
- for (int i = 0; i < m_nA2BnSepIn; ++i)
- InkOutP[i] = outData[i];
- double *LabOutP = new double[3];
- //double *LabOutP = DBG_NEW double[3];
- m_A2BTransform->evalInkP2Lab(InkOutP, LabOutP, GamutRegion);
- InkOut = DoubleToVector(InkOutP, m_nInks);
- //LabOut is in relative colorimetric
- ColorConvert CConvertD65(D65, D65);
- double *LabOutFinal1 = new double[3];
- //double *LabOutFinal1 = DBG_NEW double[3];
- for (int i = 0; i < 3; ++i)
- LabOutFinal1[i] = LabOutP[i];
- double *LabOutFinal2 = new double[3];
- //double *LabOutFinal2 = DBG_NEW double[3];
- for (int i = 0; i < 3; ++i)
- LabOutFinal2[i] = LabOutP[i];
- InGamut = true;
- //Check if white points match
+ double *outData = new double[m_nInks];
+ //double *outData = DBG_NEW double[m_nA2BnSepIn];
+ size_t CountSep = 0;
+ outData[0] = (double)(inputcoordinates->cyan);
+ outData[1] = (double)(inputcoordinates->magenta);
+ outData[2] = (double)(inputcoordinates->yellow);
+ outData[3] = (double)(inputcoordinates->key);
+ CountSep = 4;
+
+ if (CountSep != m_nInks)
+ {
+ //mismatch between table and sent data
+ throw std::exception("Mismatch between table and sent data");
+ return;
+ }
+ //Convert to RGB
+ double *InkOutP = new double[m_nInks];
+ //double *InkOutP = DBG_NEW double[m_nA2BnSepIn];
+ for (int i = 0; i < m_nInks; ++i)
+ InkOutP[i] = outData[i];
+ double *LabOutP = new double[3];
+ //double *LabOutP = DBG_NEW double[3];
+ m_colortable->m_A2BTransform->evalInkP2Lab(InkOutP, LabOutP, GamutRegion);
+ InkOut = DoubleToVector(InkOutP, m_nInks);
+ //LabOut is in relative colorimetric
+ ColorConvert CConvertD65(D65, D65);
+ double *LabOutFinal1 = new double[3];
+ //double *LabOutFinal1 = DBG_NEW double[3];
+ for (int i = 0; i < 3; ++i)
+ LabOutFinal1[i] = LabOutP[i];
+ double *LabOutFinal2 = new double[3];
+ //double *LabOutFinal2 = DBG_NEW double[3];
+ for (int i = 0; i < 3; ++i)
+ LabOutFinal2[i] = LabOutP[i];
+ InGamut = true;
+ //Check if white points match
// CConvertD65.ChangeWP(LabOutFinal1, LabOutFinal1, m_whitepointXYZ_CT, m_WP); //To Absolute
- CConvertD65.ChangeWP(LabOutFinal1, LabOutFinal1, m_whitepointXYZ_Strip, m_WP); //To Absolute
+ CConvertD65.ChangeWP(LabOutFinal1, LabOutFinal1, m_whitepointXYZ_Strip, m_WP); //To Absolute
/* if (m_AdaptWP)
{
CConvertD65.ChangeWP(LabOutFinal1, LabOutFinal2, m_whitepointXYZ_Strip, m_whitepointXYZ_CT);
@@ -1196,45 +868,75 @@ void Tango::ColorLib::ColorConverter::ConvertColorToLinearInks(InputCoordinates*
LabOutFinal1[i] = LabOutFinal2[i];
}
*/
- LabOut = DoubleToVector(LabOutFinal1, 3);
- CConvertD65.SetReferenceWhite(D65);
- //Get RGB
- double *RGBOutP = new double[3];
- //double *RGBOutP = DBG_NEW double[3];
- CConvertD65.LabtoRGB(LabOutP, RGBOutP);
- //CConvertD65.LabtoRGB(LabOutP, RGBOutP);
- RGBOut = DoubleToVector(RGBOutP, 3);
+ LabOut = DoubleToVector(LabOutFinal1, 3);
+ CConvertD65.SetReferenceWhite(D65);
+ //Get RGB
+ double *RGBOutP = new double[3];
+ //double *RGBOutP = DBG_NEW double[3];
+ CConvertD65.LabtoRGB(LabOutP, RGBOutP);
+ //CConvertD65.LabtoRGB(LabOutP, RGBOutP);
+ RGBOut = DoubleToVector(RGBOutP, 3);
- if (outData != NULL)
- {
- delete[] outData;
- outData = NULL;
- }
- if (LabOutP != NULL)
- {
- delete[] LabOutP;
- LabOutP = NULL;
- }
- if (InkOutP != NULL)
- {
- delete[] InkOutP;
- InkOutP = NULL;
- }
- if (RGBOutP != NULL)
- {
- delete[] RGBOutP;
- RGBOutP = NULL;
- }
- if (LabOutFinal1 != NULL)
- {
- delete[] LabOutFinal1;
- LabOutFinal1 = NULL;
- }
- if (LabOutFinal2 != NULL)
- {
- delete[] LabOutFinal2;
- LabOutFinal2 = NULL;
- }
+ if (outData != NULL)
+ {
+ delete[] outData;
+ outData = NULL;
+ }
+ if (LabOutP != NULL)
+ {
+ delete[] LabOutP;
+ LabOutP = NULL;
+ }
+ if (InkOutP != NULL)
+ {
+ delete[] InkOutP;
+ InkOutP = NULL;
+ }
+ if (RGBOutP != NULL)
+ {
+ delete[] RGBOutP;
+ RGBOutP = NULL;
+ }
+ if (LabOutFinal1 != NULL)
+ {
+ delete[] LabOutFinal1;
+ LabOutFinal1 = NULL;
+ }
+ if (LabOutFinal2 != NULL)
+ {
+ delete[] LabOutFinal2;
+ LabOutFinal2 = NULL;
+ }
+}
+void Tango::ColorLib::ColorConverter::ConvertColorToLinearInks(InputCoordinates* inputcoordinates, ColorSpace colorspace,
+ VectorXd &InkOut, VectorXd &RGBOut,
+ VectorXd &LabOut, int &GamutRegion, bool &InGamut)
+{
+ size_t nInks = 0;
+
+ C_RGB_XYZ_Lab DataLab;
+ SURROUND sur = m_Conv02->getSurround();
+ CAM02CS CS = m_Conv02->getCAM02CS();
+ switch (colorspace)
+ {
+ case (COLOR_SPACE__RGB):
+ {
+ ConvertRGBColorToLinearInks(inputcoordinates,
+ InkOut, RGBOut, LabOut, GamutRegion, InGamut, sur, CS);
+ break;
+ }
+ case (COLOR_SPACE__LAB):
+ {
+ ConvertLabColorToLinearInks(inputcoordinates,
+ InkOut, RGBOut, LabOut, GamutRegion, InGamut, sur, CS);
+ break;
+ }
+
+ case(COLOR_SPACE__CMYK):
+ {
+ ConvertCMYKColorToLinearInks(inputcoordinates,
+ InkOut, RGBOut, LabOut, GamutRegion, InGamut, sur, CS);
+
break;
}
case(COLOR_SPACE__Catalog):
@@ -1267,7 +969,7 @@ void Tango::ColorLib::ColorConverter::ConvertToNLInks(VectorXd InkIn, VectorXd
{
for (int i = 0; i < m_nVolumes; ++i)
{
- if (InkIn(i) <= m_GamutRegionMaxLim[0])
+ if (InkIn(i) <= m_NormGamutRegionMaxLim[0])
m_CalibCurves[i].m_InvLinearInterp->Eval(InkIn(i), InkOut(i));
else
InkOut(i) = InkIn(i);
@@ -1386,7 +1088,7 @@ void Tango::ColorLib::ColorConverter::NLInkPToVolume(VectorXd NLInk, VectorXd &V
RVolNorm(i) = round(Volume(i)*ROUNDINGTol) / ROUNDINGTol;
RsumNorm += RVolNorm(i);
}
- if (RsumNorm > m_GamutRegionMaxLim[m_nProcessRanges - 1] || abs(sumNorm - RsumNorm) >= 1 / ROUNDINGTol)
+ if (RsumNorm > m_NormGamutRegionMaxLim[m_nProcessRanges - 1] || abs(sumNorm - RsumNorm) >= 1 / ROUNDINGTol)
{
VectorXd dd(m_nInks);
double maxdd = -1;
@@ -1516,22 +1218,22 @@ void Tango::ColorLib::ColorConverter::ConvertVolumeToRGBDisplay(InputCoordinates
for (int i = 0; i < m_nVolumes; ++i)
Volume(i) = inputcoordinates->inputliquids[i]->volume; //volume is given in %
- GamutRegion = GetGamutRegion(Volume, m_GamutRegionMaxLim);
+ GamutRegion = GetGamutRegion(Volume, m_NormGamutRegionMaxLim);
VolumeToNLInkP(Volume, NLInkP);
//Limit Inks
- double *InkOutP = new double[m_nA2BnSepIn];
+ double *InkOutP = new double[m_nInks];
VectorToDouble(NLInkP, InkOutP);
//for (int i = 0; i < m_nA2BnSepIn; ++i)
// InkOutP[i] = NLInkP(i);
- double *LinInkP = new double[m_nA2BnSepIn];
+ double *LinInkP = new double[m_nInks];
//Reflect the Calibration Curves of the thread in Catalog Items
if (colorspace == COLOR_SPACE__Catalog)
{
- for (int i = 0; i < m_nB2AnSepOut; ++i)
+ for (int i = 0; i < m_nInks; ++i)
{
- if (NLInkP(i) <= m_GamutRegionMaxLim[0])
+ if (NLInkP(i) <= m_NormGamutRegionMaxLim[0])
{
- m_LinCurves->m_InterpCurves[i].Eval(InkOutP[i] * 655.35, InkOutP[i]);
+ m_colortable->m_LinCurves->m_InterpCurves[i].Eval(InkOutP[i] * 655.35, InkOutP[i]);
InkOutP[i] /= 655.35;
NLInkP(i) = InkOutP[i];
}
@@ -1539,7 +1241,7 @@ void Tango::ColorLib::ColorConverter::ConvertVolumeToRGBDisplay(InputCoordinates
}
for (int i = 0; i < (int)(m_nVolumes); ++i)
{
- if (NLInkP(i) <= m_GamutRegionMaxLim[0])
+ if (NLInkP(i) <= m_NormGamutRegionMaxLim[0])
{
m_CalibCurves[i].m_InvLinearInterp->Eval(InkOutP[i], InkOutP[i]);
NLInkP(i) = InkOutP[i];
@@ -1560,15 +1262,15 @@ void Tango::ColorLib::ColorConverter::ConvertVolumeToRGBDisplay(InputCoordinates
//Convert to RGB
//GamutRegion = 0;
//Convert to Lab
-
- double *LabOutP = new double[m_nA2BnSepOut];
+
+ double *LabOutP = new double[3];
//double *InkOutP = DBG_NEW double[m_nA2BnSepIn];
//double *LabOutP = DBG_NEW double[m_nA2BnSepOut];
//InkOutP has to be normalized to match the transform units
- for (int i = 0; i < m_nB2AnSepOut; ++i)
- InkOutP[i] *= m_InvNormFactor;
+ for (int i = 0; i < m_nInks; ++i)
+ InkOutP[i] *= m_colortable->GetInverseNormFactor();
- m_A2BTransform->evalInkP2Lab(InkOutP, LabOutP, GamutRegion);
+ m_colortable->m_A2BTransform->evalInkP2Lab(InkOutP, LabOutP, GamutRegion);
//LabOutP is in Relative Colorimetric
ColorConvert CConvertD65(D65, D65);
@@ -1716,7 +1418,13 @@ size_t Tango::ColorLib::ColorConverter::Convert(uint8_t * input_buffer, size_t i
m_WP.Set(0.9505, 1.00, 1.0888); //D65
//count number if inks
// int numofInks = CountNumberofInks(conversionInput);
+ m_colortable = new ColorTable();
readColorTransformations(conversionInput);
+ m_nProcessRanges = conversionInput->n_processranges;
+ m_NormGamutRegionMaxLim = new double[m_nProcessRanges];
+ double *tmpVal = m_colortable->GetNormGamutRegionMaxLim();
+ for (int i = 0; i < m_nProcessRanges; ++i)
+ m_NormGamutRegionMaxLim[i] = tmpVal[i];
//read calibration tables and store them in m_CalibCurves
InputLiquid **inputliquids = conversionInput->inputcoordinates->inputliquids;
int n_inputliquids = conversionInput->inputcoordinates->n_inputliquids;
@@ -1726,46 +1434,38 @@ size_t Tango::ColorLib::ColorConverter::Convert(uint8_t * input_buffer, size_t i
Illum IL = D65;
SURROUND sur = average;
CAM02CS CS = UCS;
- m_Conv02 = new ColorConvert(IL, IL, Y_b, L_A, sur, CS);
+ if(m_Conv02 ==NULL)
+ m_Conv02 = new ColorConvert(IL, IL, Y_b, L_A, sur, CS);
//m_Conv02 = DBG_NEW ColorConvert(IL, IL, Y_b, L_A, sur, CS);
- SetnA2BnSepIn(m_A2BTransform->GetSeparationsIn());
- SetnA2BnSepOut(m_A2BTransform->GetSeparationsOut());
- SetnB2AnSepIn(m_B2ATransform->GetSeparationsIn());
- SetnB2AnSepOut(m_B2ATransform->GetSeparationsOut());
-
- SetNumberOfInks(m_nB2AnSepOut);
+
// Compare Strip White point to Color Table White Point
//CompareWhitePoints();
- if (numofInks != m_nB2AnSepOut)
+ if (numofInks != m_nInks)
throw std::exception("Number of available inks does not match ink tables\0");
//Tables have been filled
//Set Process Ranges
- m_ProcessRangesMaxP = new double[m_nProcessRanges];
+ if(m_ProcessRangesMaxP == NULL)
+ m_ProcessRangesMaxP = new double[m_nProcessRanges];
for (int i = 0; i < m_nProcessRanges; ++i)
{
m_ProcessRangesMaxP[i] = conversionInput->processranges[i]->maxinkuptake;
}
- NormGamutRegionMaxLim();
- if (m_NormFactor <= 0.0)
- {
- SetNormFactor();
- SetInverseNormFactor();
- }
- VectorXd InkOut(m_nB2AnSepOut);
+
+ VectorXd InkOut(m_nInks);
VectorXd RGBOut(3);
VectorXd LabOut(3);
- VectorXd NLInkOut(m_nB2AnSepOut);
- VectorXd Volume(m_nB2AnSepOut);
- VectorXd VolumeOut(m_nB2AnSepOut);
+ VectorXd NLInkOut(m_nInks);
+ VectorXd Volume(m_nInks);
+ VectorXd VolumeOut(m_nInks);
//set maxNlPerCM
- VectorXd NlperCM(m_nB2AnSepOut);
+ VectorXd NlperCM(m_nInks);
NlperCM.setZero();
m_maxNlPerCM = NlperCM;
- for (int i = 0; i < m_nB2AnSepOut; ++i)
+ for (int i = 0; i < m_nInks; ++i)
SetMaxNLperCM(conversionInput->inputcoordinates->inputliquids[i]->maxnanoliterpercentimeter, i);
- m_nVolumes = m_nB2AnSepOut;
+ m_nVolumes = m_nInks;
int GamutRegion = 0;
//Convert input data to linear inks
if (conversionInput->colorspace == COLOR_SPACE__Volume || conversionInput->colorspace == COLOR_SPACE__Catalog)
@@ -1786,7 +1486,7 @@ size_t Tango::ColorLib::ColorConverter::Convert(uint8_t * input_buffer, size_t i
//Limit inks based on m_maxNlpercm
//Inks are limited in their nonlinear form
//Output Volume is in %
- double *InkOutP = new double[m_nB2AnSepOut];
+ double *InkOutP = new double[m_nInks];
LimitInks(NLInkOut, InkOutP);
NLInkPToVolume(DoubleToVector(InkOutP, m_nInks), Volume);
GamutRegion = GetGamutRegion(Volume, m_ProcessRangesMaxP);
@@ -2038,7 +1738,7 @@ bool Tango::ColorLib::ColorConverter::IsInGamut(double *InLab, SURROUND sur, CA
}
double ctr[3];
- C_RGB_XYZ_Lab center = m_GBD->getCenter();
+ C_RGB_XYZ_Lab center = m_colortable->m_GBD->getCenter();
VectorXd JInLab(3);
JInLab << InLab[0], InLab[1], InLab[2];
VectorXd JLab = m_Conv02->LabToJab(JInLab, sur);
@@ -2049,7 +1749,7 @@ bool Tango::ColorLib::ColorConverter::IsInGamut(double *InLab, SURROUND sur, CA
//double *dJLab = DBG_NEW double[3];
VectorToDouble(JLab, dJLab);
bool intersect = false;
- m_GBD->TriangleRayIntersection(dJLab, ctr, intersect, xCoord);
+ m_colortable->m_GBD->TriangleRayIntersection(dJLab, ctr, intersect, xCoord);
if (intersect)
{
VectorXd V1(3);
@@ -2090,92 +1790,7 @@ bool Tango::ColorLib::ColorConverter::IsInGamut(double *InLab, SURROUND sur, CA
}
-Tango::CT_Header Tango::ColorLib::ColorConverter::read_header(uint8_t *data, int &bytesread)
-{
- //CT_Header *Header = new CT_Header;
- //CT_Header *Header = DBG_NEW CT_Header;
- CT_Header Header;
-
- // unsigned int tmp = (buffer[2 * i + 1] << 8) | buffer[2 * i];
- uint8_t *ColorTable =data;
- //File Size
- NumConversions Conv;
- Header.TblSIze = Conv.ByteToInt(ColorTable, bytesread);
- bytesread = 4;
- uint8_t versionBCT[2];
- versionBCT[0] = (unsigned int)ColorTable[bytesread];
- bytesread += 1;
- versionBCT[1] = (unsigned int)ColorTable[bytesread];
- Header.Version[0] = versionBCT[0];
- Header.Version[1] = versionBCT[1] << 4;
- Header.Version[2] = versionBCT[1] & 15;
- bytesread += 1;
- uint32_t tmp = Conv.ByteToInt(ColorTable, bytesread);
- int n = sizeof((char*)&tmp);
- //char *tmpC = DBG_NEW char[n];
- char *tmpC = new char[n];
- Conv.getchar(tmp, n, tmpC);
- //Header.ColorSpace = DBG_NEW char[n];
- Header.ColorSpace = new char[n];
- memcpy_s(Header.ColorSpace, n + 1, tmpC, n);
-
- // strncpy_s(Header->ColorSpace, n+1, tmpC, n);
- //Header->ColorSpace = tmpC;
- bytesread += 4;
- tmp = Conv.ByteToInt(ColorTable, bytesread);
- Conv.getchar(tmp, n, tmpC);
- //Header.ConnectionSpace = DBG_NEW char[n];
- Header.ConnectionSpace = new char[n];
- memcpy_s(Header.ConnectionSpace, n + 1, tmpC, n);
-
- bytesread += 4;
-
- bytesread += 12;
- tmp = Conv.ByteToInt(ColorTable, bytesread);
- Conv.getchar(tmp, n, tmpC);
- //Header.DeviceManufacturer = DBG_NEW char[n];
- Header.DeviceManufacturer = new char[n];
- memcpy_s(Header.DeviceManufacturer, n + 1, tmpC, n);
- // strncpy_s(Header->DeviceManufacturer, n + 1, tmpC, n);
- //Header->DeviceManufacturer = tmpC;
- if (tmpC != NULL)
- {
- delete[]tmpC;
- tmpC = NULL;
- }
-
- bytesread += 4;
- //read illuminant
- double xyz[3];
- for (int j = 0; j < 3; ++j)
- {
- tmp = Conv.ByteToInt(ColorTable, bytesread);
- xyz[j] = (double)(tmp) / 65536;
- bytesread += 4;
- }
- Header.Illuminant.Set(xyz[0], xyz[1], xyz[2]);
- //Read Number of Gamut Regions and Max Limits per Region
- Header.nGamutRegions = ColorTable[bytesread];
- bytesread++;
- Header.GRegMaxLim = new double[Header.nGamutRegions];
- for (int i = 0; i < Header.nGamutRegions; ++i)
- {
- tmp = Conv.ByteToShort(ColorTable, bytesread);
- bytesread += 2;
- Header.GRegMaxLim[i] = (double)tmp;
- }
-
- if (bytesread < 128)
- {
- bytesread = 128;
- return(Header);
- }
- else
- {
- throw std::exception("could not read Color table Header");
- }
-}
void Tango::ColorLib::ColorConverter::read_lut_type(int offset, int data_size, ColorTransf *Transf, ConversionInput* conversionInput)
{
@@ -2203,166 +1818,11 @@ void Tango::ColorLib::ColorConverter::read_lut_type(int offset, int data_size, C
return;
}
-void Tango::ColorLib::ColorConverter::read_xyz_type(int offset, int data_size, C_RGB_XYZ_Lab *XYZ, uint8_t *data)
-{
- // 0 - 3 'XYZ '
- //4 - 7 reserved, must be 0
- // 8 - n array of XYZ numbers
- if (data_size < 8)
- {
- throw std::exception("not enough data to read xyz");
- }
- uint8_t *buff = &(data[offset]);
- NumConversions Conv;
- int bytesread = 0;
- int tmpxyz = Conv.ByteToInt(buff, bytesread);
- int n = sizeof(tmpxyz);
- //char* tmpC = DBG_NEW char[n];
- char* tmpC = new char[n];
- Conv.getchar(tmpxyz, n, tmpC);
-
- char *xyztype = new char[n + 1];
- //char *xyztype = DBG_NEW char[n + 1];
- strncpy_s(xyztype, n + 1, tmpC, n);
- if (strncmp(xyztype, "XYZ ", n) != 0)
- {
- throw std::exception("Wrong Tag Type");
- return;
- }
- if (xyztype != NULL)
- {
- delete[] xyztype;
- xyztype = NULL;
- }
- if (tmpC != NULL)
- {
- delete[] tmpC;
- tmpC = NULL;
- }
- bytesread = 8;
- int num_values = (data_size - 8) / 4;
- if (floor((double)(num_values) / 3) * 3 != num_values)
- {
- throw std::exception("not enough Data to read xyz");
- return;
- }
- double xyz[3];
- int tmp;
- for (int j = 0; j < 3; ++j)
- {
- tmp = Conv.ByteToInt(buff, bytesread);
- xyz[j] = (double)(tmp) / 65536;
- bytesread += 4;
- }
- XYZ->Set(xyz[0], xyz[1], xyz[2]);
- return;
-}
-
-void Tango::ColorLib::ColorConverter::read_text_type(int offset, int data_size, std::string *textstr, uint8_t *data)
-{
- // 0 - 3 'text'
- //4 - 7 reserved, must be 0
- //8 - string of(data_size - 8) 7 - bit ASCII characters, including NULL
-
- std::stringstream strstr;
- if (data_size < 8)
- {
- throw std::exception("invalid Tag Name");
- strstr << "";
- *textstr = strstr.str();
- return;
- }
-
- uint8_t *buff = &(data[offset]);
- int bytesread = 0;
- NumConversions Conv;
- int tmp = Conv.ByteToInt(buff, bytesread);
- int n = sizeof((char*)&tmp);
- //char *tmpC = DBG_NEW char[n];
- char *tmpC = new char[n];
- Conv.getchar(tmp, n, tmpC);
- char *tagtype = new char[n + 1];
- //char *tagtype = DBG_NEW char[n + 1];
- strncpy_s(tagtype, n + 1, tmpC, n);
- if (strcmp(tagtype, "text") != 0)
- {
- throw std::exception("invalid Tag Name");
- strstr << "";
- *textstr = strstr.str();
- return;
- }
- if (tagtype != NULL)
- {
- delete[] tagtype;
- tagtype = NULL;
- }
- if (tmpC != NULL)
- {
- delete[]tmpC;
- tmpC = NULL;
- }
- bytesread += 8;
- uint8_t tmp1;
- for (int i = bytesread; i < data_size; ++i)
- {
- tmp1 = buff[i];
- strstr.put(tmp1);
- }
- *textstr = strstr.str();
- return;
-}
-void Tango::ColorLib::ColorConverter::read_text_description_type(int offset, int data_size, std::string textdescstr, uint8_t *data)
-{
- // 0 - 3 'desc'
- // 4 - 7 reserved, must be 0
- // 8 - 11 ASCII invariant description count, including terminating NULL
- // 12 - ASCII invariant description
- uint8_t *buff = &(data[offset]);
- int bytesread = 0;
- NumConversions Conv;
- int tmp = Conv.ByteToInt(buff, bytesread);
- int n = sizeof((char*)&tmp);
- //char *tmpC= DBG_NEW char[n];
- char *tmpC = new char[n];
- Conv.getchar(tmp, n, tmpC);
- char *tagtype = new char[n + 1];
- //char *tagtype = DBG_NEW char[n + 1];
- strncpy_s(tagtype, n + 1, tmpC, n);
- std::stringstream strstr;
- if (strcmp(tagtype, "desc") != 0)
- {
- throw std::exception("invalid Tag Name");
- strstr << "";
- textdescstr = strstr.str();
- return;
- }
- if (tagtype != NULL)
- {
- delete[] tagtype;
- tagtype = NULL;
- }
- if (tmpC != NULL)
- {
- delete[]tmpC;
- tmpC = NULL;
- }
- bytesread += 8;
- int count = Conv.ByteToInt(buff, bytesread);
- bytesread += 4;
- uint8_t tmp1;
- for (int i = 0; i < count - 1; ++i)
- {
- tmp1 = buff[bytesread + i];
- strstr << tmp1;
- }
- textdescstr = strstr.str();
- return;
-}
/*void Tango::ColorLib::ColorConverter::CompareWhitePoints()
{
@@ -2602,23 +2062,18 @@ size_t Tango::ColorLib::ColorConverter::P_IsInGamut(uint8_t * input_buffer, size
CAM02CS CS = UCS;
m_Conv02 = new ColorConvert(IL, IL, Y_b, L_A, sur, CS);
//m_Conv02 = DBG_NEW ColorConvert(IL, IL, Y_b, L_A, sur, CS);
- SetnA2BnSepIn(m_A2BTransform->GetSeparationsIn());
- SetnA2BnSepOut(m_A2BTransform->GetSeparationsOut());
- SetnB2AnSepIn(m_B2ATransform->GetSeparationsIn());
- SetnB2AnSepOut(m_B2ATransform->GetSeparationsOut());
- SetNumberOfInks(m_nB2AnSepOut);
// Compare Strip White point to Color Table White Point
//CompareWhitePoints();
- if (numofInks != m_nB2AnSepOut)
+ if (numofInks != m_nInks)
throw std::exception("Number of available inks does not match ink tables");
- VectorXd InkOut(m_nB2AnSepOut);
+ VectorXd InkOut(m_nInks);
VectorXd RGBOut(3);
VectorXd LabOut(3);
- VectorXd NLInkOut(m_nB2AnSepOut);
- VectorXd Volume(m_nB2AnSepOut);
+ VectorXd NLInkOut(m_nInks);
+ VectorXd Volume(m_nInks);
C_RGB_XYZ_Lab DataLab;
//SURROUND sur = m_Conv02->getSurround();
@@ -2779,6 +2234,7 @@ size_t Tango::ColorLib::ColorConverter::GenerateGradient(uint8_t * input_buffer,
conversionOutput->has_haserror = false;
//Get segment length...
double segmentLength = conversionInput->segmentlength;
+ m_colortable = new ColorTable();
PrepareGradient(conversionInput, conversionOutput);
//Get liquid types info...
/* InputLiquid* cyan = NULL;
@@ -2824,23 +2280,27 @@ size_t Tango::ColorLib::ColorConverter::GenerateGradient(uint8_t * input_buffer,
void Tango::ColorLib::ColorConverter::fillGradientStops(GradientConversionInput *conversionInput)
{
+ C_RGB_XYZ_Lab RGB;
+ C_RGB_XYZ_Lab Lab;
for (int i = 0; i < m_nGradStops; ++i)
{
switch (conversionInput->stops[i]->colorspace)
{
case COLOR_SPACE__RGB: //Case RGB
- m_GradStops[i].RGB.Set(conversionInput->stops[i]->red, conversionInput->stops[i]->green, conversionInput->stops[i]->blue);
- m_GradStops[i].colorspace = COLOR_SPACE__RGB;
- m_GradStops[i].offset = conversionInput->stops[i]->offset;
+ RGB = C_RGB_XYZ_Lab(conversionInput->stops[i]->red, conversionInput->stops[i]->green, conversionInput->stops[i]->blue);
+ m_GradStops[i].Set_RGB(RGB);
+ m_GradStops[i].Set_ColorSpace(COLOR_SPACE__RGB);
+ m_GradStops[i].Set_Offset(conversionInput->stops[i]->offset);
break;
case COLOR_SPACE__LAB: //Case LAB
- m_GradStops[i].Lab.Set(conversionInput->stops[i]->l, conversionInput->stops[i]->a, conversionInput->stops[i]->b);
- m_GradStops[i].colorspace = COLOR_SPACE__LAB;
- m_GradStops[i].offset = conversionInput->stops[i]->offset;
+ Lab = C_RGB_XYZ_Lab(conversionInput->stops[i]->l, conversionInput->stops[i]->a, conversionInput->stops[i]->b);
+ m_GradStops[i].Set_Lab(Lab);
+ m_GradStops[i].Set_ColorSpace(COLOR_SPACE__LAB);
+ m_GradStops[i].Set_Offset(conversionInput->stops[i]->offset);
break;
case COLOR_SPACE__Volume: //Case Volume
- m_GradStops[i].colorspace = COLOR_SPACE__Volume;
- m_GradStops[i].offset = conversionInput->stops[i]->offset;
+ m_GradStops[i].Set_ColorSpace(COLOR_SPACE__Volume);
+ m_GradStops[i].Set_Offset(conversionInput->stops[i]->offset);
for (int j = 0; j < (int)conversionInput->stops[i]->n_liquidvolumes; j++)
{
LiquidVolume* liquidVolume = conversionInput->stops[i]->liquidvolumes[j];
@@ -2848,16 +2308,16 @@ void Tango::ColorLib::ColorConverter::fillGradientStops(GradientConversionInput
switch (liquidVolume->liquidtype)
{
case LIQUID_TYPE__Cyan:
- m_GradStops[i].Volume[0] = liquidVolume->volume;
+ m_GradStops[i].SetVolumeValue(liquidVolume->volume,0);
break;
case LIQUID_TYPE__Magenta:
- m_GradStops[i].Volume[1] = liquidVolume->volume;
+ m_GradStops[i].SetVolumeValue(liquidVolume->volume, 1);
break;
case LIQUID_TYPE__Yellow:
- m_GradStops[i].Volume[2] = liquidVolume->volume;
+ m_GradStops[i].SetVolumeValue(liquidVolume->volume, 2);
break;
case LIQUID_TYPE__Black:
- m_GradStops[i].Volume[3] = liquidVolume->volume;
+ m_GradStops[i].SetVolumeValue(liquidVolume->volume, 3);
break;
default:
throw std::exception("could not fill all volumes");
@@ -2869,12 +2329,12 @@ void Tango::ColorLib::ColorConverter::fillGradientStops(GradientConversionInput
}
-void Tango::ColorLib::ColorConverter::findStops(GradStruct m_GradStop1, GradStruct m_GradStop2, double dEThr, int ninterstops,
+void Tango::ColorLib::ColorConverter::findStops(Gradient &GradStop1, Gradient &GradStop2, double dEThr, int ninterstops,
int &nOut, double **VecRGBOut, double **VecLabOut, double *posOut)
{
ColorConvert CConvertD65(D65, D65);
- C_RGB_XYZ_Lab RGBStart = m_GradStop1.RGB;
- C_RGB_XYZ_Lab RGBEnd = m_GradStop2.RGB;
+ C_RGB_XYZ_Lab RGBStart = GradStop1.Get_RGB();
+ C_RGB_XYZ_Lab RGBEnd = GradStop2.Get_RGB();
C_RGB_XYZ_Lab LowLab(0, -128, -128);
C_RGB_XYZ_Lab HighLab(100, 127, 127);
C_RGB_XYZ_Lab LowRGB(0, 0, 0);
@@ -2895,7 +2355,7 @@ void Tango::ColorLib::ColorConverter::findStops(GradStruct m_GradStop1, GradStru
// make a matching Lab vector;
VecRGBOut_tmp[0] = C_RGB_XYZ_Lab(RGBStart);
- VecLabOut_tmp[0] = C_RGB_XYZ_Lab(m_GradStop1.Lab);
+ VecLabOut_tmp[0] = C_RGB_XYZ_Lab(GradStop1.Get_Lab());
for (int i = 1; i <= nsubdiv; ++i)
{
@@ -3011,10 +2471,10 @@ void Tango::ColorLib::ColorConverter::ConvertGradStoptoVolume(InputCoordinates*
size_t nInks = 0;
C_RGB_XYZ_Lab DataLab;
- VectorXd InkOut(m_nB2AnSepOut);
+ VectorXd InkOut(m_nInks);
double normFactor = 1;
if (!same_regions)
- normFactor = m_NormFactor;
+ normFactor = m_colortable->GetNormFactor();
if (colorspace ==COLOR_SPACE__RGB)
{
@@ -3036,20 +2496,20 @@ void Tango::ColorLib::ColorConverter::ConvertGradStoptoVolume(InputCoordinates*
//convert to inks
int GamutRegion;
- double *InkOutP = new double[m_nB2AnSepOut];
+ double *InkOutP = new double[m_nInks];
if(same_regions)
- m_B2ARTransform->evalLab2InkP(LabIn, InkOutP, GamutRegion); //InkOut is in units of 16 bits
+ m_colortable->m_B2ARTransform->evalLab2InkP(LabIn, InkOutP, GamutRegion); //InkOut is in units of 16 bits
else
- m_B2ATransform->evalLab2InkP(LabIn, InkOutP, GamutRegion); //InkOut is in units of 16 bits
+ m_colortable->m_B2ATransform->evalLab2InkP(LabIn, InkOutP, GamutRegion); //InkOut is in units of 16 bits
//Convert InkOut to Linear via initial calibration Tables
//Initial calibration tables are the ones that were included in the color table
- for (int i = 0; i < m_nB2AnSepOut; ++i)
+ for (int i = 0; i < m_nInks; ++i)
{
InkOutP[i] *= normFactor;
- if (InkOutP[i] <= m_GamutRegionMaxLim[0])
+ if (InkOutP[i] <= m_NormGamutRegionMaxLim[0])
{
- m_LinCurves->m_InterpCurves[i].Eval(InkOutP[i] * 655.35, InkOutP[i]);
+ m_colortable->m_LinCurves->m_InterpCurves[i].Eval(InkOutP[i] * 655.35, InkOutP[i]);
InkOutP[i] /= 655.35;
}
}
@@ -3082,18 +2542,18 @@ void Tango::ColorLib::ColorConverter::ConvertGradStoptoVolume(InputCoordinates*
//convert to Inks
int GamutRegion;
- double *InkOutP = new double[m_nB2AnSepOut];
+ double *InkOutP = new double[m_nInks];
if(same_regions)
- m_B2ARTransform->evalLab2InkP(LabIn, InkOutP, GamutRegion); //InkOut is in the [0-100] interval
+ m_colortable->m_B2ARTransform->evalLab2InkP(LabIn, InkOutP, GamutRegion); //InkOut is in the [0-100] interval
else
- m_B2ATransform->evalLab2InkP(LabIn, InkOutP, GamutRegion); //InkOut is in the [0-100] interval
+ m_colortable->m_B2ATransform->evalLab2InkP(LabIn, InkOutP, GamutRegion); //InkOut is in the [0-100] interval
- for (int i = 0; i < m_nB2AnSepOut; ++i)
+ for (int i = 0; i < m_nInks; ++i)
{
InkOutP[i] *= normFactor;
- if (InkOutP[i] <= m_GamutRegionMaxLim[0])
+ if (InkOutP[i] <= m_NormGamutRegionMaxLim[0])
{
- m_LinCurves->m_InterpCurves[i].Eval(InkOutP[i] * 655.35, InkOutP[i]);
+ m_colortable->m_LinCurves->m_InterpCurves[i].Eval(InkOutP[i] * 655.35, InkOutP[i]);
InkOutP[i] /= 655.35;
}
}
@@ -3115,9 +2575,9 @@ void Tango::ColorLib::ColorConverter::ConvertGradStoptoVolume(InputCoordinates*
throw std::exception("Unsupported Color Space");
return;
}
- VectorXd NLInkOut(m_nB2AnSepOut);
- VectorXd VolumeOut(m_nB2AnSepOut);
- double *InkOutL = new double[m_nB2AnSepOut];
+ VectorXd NLInkOut(m_nInks);
+ VectorXd VolumeOut(m_nInks);
+ double *InkOutL = new double[m_nInks];
ConvertToNLInks(InkOut, NLInkOut);
LimitInks(NLInkOut, InkOutL);
NLInkPToVolume(DoubleToVector(InkOutL, m_nInks), Volume);
@@ -3132,32 +2592,25 @@ void Tango::ColorLib::ColorConverter::ConvertGradStoptoVolume(InputCoordinates*
return;
}
-void Tango::ColorLib::ColorConverter::SetNormFactor()
-{
- m_NormFactor = m_GamutRegionMaxLim[m_nProcessRanges - 1] / m_GamutRegionMaxLim[0];
-}
-
-void Tango::ColorLib::ColorConverter::SetInverseNormFactor()
-{
- if (m_NormFactor <= 0)
- m_InvNormFactor = -1;
- else
- m_InvNormFactor = 1.0 / m_NormFactor;
-}
void Tango::ColorLib::ColorConverter::PrepareGradient(GradientConversionInput* conversionInput, GradientConversionOutput *conversionOutput)
{
//fill input stops...
+
m_nGradStops = conversionInput->n_stops;
- m_GradStops = new GradStruct[m_nGradStops];
+ int nInks = conversionInput->n_inputliquids;
+ m_nVolumes = nInks;
+ m_GradStops = new Gradient[m_nGradStops];
+ for (int i = 0; i < m_nGradStops; ++i)
+ m_GradStops[i].SetVolumeSize(nInks);
+
InputCoordinates **inputcoordinates = (InputCoordinates**)malloc(sizeof(InputCoordinates*)*m_nGradStops);
- double *InkOutL = new double[m_nB2AnSepOut];
for (int i = 0; i < m_nGradStops; ++i)
{
inputcoordinates[i] = (InputCoordinates*)malloc(sizeof(InputCoordinates));
input_coordinates__init(inputcoordinates[i]);
}
- m_nVolumes = conversionInput->stops[0]->n_liquidvolumes;
+
fillGradientStops(conversionInput);
GradInput2InputCoords(conversionInput, inputcoordinates);
@@ -3165,13 +2618,17 @@ void Tango::ColorLib::ColorConverter::PrepareGradient(GradientConversionInput* c
SetStripWhitepoint(conversionInput->threadl, conversionInput->threada, conversionInput->threadb);
bool has_forwarddata = conversionInput->has_forwarddata;
uint8_t *data = conversionInput->forwarddata.data;
- int nprocessranges = conversionInput->n_processranges;
- readColorTables(has_forwarddata, data, nprocessranges);
-
+ m_nProcessRanges = conversionInput->n_processranges;
+ m_colortable->InitColorTables(has_forwarddata, data, m_nProcessRanges);
+ SetNumberofInks(m_colortable->GetnA2BnSepOut());
+ m_NormGamutRegionMaxLim = new double[m_nProcessRanges];
+ double *tmpVal = m_colortable->GetNormGamutRegionMaxLim();
+ for (int i = 0; i < m_nProcessRanges; ++i)
+ m_NormGamutRegionMaxLim[i] = tmpVal[i];
int n_inputliquids = conversionInput->n_inputliquids;
InputLiquid **inputliquid = conversionInput->inputliquids;
readCalibrationTables(inputliquid, n_inputliquids);
- if (m_TableVersion <= 1)
+ if (m_colortable->GetTableVersion() <= 1)
{
throw std::exception("Color Table Version does not support gradients\0");
}
@@ -3193,128 +2650,55 @@ void Tango::ColorLib::ColorConverter::PrepareGradient(GradientConversionInput* c
Illum IL = D65;
SURROUND sur = average;
CAM02CS CS = UCS;
- m_Conv02 = new ColorConvert(IL, IL, Y_b, L_A, sur, CS);
- SetnA2BnSepIn(m_A2BTransform->GetSeparationsIn());
- SetnA2BnSepOut(m_A2BTransform->GetSeparationsOut());
- SetnB2AnSepIn(m_B2ATransform->GetSeparationsIn());
- SetnB2AnSepOut(m_B2ATransform->GetSeparationsOut());
- SetNumberOfInks(m_nB2AnSepOut);
+ if (m_Conv02 == NULL)
+ m_Conv02 = new ColorConvert(IL, IL, Y_b, L_A, sur, CS);
+
// Compare Strip White point to Color Table White Point
//CompareWhitePoints();
ColorConvert CConvertD65(D65, D65); //Destination, source
if (n_inputliquids != m_nInks)
throw std::exception("Number of available inks does not match ink tables\0");
- //Convert maxInkUptake to percentages
- if(m_ProcessRangesMaxP == NULL)
+ if (m_ProcessRangesMaxP == NULL)
m_ProcessRangesMaxP = new double[m_nProcessRanges];
for (int i = 0; i < m_nProcessRanges; ++i)
{
m_ProcessRangesMaxP[i] = conversionInput->processranges[i]->maxinkuptake;
}
- NormGamutRegionMaxLim();
- if (m_NormFactor <= 0.0)
- {
- SetNormFactor();
- SetInverseNormFactor();
- }
- VectorXd InkOut(m_nB2AnSepOut);
+
+ VectorXd InkOut(m_nInks);
VectorXd RGBOut(3);
VectorXd LabOut(3);
- VectorXd NLInkOut(m_nB2AnSepOut);
- VectorXd Volume(m_nB2AnSepOut);
- VectorXd VolumeOut(m_nB2AnSepOut);
+ VectorXd NLInkOut(m_nInks);
+ VectorXd Volume(m_nInks);
+ VectorXd VolumeOut(m_nInks);
//set maxNlPerCM
- VectorXd NlperCM(m_nB2AnSepOut);
- double *LabOutV = new double[3];
- double *LabOutFinal = new double[3];
+ VectorXd NlperCM(m_nInks);
NlperCM.setZero();
m_maxNlPerCM = NlperCM;
- for (int i = 0; i < m_nB2AnSepOut; ++i)
+ for (int i = 0; i < m_nInks; ++i)
SetMaxNLperCM(conversionInput->inputliquids[i]->maxnanoliterpercentimeter, i);
- m_nVolumes = m_nB2AnSepOut;
+ //m_nVolumes = m_nB2AnSepOut;
int GamutRegion = 0;
- for (int i = 0; i < m_nGradStops; ++i)
- {
- if (m_GradStops[i].colorspace == COLOR_SPACE__Volume || m_GradStops[i].colorspace == COLOR_SPACE__Catalog)
- { //Convert volume to Lab
- //Convert lab to rgb
- ConvertVolumeToRGBDisplay(inputcoordinates[i], m_nProcessRanges, m_GradStops[i].colorspace, Volume, RGBOut, LabOut, GamutRegion);
- //store data
- m_GradStops[i].Lab.Set(LabOut(0), LabOut(1), LabOut(2));
- m_GradStops[i].RGB.Set(RGBOut(0), RGBOut(1), RGBOut(2));
- m_GradStops[i].GamutRegion = GamutRegion;
- m_GradStops[i].InGamut = true;
- }
- else
- {
- ConvertColorToLinearInks(inputcoordinates[i], m_GradStops[i].colorspace, InkOut, RGBOut, LabOut, GamutRegion, InGamut);
- //Inks are in Linear Space , convert to nonlinear by using Calibration Tables,
- // Right now calibration is in the [0-100] range, values exceeding [0-100] are not transformed
-
- ConvertToNLInks(InkOut, NLInkOut);
- LimitInks(NLInkOut, InkOutL);
- NLInkPToVolume(DoubleToVector(InkOutL, m_nInks), Volume);
- GamutRegion = GetGamutRegion(Volume, m_ProcessRangesMaxP);
- NLcmtoPercentage(Volume, Volume);
-
- //fill data
- //fill volume
- //allocate m_GradStops[i].Volume
- m_GradStops[i].Volume = new double[m_nB2AnSepOut];
- for (int j = 0; j < m_nB2AnSepOut; ++j)
- m_GradStops[i].Volume[j] = Volume[j];
- m_GradStops[i].GamutRegion = GamutRegion;
- m_GradStops[i].InGamut = InGamut;
- //LabOut and RGBOut might be different if the input was out of gamut
- m_GradStops[i].Lab.Set(LabOut(0), LabOut(1), LabOut(2));
- m_GradStops[i].RGB.Set(RGBOut(0), RGBOut(1), RGBOut(2));
- }
- //Convert Lab Values to Relative Colorimetric. These values will be used in the Gradient Volume calculation.
- VectorToDouble(LabOut, LabOutV);
-/* if (m_AdaptWP)
- {
- CConvertD65.ChangeWP(LabOutV, LabOutV, m_whitepointXYZ_CT, m_whitepointXYZ_Strip); //to Color Tables
- }
- */
- //double *LabInFinal2 = DBG_NEW double[3];
-// CConvertD65.ChangeWP(LabOutV, LabOutFinal, m_WP, m_whitepointXYZ_CT); //LabInFinal is in Relative Colorimetric Space
- CConvertD65.ChangeWP(LabOutV, LabOutFinal, m_WP, m_whitepointXYZ_Strip); //LabInFinal is in Relative Colorimetric Space
- m_GradStops[i].Lab.Set(LabOutFinal[0], LabOutFinal[1], LabOutFinal[2]);
- }
- //free vectors
- if (LabOutV == NULL)
- {
- delete[] LabOutV;
- LabOutV = NULL;
- }
- if (LabOutFinal == NULL)
- {
- delete[] LabOutFinal;
- LabOutFinal = NULL;
- }
- if (InkOutL == NULL)
- {
- delete[] InkOutL;
- InkOutL = NULL;
- }
+ ProcessGradientStops(inputcoordinates);
//are all stops in the same region?
int maxreg = -10;
int minreg = 10;
for (int i = 0; i < m_nGradStops; ++i)
{
- maxreg = std::max(maxreg, m_GradStops[i].GamutRegion);
- minreg = std::min(minreg, m_GradStops[i].GamutRegion);
+ GamutRegion = m_GradStops[i].Get_GamutRegion();
+ maxreg = std::max(maxreg, GamutRegion);
+ minreg = std::min(minreg, GamutRegion);
}
//Choose Gamut Region for Gradient calculation
-
+
bool same_regions = true;
- if ((maxreg != minreg) & (maxreg>0))
+ if ((maxreg != minreg) & (maxreg > 0))
same_regions = false;
double dEThr = 0.8;
//find intermediate points
- int ninterstops = 300;
+ int ninterstops = 300;
double **VecRGBOut = new double*[ninterstops];
double **VecLabOut = new double*[ninterstops];
double *posOut = new double[ninterstops];
@@ -3336,71 +2720,72 @@ void Tango::ColorLib::ColorConverter::PrepareGradient(GradientConversionInput* c
AllRGBOut_tmp[i] = new double[3];
AllLabOut_tmp[i] = new double[3];
}
- AllRGBOut_tmp[0][0] = m_GradStops[0].RGB.Get_x();
- AllRGBOut_tmp[0][1] = m_GradStops[0].RGB.Get_y();
- AllRGBOut_tmp[0][2] = m_GradStops[0].RGB.Get_z();
- AllLabOut_tmp[0][0] = m_GradStops[0].Lab.Get_x();
- AllLabOut_tmp[0][1] = m_GradStops[0].Lab.Get_y();
- AllLabOut_tmp[0][2] = m_GradStops[0].Lab.Get_z();
- AllPos_tmp[0] = m_GradStops[0].offset;
+ AllRGBOut_tmp[0][0] = m_GradStops[0].Get_RGB().Get_x();
+ AllRGBOut_tmp[0][1] = m_GradStops[0].Get_RGB().Get_y();
+ AllRGBOut_tmp[0][2] = m_GradStops[0].Get_RGB().Get_z();
+ AllLabOut_tmp[0][0] = m_GradStops[0].Get_Lab().Get_x();
+ AllLabOut_tmp[0][1] = m_GradStops[0].Get_Lab().Get_y();
+ AllLabOut_tmp[0][2] = m_GradStops[0].Get_Lab().Get_z();
+ AllPos_tmp[0] = m_GradStops[0].Get_Offset();
int ncountStops = 0;
int nPosStops = 0;
double dOffset = 0;
GradOffset OffsetType = EqSpaced;
- for (int i = 0; i < m_nGradStops - 1; ++i)
+
+ for (int iStop = 0; iStop < m_nGradStops - 1; ++iStop)
{
- findStops(m_GradStops[i], m_GradStops[i + 1], dEThr, ninterstops, nOut, VecRGBOut, VecLabOut, posOut);
+ findStops(m_GradStops[iStop], m_GradStops[iStop + 1], dEThr, ninterstops, nOut, VecRGBOut, VecLabOut, posOut);
switch (OffsetType)
{
case EqSpaced:
- if (i == m_nGradStops - 2)
- dOffset = (m_GradStops[i + 1].offset - m_GradStops[i].offset)*GradientEndThr / (nOut - 1);
+ if (iStop == m_nGradStops - 2)
+ dOffset = (m_GradStops[iStop + 1].Get_Offset() - m_GradStops[iStop].Get_Offset())*GradientEndThr / (nOut - 1);
else
- dOffset = (m_GradStops[i + 1].offset - m_GradStops[i].offset) / (nOut - 1);
- for (int j = 1; j < nOut; ++j)
+ dOffset = (m_GradStops[iStop + 1].Get_Offset() - m_GradStops[iStop].Get_Offset()) / (nOut - 1);
+ for (int jPos = 1; jPos < nOut; ++jPos)
{
nPosStops++;
- AllPos_tmp[nPosStops] = m_GradStops[i].offset + dOffset * j;
+ AllPos_tmp[nPosStops] = m_GradStops[iStop].Get_Offset() + dOffset * jPos;
}
break;
case dESpaced:
- if (i == m_nGradStops - 2)
- dOffset = (m_GradStops[i + 1].offset - m_GradStops[i].offset)*GradientEndThr / posOut[nOut - 1];
+ if (iStop == m_nGradStops - 2)
+ dOffset = (m_GradStops[iStop + 1].Get_Offset() - m_GradStops[iStop].Get_Offset())*GradientEndThr / posOut[nOut - 1];
else
- dOffset = (m_GradStops[i + 1].offset - m_GradStops[i].offset) / posOut[nOut - 1];
- for (int j = 0; j < nOut; ++j)
+ dOffset = (m_GradStops[iStop + 1].Get_Offset() - m_GradStops[iStop].Get_Offset()) / posOut[nOut - 1];
+ for (int jPos = 0; jPos < nOut; ++jPos)
{
nPosStops++;
- AllPos_tmp[nPosStops] = m_GradStops[i].offset + dOffset * posOut[j];
+ AllPos_tmp[nPosStops] = m_GradStops[iStop].Get_Offset() + dOffset * posOut[jPos];
}
break;
}
//store the stops in temporary vector
- for (int i = 1; i < nOut; ++i)
+ for (int iCount = 1; iCount < nOut; ++iCount)
{
ncountStops++;
- for (int j = 0; j < 3; ++j)
+ for (int jCS = 0; jCS < 3; ++jCS)
{
- AllRGBOut_tmp[ncountStops][j] = VecRGBOut[i][j];
- AllLabOut_tmp[ncountStops][j] = VecLabOut[i][j];
+ AllRGBOut_tmp[ncountStops][jCS] = VecRGBOut[iCount][jCS];
+ AllLabOut_tmp[ncountStops][jCS] = VecLabOut[iCount][jCS];
}
}
}
if (VecRGBOut != NULL)
{
- for (int i = 0; i < nOut; ++i)
+ for (int i = 0; i < ninterstops; ++i)
delete[]VecRGBOut[i];
delete[]VecRGBOut;
}
if (VecLabOut != NULL)
{
- for (int i = 0; i < nOut; ++i)
+ for (int i = 0; i < ninterstops; ++i)
delete[]VecLabOut[i];
delete[]VecLabOut;
VecLabOut = NULL;
}
- if (VecLabOut != NULL)
+ if (posOut != NULL)
{
delete[]posOut;
posOut = NULL;
@@ -3414,94 +2799,90 @@ void Tango::ColorLib::ColorConverter::PrepareGradient(GradientConversionInput* c
InputCoordinates **SubStops = (InputCoordinates**)malloc(sizeof(InputCoordinates*)*nTotalStops);
//Calculate and store
- for (int i = 0; i < nTotalStops; ++i)
+ for (int iTStops = 0; iTStops < nTotalStops; ++iTStops)
{
- SubStops[i] = (InputCoordinates*)malloc(sizeof(InputCoordinates));
- input_coordinates__init(SubStops[i]);
- SubStops[i]->l = AllLabOut_tmp[i][0];
- SubStops[i]->a = AllLabOut_tmp[i][1];
- SubStops[i]->b = AllLabOut_tmp[i][2];
- SubStops[i]->red = (int)round(AllRGBOut_tmp[i][0]);
- SubStops[i]->green = (int)round(AllRGBOut_tmp[i][1]);
- SubStops[i]->blue = (int)round(AllRGBOut_tmp[i][2]);
+ SubStops[iTStops] = (InputCoordinates*)malloc(sizeof(InputCoordinates));
+ input_coordinates__init(SubStops[iTStops]);
+ SubStops[iTStops]->l = AllLabOut_tmp[iTStops][0];
+ SubStops[iTStops]->a = AllLabOut_tmp[iTStops][1];
+ SubStops[iTStops]->b = AllLabOut_tmp[iTStops][2];
+ SubStops[iTStops]->red = (int)round(AllRGBOut_tmp[iTStops][0]);
+ SubStops[iTStops]->green = (int)round(AllRGBOut_tmp[iTStops][1]);
+ SubStops[iTStops]->blue = (int)round(AllRGBOut_tmp[iTStops][2]);
}
-GradientOutputStop** outputStops = (GradientOutputStop**)malloc(sizeof(GradientOutputStop*) * nTotalStops);
-conversionOutput->stops = outputStops;
-conversionOutput->n_stops = nTotalStops;
+ GradientOutputStop** outputStops = (GradientOutputStop**)malloc(sizeof(GradientOutputStop*) * nTotalStops);
+ conversionOutput->stops = outputStops;
+ conversionOutput->n_stops = nTotalStops;
-ColorSpace SubStopsCS = COLOR_SPACE__LAB;
-//double NormFactor = m_ProcessRangesMaxP[m_nProcessRanges - 1] / 100.0;
-VectorXd VolumeStop(m_nB2AnSepOut);
-MatrixXd MatVolume(ncountStops, m_nB2AnSepOut);
-for (int i = 0; i < ncountStops; ++i)
-{
- GradientOutputStop *stop = (GradientOutputStop*)malloc(sizeof(GradientOutputStop));
- gradient_output_stop__init(stop);
- ConvertGradStoptoVolume(SubStops[i], SubStopsCS,
- VolumeStop, GamutRegion, same_regions);
- //start filling Output
- fillStop(stop, VolumeStop, GamutRegion, AllPos_tmp[i]);
- MatVolume.row(i) = VolumeStop;
- outputStops[i] = stop;
-}
-//Smooth Volumes
-VectorXd VIn(ncountStops);
-VectorXd VOut(ncountStops);
-int FilterWidth = 7;
-for (int i = 0; i < m_nB2AnSepOut; ++i)
-{
- for (int j = 0; j < ncountStops; ++j)
- VIn(j) = MatVolume(j, i);
- SmoothCurveData(VIn, VOut, FilterWidth);
- for (int j = 0; j < ncountStops; ++j)
- outputStops[j]->outputliquids[i]->volume = VOut(j);
-}
-//Temp Output
-/*for (int i = 0; i < ncountStops; ++i)
-{
- fprintf(stdout, "%d\t%6.3f\t%6.3f\t%6.3f\t%6.3f\t%6.3f\n", i, outputStops[i]->offset, outputStops[i]->outputliquids[0]->volume,
- outputStops[i]->outputliquids[1]->volume, outputStops[i]->outputliquids[2]->volume, outputStops[i]->outputliquids[3]->volume);
-}*/
-//release memory
-if(AllLabOut_tmp != NULL)
-{
- for (int i = 0; i < nmaxstops; ++i)
- delete[] AllLabOut_tmp[i];
- delete[] AllLabOut_tmp;
- AllLabOut_tmp = NULL;
-}
-if (AllRGBOut_tmp != NULL)
-{
- for (int i = 0; i < nmaxstops; ++i)
- delete[] AllRGBOut_tmp[i];
- delete[] AllRGBOut_tmp;
- AllRGBOut_tmp = NULL;
-}
-if (AllPos_tmp != NULL)
-{
- delete[] AllPos_tmp;
- AllPos_tmp = NULL;
-}
+ ColorSpace SubStopsCS = COLOR_SPACE__LAB;
+ //double NormFactor = m_ProcessRangesMaxP[m_nProcessRanges - 1] / 100.0;
+ VectorXd VolumeStop(m_nInks);
+ MatrixXd MatVolume(ncountStops, m_nInks);
+ for (int iS = 0; iS < ncountStops; ++iS)
+ {
+ GradientOutputStop *stop = (GradientOutputStop*)malloc(sizeof(GradientOutputStop));
+ gradient_output_stop__init(stop);
+ ConvertGradStoptoVolume(SubStops[iS], SubStopsCS,
+ VolumeStop, GamutRegion, same_regions);
+ //start filling Output
+ fillStop(stop, VolumeStop, GamutRegion, AllPos_tmp[iS]);
+ MatVolume.row(iS) = VolumeStop;
+ outputStops[iS] = stop;
+ }
+ //Smooth Volumes
+ VectorXd VIn(ncountStops);
+ VectorXd VOut(ncountStops);
+ int FilterWidth = 7;
+ for (int iSep = 0; iSep < m_nInks; ++iSep)
+ {
+ for (int jStop = 0; jStop < ncountStops; ++jStop)
+ VIn(jStop) = MatVolume(jStop, iSep);
+ SmoothCurveData(VIn, VOut, FilterWidth);
+ for (int jS = 0; jS < ncountStops; ++jS)
+ outputStops[jS]->outputliquids[iSep]->volume = VOut(jS);
+ }
+ //Temp Output
+ /*for (int i = 0; i < ncountStops; ++i)
+ {
+ fprintf(stdout, "%d\t%6.3f\t%6.3f\t%6.3f\t%6.3f\t%6.3f\n", i, outputStops[i]->offset, outputStops[i]->outputliquids[0]->volume,
+ outputStops[i]->outputliquids[1]->volume, outputStops[i]->outputliquids[2]->volume, outputStops[i]->outputliquids[3]->volume);
+ }*/
+ //release memory
+ if (AllLabOut_tmp != NULL)
+ {
+ for (int i = 0; i < nmaxstops; ++i)
+ delete[] AllLabOut_tmp[i];
+ delete[] AllLabOut_tmp;
+ AllLabOut_tmp = NULL;
+ }
+ if (AllRGBOut_tmp != NULL)
+ {
+ for (int i = 0; i < nmaxstops; ++i)
+ delete[] AllRGBOut_tmp[i];
+ delete[] AllRGBOut_tmp;
+ AllRGBOut_tmp = NULL;
+ }
+ if (AllPos_tmp != NULL)
+ {
+ delete[] AllPos_tmp;
+ AllPos_tmp = NULL;
+ }
-for (int i=0; i< m_nGradStops; ++i)
- input_coordinates__free_unpacked(inputcoordinates[i], NULL);
-free(inputcoordinates);
-inputcoordinates = NULL;
-for (int i = 0; i < nTotalStops; ++i)
- input_coordinates__free_unpacked(SubStops[i], NULL);
-free(SubStops);
-SubStops = NULL;
+ for (int i = 0; i < m_nGradStops; ++i)
+ input_coordinates__free_unpacked(inputcoordinates[i], NULL);
+ free(inputcoordinates);
+ inputcoordinates = NULL;
+ for (int i = 0; i < nTotalStops; ++i)
+ input_coordinates__free_unpacked(SubStops[i], NULL);
+ free(SubStops);
+ SubStops = NULL;
}
-void Tango::ColorLib::ColorConverter::NormGamutRegionMaxLim()
-{
- double GamutRegionMaxLim0 = m_GamutRegionMaxLim[0];
- for (int i = 0; i < m_nProcessRanges; ++i)
- m_GamutRegionMaxLim[i] = 100 * m_GamutRegionMaxLim[i] / GamutRegionMaxLim0;
-}
+
+
void Tango::ColorLib::ColorConverter::fillStop(GradientOutputStop *&stop, VectorXd Volume, int GamutRegion, double Position)
{
@@ -3557,28 +2938,41 @@ void Tango::ColorLib::ColorConverter::GradInput2InputCoords(GradientConversionI
inputcoordinates[i]->has_a = true;
inputcoordinates[i]->has_b = true;
break;
- case COLOR_SPACE__Volume: //Case Volume
- for (int j = 0; j < (int)conversionInput->stops[i]->n_liquidvolumes; j++)
+ case COLOR_SPACE__Volume: //Case Volume
+ int size= (int)conversionInput->stops[i]->n_liquidvolumes;
+ InputLiquid** InputLiquidsIC = (InputLiquid**)malloc(sizeof(InputLiquid*) *size);
+ for (int j = 0; j < size; j++)
+ {
+ InputLiquidsIC[j] = (InputLiquid*)malloc(sizeof(InputLiquid));
+ input_liquid__init(InputLiquidsIC[j]);
+ }
+ for (size_t j= 0; j< (int)conversionInput->stops[i]->n_liquidvolumes; j++)
{
LiquidVolume* liquidVolume = conversionInput->stops[i]->liquidvolumes[j];
-
switch (liquidVolume->liquidtype)
{
case LIQUID_TYPE__Cyan:
- inputcoordinates[i]->inputliquids[0]->liquidtype = LIQUID_TYPE__Cyan;
- inputcoordinates[i]->inputliquids[0]->volume = liquidVolume->volume;
+// inputcoordinates[i]->inputliquids[0]->volume = liquidVolume->volume;
+ InputLiquidsIC[0]->volume = liquidVolume->volume;
+ InputLiquidsIC[0]->liquidtype = LIQUID_TYPE__Cyan;
+ break;
case LIQUID_TYPE__Magenta:
- inputcoordinates[i]->inputliquids[1]->liquidtype = LIQUID_TYPE__Magenta;
- inputcoordinates[i]->inputliquids[1]->volume = liquidVolume->volume;
+ InputLiquidsIC[1]->volume = liquidVolume->volume;
+ InputLiquidsIC[1]->liquidtype = LIQUID_TYPE__Magenta;
+ break;
case LIQUID_TYPE__Yellow:
- inputcoordinates[i]->inputliquids[2]->liquidtype = LIQUID_TYPE__Yellow;
- inputcoordinates[i]->inputliquids[2]->volume = liquidVolume->volume;
+ InputLiquidsIC[2]->volume = liquidVolume->volume;
+ InputLiquidsIC[2]->liquidtype = LIQUID_TYPE__Yellow;
+ break;
case LIQUID_TYPE__Black:
- inputcoordinates[i]->inputliquids[3]->liquidtype = LIQUID_TYPE__Black;
- inputcoordinates[i]->inputliquids[3]->volume = liquidVolume->volume;
+ InputLiquidsIC[3]->volume = liquidVolume->volume;
+ InputLiquidsIC[3]->liquidtype = LIQUID_TYPE__Black;
+ break;
}
+
}
- break;
+ inputcoordinates[i]->inputliquids = InputLiquidsIC;
+ inputcoordinates[i]->n_inputliquids = size;
}
}
}
@@ -3603,7 +2997,7 @@ int Tango::ColorLib::ColorConverter::GetGamutRegion(VectorXd Volume, double *Ga
int GamutRegion = 0;
for (int i = 0; i < m_nInks; ++i)
TotalVolume += Volume(i);
- for (int i=0; i<m_nGamutRegions; ++i)
+ for (int i=0; i< m_colortable->GetnGamutRegions(); ++i)
{
if (TotalVolume > GamutLimits[i])
GamutRegion++;
@@ -3626,4 +3020,89 @@ void Tango::ColorLib::ColorConverter::SmoothCurveData(VectorXd VIn, VectorXd &VO
}
for (int j = 0; j < Vlength; ++j)
VOut(j) = VIn(j);
+}
+
+void Tango::ColorLib::ColorConverter::ProcessGradientStops(InputCoordinates **inputcoordinates)
+{
+ VectorXd Volume(m_nInks);
+ VectorXd RGBOut(m_nInks);
+ VectorXd LabOut(m_nInks);
+ VectorXd InkOut(m_nInks);
+ VectorXd NLInkOut(m_nInks);
+ double * InkOutL = new double[m_nInks];
+ double * LabOutV = new double[3];
+ double * LabOutFinal = new double[3];
+
+ ColorConvert CConvertD65(D65, D65);
+
+ bool InGamut = true;
+ int GamutRegion = 0;
+ for (int i = 0; i < m_nGradStops; ++i)
+ {
+ if (m_GradStops[i].Get_ColorSpace() == COLOR_SPACE__Volume || m_GradStops[i].Get_ColorSpace() == COLOR_SPACE__Catalog)
+ { //Convert volume to Lab
+ //Convert lab to rgb
+ ConvertVolumeToRGBDisplay(inputcoordinates[i], m_nProcessRanges, m_GradStops[i].Get_ColorSpace(), Volume, RGBOut, LabOut, GamutRegion);
+ //store data
+ C_RGB_XYZ_Lab Lab(LabOut);
+ C_RGB_XYZ_Lab RGB(RGBOut);
+ m_GradStops[i].Set_Lab(LabOut);
+ m_GradStops[i].Set_RGB(RGBOut);
+ m_GradStops[i].Set_GamutRegion( GamutRegion);
+ m_GradStops[i].SetInGamut (true);
+ }
+ else
+ {
+ ConvertColorToLinearInks(inputcoordinates[i], m_GradStops[i].Get_ColorSpace(), InkOut, RGBOut, LabOut, GamutRegion, InGamut);
+ //Inks are in Linear Space , convert to nonlinear by using Calibration Tables,
+ // Right now calibration is in the [0-100] range, values exceeding [0-100] are not transformed
+
+ ConvertToNLInks(InkOut, NLInkOut);
+ LimitInks(NLInkOut, InkOutL);
+ NLInkPToVolume(DoubleToVector(InkOutL, m_nInks), Volume);
+ GamutRegion = GetGamutRegion(Volume, m_ProcessRangesMaxP);
+ NLcmtoPercentage(Volume, Volume);
+
+ //fill data
+ //fill volume
+ //allocate m_GradStops[i].Volume
+ C_RGB_XYZ_Lab Lab(LabOut);
+ C_RGB_XYZ_Lab RGB(RGBOut);
+ for (int j = 0; j < m_nInks; ++j)
+ m_GradStops[i].SetVolumeValue(Volume[j], j);
+ m_GradStops[i].Set_GamutRegion(GamutRegion);
+ m_GradStops[i].SetInGamut(InGamut);
+ //LabOut and RGBOut might be different if the input was out of gamut
+ m_GradStops[i].Set_Lab(LabOut);
+ m_GradStops[i].Set_RGB(RGBOut);
+ }
+ //Convert Lab Values to Relative Colorimetric. These values will be used in the Gradient Volume calculation.
+ VectorToDouble(LabOut, LabOutV);
+ /* if (m_AdaptWP)
+ {
+ CConvertD65.ChangeWP(LabOutV, LabOutV, m_whitepointXYZ_CT, m_whitepointXYZ_Strip); //to Color Tables
+ }
+ */
+ //double *LabInFinal2 = DBG_NEW double[3];
+ // CConvertD65.ChangeWP(LabOutV, LabOutFinal, m_WP, m_whitepointXYZ_CT); //LabInFinal is in Relative Colorimetric Space
+ CConvertD65.ChangeWP(LabOutV, LabOutFinal, m_WP, m_whitepointXYZ_Strip); //LabInFinal is in Relative Colorimetric Space
+ C_RGB_XYZ_Lab LabOut1(LabOutFinal[0], LabOutFinal[1], LabOutFinal[2]);
+ m_GradStops[i].Set_Lab(LabOut1);
+ }
+ //free vectors
+ if (LabOutV != NULL)
+ {
+ delete[] LabOutV;
+ LabOutV = NULL;
+ }
+ if (LabOutFinal != NULL)
+ {
+ delete[] LabOutFinal;
+ LabOutFinal = NULL;
+ }
+ if (InkOutL != NULL)
+ {
+ delete[] InkOutL;
+ InkOutL = NULL;
+ }
} \ No newline at end of file
diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/ColorConverter.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/ColorConverter.h
index 4563a2627..7aec6d993 100644
--- a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/ColorConverter.h
+++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/ColorConverter.h
@@ -8,6 +8,7 @@
#include "ColorTransf.h"
#include "ColorConvert.h"
#include "GBD.h"
+#include "CT_Header.h"
#include "ConversionOutput.pb-c.h"
#include "CalibrationData.pb-c.h"
#include "ConversionInput.pb-c.h"
@@ -17,11 +18,13 @@
#include "GradientConversionOutput.pb-c.h"
#include "Interp.h"
#include "Curves.h"
+#include "Gradient.h"
+#include "ColorTable.h"
#pragma once
namespace Tango
{
- typedef struct
+/* typedef struct
{
unsigned int TblSIze = 0;
unsigned int Version[3] = { 0,0,0 };
@@ -31,9 +34,9 @@ namespace Tango
C_RGB_XYZ_Lab Illuminant;
unsigned char nGamutRegions=0;
double *GRegMaxLim;
- } CT_Header;
+ } CT_Header; */
- typedef struct
+/* typedef struct
{
C_RGB_XYZ_Lab Lab;
C_RGB_XYZ_Lab RGB;
@@ -42,7 +45,7 @@ namespace Tango
int GamutRegion;
double offset;
ColorSpace colorspace;
- }GradStruct;
+ }GradStruct;*/
/*typedef enum {
XYZ,
@@ -56,19 +59,7 @@ namespace Tango
dESpaced
}GradOffset;
- typedef enum {
- A2B,
- A2BR,
- B2A,
- B2AR,
- cprt,
- gbd,
- gbdR,
- wtpt,
- desc,
- lcrv
-// GReg
- }TagList;
+
namespace ColorLib
{
@@ -95,57 +86,33 @@ namespace Tango
void SetMaxNLperCM(double maxNlPerCM, int i);
size_t P_IsInGamut(uint8_t * input_buffer, size_t input_buffer_size, uint8_t *& output_buffer);
private:
- ColorTransf *m_B2ATransform;
- ColorTransf *m_A2BTransform;
- ColorTransf *m_B2ARTransform;
- ColorTransf *m_A2BRTransform;
-// ColorTransf *m_GRegTransform;
- GBD *m_GBD;
- GBD *m_GBDR;
- Curves *m_LinCurves;
+ ColorTable *m_colortable;
ColorConvert *m_Conv02;
// Interp *m_LinInterp;
// Interp *m_InvLinInterp;
C_RGB_XYZ_Lab m_whitepointLab;
C_RGB_XYZ_Lab m_whitepointXYZ_Strip;
- C_RGB_XYZ_Lab m_whitepointXYZ_CT;
+ double *m_NormGamutRegionMaxLim;
+ double *m_ProcessRangesMaxP;
+ int m_nProcessRanges;
void LimitLab(double* LabIn);
- int m_nGamutRegions;
int m_nGradStops;
- GradStruct *m_GradStops;
- double *m_GamutRegionMaxLim;
- int m_nB2AnSepIn;
- int m_nB2AnSepOut;
- int m_nA2BnSepIn;
- int m_nA2BnSepOut;
+ Gradient *m_GradStops;
bool same_regions;
// bool m_AdaptWP;
CalibData *m_CalibCurves;
int m_nInks;
int m_nVolumes;
- int m_nProcessRanges;
- //double *m_ProcessRangesMinP;
- double *m_ProcessRangesMaxP;
- double m_NormFactor;
- int m_TableVersion;
- double m_InvNormFactor;
//double *m_ProcessRangesMaxInkUptake;
//double *m_ProcessRangesMinInkUptake;
C_RGB_XYZ_Lab m_WP;
VectorXd m_maxNlPerCM;
- void SetnB2AnSepIn(int nB2AnSepIn) { m_nB2AnSepIn = nB2AnSepIn; };
- void SetnB2AnSepOut(int nB2AnSepOut) { m_nB2AnSepOut = nB2AnSepOut; };
- void SetnA2BnSepIn(int nA2BnSepIn) { m_nA2BnSepIn = nA2BnSepIn; };
- void SetnA2BnSepOut(int nA2BnSepOut) { m_nA2BnSepOut = nA2BnSepOut; };
- void SetnGamutRegions(int nGamutRegions) { m_nGamutRegions = nGamutRegions; };
- void SetTableVersion(int TableVersion) { m_TableVersion = TableVersion; };
void readColorTransformations(ConversionInput* conversionInput);
- void readColorTables(bool has_rddata, uint8_t *data, int nprocessranges);
+// void readColorTables(bool has_rddata, uint8_t *data, int nprocessranges);
void readCalibrationTables(InputLiquid **inputliquids, int n_inputliquids);
void SetCalibData(CalibrationData* calibrationData, int i, CalibData *tmpCurve);
void SetNumberofInks(int nInks) { m_nInks = nInks; };
void SetNumberOfVolumes(int nVol) { m_nVolumes = nVol; };
- void SetNumberOfInks(int nInks) { m_nInks = nInks; };
// void InitInterpolations(int numofInks, Interp *linearInterp, Interp *InvLinearInterp);
void fillRGB(OutputCoordinates *outputCoords, VectorXd RGBOut);
void fillLab(OutputCoordinates *outputCoords, VectorXd LabOut);
@@ -165,24 +132,26 @@ namespace Tango
VectorXd DoubleToVector(double *doub, int nSize);
void CompareWhitePoints();
bool IsInGamut(double *InLab, SURROUND sur, CAM02CS CS, double *LabCoord);
- CT_Header read_header(uint8_t* data, int &bytesread);
+// CT_Header *read_header(uint8_t* data, int &bytesread);
void read_lut_type(int offset, int data_size, ColorTransf *Transf, ConversionInput* conversionInput);
- void read_xyz_type(int offset, int data_size, C_RGB_XYZ_Lab *xyz, uint8_t *data);
- void read_text_type(int offset, int data_size, std::string *textstr,
- uint8_t *data);
- void read_text_description_type(int offset, int data_size, std::string textdescstr,
- uint8_t *data);
- void findStops(GradStruct m_GradStops1, GradStruct m_GradStops2, double dEThr, int ninterstops, int &nOut,
+ void findStops(Gradient& m_GradStops1, Gradient& m_GradStops2, double dEThr, int ninterstops, int &nOut,
double **VecRGBOut, double **VecLabOut, double *posOut);
- void SetNormFactor();
- void SetInverseNormFactor();
- void NormGamutRegionMaxLim();
void GradInput2InputCoords(GradientConversionInput *conversionInput, InputCoordinates **inputcoordinates);
+ void ProcessGradientStops(InputCoordinates **inputcoordinates);
void PrepareGradient(GradientConversionInput* conversionInput, GradientConversionOutput *conversionOutput);
void LimitInks(VectorXd inInks, double *BoundedInks);
void NLcmtoPercentage(VectorXd InVolume, VectorXd &OutVolume);
int GetGamutRegion(VectorXd Volume, double *GamutLimits);
void SmoothCurveData(VectorXd VIn, VectorXd &VOut, int FilterWidth);
+ void ConvertRGBColorToLinearInks(InputCoordinates* inputcoordinates,
+ VectorXd &InkOut, VectorXd &RGBOut,
+ VectorXd &LabOut, int &GamutRegion, bool &InGamut, SURROUND sur, CAM02CS CS);
+ void ConvertLabColorToLinearInks(InputCoordinates* inputcoordinates,
+ VectorXd &InkOut, VectorXd &RGBOut,
+ VectorXd &LabOut, int &GamutRegion, bool &InGamut, SURROUND sur, CAM02CS CS);
+ void ConvertCMYKColorToLinearInks(InputCoordinates* inputcoordinates,
+ VectorXd &InkOut, VectorXd &RGBOut,
+ VectorXd &LabOut, int &GamutRegion, bool &InGamut, SURROUND sur, CAM02CS CS);
};
}
}
diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Tango.ColorLib_v4.vcxproj b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Tango.ColorLib_v4.vcxproj
index 5c9365f84..e12055f28 100644
--- a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Tango.ColorLib_v4.vcxproj
+++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Tango.ColorLib_v4.vcxproj
@@ -192,10 +192,13 @@
<ClInclude Include="targetver.h" />
<ClInclude Include="Utils\CalibData.h" />
<ClInclude Include="Utils\ColorConvert.h" />
+ <ClInclude Include="Utils\ColorTable.h" />
<ClInclude Include="Utils\ColorTransf.h" />
+ <ClInclude Include="Utils\CT_Header.h" />
<ClInclude Include="Utils\Curves.h" />
<ClInclude Include="Utils\C_RGB_XYZ_Lab.h" />
<ClInclude Include="Utils\GBD.h" />
+ <ClInclude Include="Utils\Gradient.h" />
<ClInclude Include="Utils\Interp.h" />
<ClInclude Include="Utils\NDInterpUtils.h" />
<ClInclude Include="Utils\NumConversions.h" />
@@ -229,10 +232,13 @@
<ClCompile Include="protobuf-c\protobuf-c.c" />
<ClCompile Include="Utils\CalibData.cpp" />
<ClCompile Include="Utils\ColorConvert.cpp" />
+ <ClCompile Include="Utils\ColorTable.cpp" />
<ClCompile Include="Utils\ColorTransf.cpp" />
+ <ClCompile Include="Utils\CT_Header.cpp" />
<ClCompile Include="Utils\Curves.cpp" />
<ClCompile Include="Utils\C_RGB_XYZ_Lab.cpp" />
<ClCompile Include="Utils\GBD.cpp" />
+ <ClCompile Include="Utils\Gradient.cpp" />
<ClCompile Include="Utils\Interp.cpp" />
<ClCompile Include="Utils\NDInterpUtils.cpp" />
<ClCompile Include="Utils\NumConversions.cpp" />
diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Tango.ColorLib_v4.vcxproj.filters b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Tango.ColorLib_v4.vcxproj.filters
index 3c6c1330d..5ebaedebc 100644
--- a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Tango.ColorLib_v4.vcxproj.filters
+++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Tango.ColorLib_v4.vcxproj.filters
@@ -141,6 +141,15 @@
<ClInclude Include="PMR\ColorLab\LinearizationOutput.pb-c.h">
<Filter>PMR</Filter>
</ClInclude>
+ <ClInclude Include="Utils\Gradient.h">
+ <Filter>Utils</Filter>
+ </ClInclude>
+ <ClInclude Include="Utils\CT_Header.h">
+ <Filter>Utils</Filter>
+ </ClInclude>
+ <ClInclude Include="Utils\ColorTable.h">
+ <Filter>Utils</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Exports.cpp">
@@ -248,5 +257,14 @@
<ClCompile Include="PMR\ColorLab\LinearizationOutput.pb-c.c">
<Filter>PMR</Filter>
</ClCompile>
+ <ClCompile Include="Utils\Gradient.cpp">
+ <Filter>Utils</Filter>
+ </ClCompile>
+ <ClCompile Include="Utils\CT_Header.cpp">
+ <Filter>Utils</Filter>
+ </ClCompile>
+ <ClCompile Include="Utils\ColorTable.cpp">
+ <Filter>Utils</Filter>
+ </ClCompile>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/CT_Header.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/CT_Header.cpp
new file mode 100644
index 000000000..5e419f711
--- /dev/null
+++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/CT_Header.cpp
@@ -0,0 +1,83 @@
+#ifdef _MSC_VER
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+#include "CT_Header.h"
+#include <iostream>
+#include <stdio.h>
+#include <cstring>
+
+CT_Header::CT_Header() :
+ m_Version(NULL), m_ColorSpace(NULL), m_ConnectionSpace(NULL), m_TblSize(0),
+ m_DeviceManufacturer(NULL), m_Illuminant(0), m_nGamutRegions(0), m_GRegMaxLim(NULL)
+{
+
+}
+
+CT_Header::~CT_Header()
+{
+ if (m_Version != NULL)
+ {
+ delete[]m_Version;
+ m_Version = NULL;
+ }
+ if (m_ColorSpace != NULL)
+ {
+ delete m_ColorSpace;
+ m_ColorSpace = NULL;
+ }
+ if (m_ConnectionSpace != NULL)
+ {
+ delete m_ConnectionSpace;
+ m_ConnectionSpace = NULL;
+ }
+ if (m_DeviceManufacturer != NULL)
+ {
+ delete m_DeviceManufacturer;
+ m_DeviceManufacturer = NULL;
+ }
+ if (m_GRegMaxLim != NULL)
+ {
+ delete[]m_GRegMaxLim;
+ m_GRegMaxLim = NULL;
+ }
+}
+
+void CT_Header::SetTableVersion(unsigned int *Version)
+{
+ m_Version = new unsigned int[3];
+ for (int i = 0; i < 3; ++i)
+ m_Version[i] = Version[i];
+}
+
+C_RGB_XYZ_Lab CT_Header::GetIlluminant() {
+ return(m_Illuminant);
+};
+
+void CT_Header::SetColorSpace(char *ColorSPace)
+{
+ int nsize = sizeof(ColorSPace);
+ m_ColorSpace = new char[nsize];
+ strcpy(m_ColorSpace, ColorSPace);
+}
+
+void CT_Header :: SetConnectionSpace(char *ConnectionSpace)
+{
+ int nsize = sizeof(ConnectionSpace);
+ m_ConnectionSpace = new char[nsize];
+ strcpy(m_ConnectionSpace, ConnectionSpace);
+}
+
+void CT_Header::SetDeviceManufacturer(char *DeviceManufacturer)
+{
+ int nsize = sizeof(DeviceManufacturer);
+ m_DeviceManufacturer = new char[nsize];
+ strcpy(m_DeviceManufacturer, DeviceManufacturer);
+}
+
+void CT_Header::SetGamutRegionsMaxLimit(double *GRegMaxLim)
+{
+ if (m_GRegMaxLim == NULL)
+ m_GRegMaxLim = new double[m_nGamutRegions];
+ for (int i = 0; i < m_nGamutRegions; ++i)
+ m_GRegMaxLim[i] = GRegMaxLim[i];
+}
diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/CT_Header.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/CT_Header.h
new file mode 100644
index 000000000..6476a82cc
--- /dev/null
+++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/CT_Header.h
@@ -0,0 +1,57 @@
+#ifndef _CT_HEADER_H_
+#define _CT_HEADER_H_
+#pragma once
+#include <stdlib.h>
+#include "C_RGB_XYZ_Lab.h"
+
+class CT_Header {
+public:
+ CT_Header();
+ ~CT_Header();
+ unsigned int GetTableSize() { return(m_TblSize); };
+ void SetTableSize(unsigned int TableSize) {
+ m_TblSize = TableSize;
+ };
+ unsigned int *GetTableVersion() { return(m_Version); };
+ void SetTableVersion(unsigned int *version);
+ char* GetColorSpace() {
+ return(m_ColorSpace);
+ };
+ void SetColorSpace(char *ColorSPace);
+ char* GetConnectionSpace() {
+ return(m_ConnectionSpace);
+ };
+ void SetConnectionSpace(char *ConnectionSpace);
+
+ char* GetDeviceManufacturer() {
+ return(m_DeviceManufacturer);
+ };
+ void SetDeviceManufacturer(char *DeviceManufacturer);
+
+ C_RGB_XYZ_Lab GetIlluminant();
+
+ void SetIlluminant(C_RGB_XYZ_Lab Illuminant) {
+ m_Illuminant = Illuminant;
+ };
+
+ void SetNGamutRegions(unsigned char GamutRegions) {
+ m_nGamutRegions = GamutRegions;
+ };
+ unsigned char GetNGamutRegions() {
+ return(m_nGamutRegions);
+ };
+ void SetGamutRegionsMaxLimit(double *GRegMaxLim);
+ double *GetGamutRegionsMaxLimit() { return(m_GRegMaxLim); };
+
+private:
+ unsigned int *m_Version;
+ char *m_ColorSpace;
+ char * m_ConnectionSpace;
+ char * m_DeviceManufacturer;
+ C_RGB_XYZ_Lab m_Illuminant;
+ unsigned char m_nGamutRegions ;
+ double *m_GRegMaxLim;
+ unsigned int m_TblSize;
+};
+
+#endif \ No newline at end of file
diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/ColorTable.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/ColorTable.cpp
new file mode 100644
index 000000000..9bdadeb3f
--- /dev/null
+++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/ColorTable.cpp
@@ -0,0 +1,645 @@
+#include "ColorTable.h"
+#include "NumConversions.h"
+
+using namespace std;
+
+//Constructor
+ColorTable::ColorTable() :
+ m_B2ATransform(NULL), m_A2BTransform(NULL),
+m_B2ARTransform(NULL), m_A2BRTransform(NULL),
+m_GBD(NULL), m_GBDR(NULL), m_LinCurves(NULL),
+m_nB2AnSepIn(0), m_nB2AnSepOut(0),
+m_nA2BnSepIn(0), m_nA2BnSepOut(0),
+m_TableVersion(0), m_NormFactor(0.0), m_InvNormFactor(1.0),
+m_nGamutRegions(0), m_nProcessRanges(0),
+m_GamutRegionMaxLim(NULL), m_whitepointXYZ_CT(0.0)
+{
+}
+
+ColorTable::~ColorTable()
+{
+ if (m_B2ATransform != NULL)
+ {
+ delete m_B2ATransform;
+ m_B2ATransform = NULL;
+ }
+ if (m_B2ARTransform != NULL)
+ {
+ delete m_B2ARTransform;
+ m_B2ARTransform = NULL;
+ }
+ if (m_A2BTransform != NULL)
+ {
+ delete m_A2BTransform;
+ m_A2BTransform = NULL;
+ }
+ if (m_A2BRTransform != NULL)
+ {
+ delete m_A2BRTransform;
+ m_A2BRTransform = NULL;
+ }
+ if (m_GBD != NULL)
+ {
+ delete m_GBD;
+ m_GBD = NULL;
+ }
+ if (m_GBDR != NULL)
+ {
+ delete m_GBDR;
+ m_GBDR = NULL;
+ }
+ if (m_LinCurves != NULL)
+ {
+ delete m_LinCurves;
+ m_LinCurves = NULL;
+ }
+ if (m_GamutRegionMaxLim != NULL)
+ {
+ delete[] m_GamutRegionMaxLim;
+ m_GamutRegionMaxLim = NULL;
+ }
+}
+void ColorTable::InitColorTables(bool has_rddata, uint8_t *data, int nprocessranges)
+{
+ readColorTables(has_rddata, data, nprocessranges);
+ SetNormFactor();
+ SetInverseNormFactor();
+ NormGamutRegionMaxLim();
+}
+void ColorTable::readColorTables(bool has_data, uint8_t * data, int nprocessranges)
+{
+ //parse Color Tansformations, placed in forward data
+ int bytesread = 0;
+ NumConversions conv;
+ int tag_count = 0;
+ int TblVer = 0;
+ if (has_data)
+ {
+ //Read Header
+ CT_Header *header = read_header(data, bytesread);
+ SetnGamutRegions((int)(header->GetNGamutRegions()));
+ TblVer = (int)header->GetTableVersion()[0];
+ SetTableVersion(TblVer);
+ if (m_nGamutRegions != nprocessranges)
+ {
+ throw std::exception("Number of gamut regions in table does not match STRIP\0");
+ return;
+ }
+ double *tmpGamutRegionsLim = header->GetGamutRegionsMaxLimit();
+ m_GamutRegionMaxLim = new double[m_nGamutRegions];
+ for (int i = 0; i < m_nGamutRegions; ++i)
+ m_GamutRegionMaxLim[i] = tmpGamutRegionsLim[i];
+
+ m_nProcessRanges = (int)(nprocessranges);
+
+ uint32_t tmp;
+ uint8_t *buff = data;
+ tmp = conv.ByteToInt(buff, bytesread);
+ tag_count = (int)tmp;
+ bytesread += 4;
+ //read Tag Table
+ char **TagNames = new char*[tag_count];
+ //char **TagNames = DBG_NEW char*[tag_count];
+ int **TagSize = new int*[tag_count];
+ //int **TagSize = DBG_NEW int*[tag_count];
+ char *tmpC = new char[80];
+ int n = 0;
+ int i, j;
+ for (i = 0; i < tag_count; ++i)
+ {
+ TagSize[i] = new int[2];
+ //TagSize[i] = DBG_NEW int[3];
+ tmp = conv.ByteToInt(buff, bytesread);
+ n = sizeof((char*)&tmp);
+ //tmpC = DBG_NEW char[n];
+ conv.getchar(tmp, n, tmpC);
+ //TagNames[i] = DBG_NEW char[n];
+ TagNames[i] = new char[n];
+ for (j = 0; j < n; ++j)
+ TagNames[i][j] = tmpC[j];
+ bytesread += 4;
+ TagSize[i][0] = conv.ByteToInt(buff, bytesread);
+ bytesread += 4;
+ TagSize[i][1] = conv.ByteToInt(buff, bytesread);
+ bytesread += 4;
+ }
+ if (tmpC != NULL)
+ {
+ delete[] tmpC;
+ tmpC = NULL;
+ }
+
+
+ int *TList = new int[tag_count];
+ //int *TList = DBG_NEW int[tag_count];
+ for (int k = 0; k < tag_count; ++k)
+ {
+ if (strncmp(TagNames[k], "A2B ", 4) == 0)
+ TList[k] = A2B;
+ else if (strncmp(TagNames[k], "A2BR", 4) == 0)
+ TList[k] = A2BR;
+ else if (strncmp(TagNames[k], "B2A ", 4) == 0)
+ TList[k] = B2A;
+ else if (strncmp(TagNames[k], "B2AR ", 4) == 0)
+ TList[k] = B2AR;
+ else if (strncmp(TagNames[k], "wtpt", 4) == 0)
+ TList[k] = wtpt;
+ else if (strncmp(TagNames[k], "desc", 4) == 0)
+ TList[k] = desc;
+ else if (strncmp(TagNames[k], "gbd ", 4) == 0)
+ TList[k] = gbd;
+ else if (strncmp(TagNames[k], "gbdR", 4) == 0)
+ TList[k] = gbdR;
+ else if (strncmp(TagNames[k], "cprt", 4) == 0)
+ TList[k] = cprt;
+ else if (strncmp(TagNames[k], "lcrv", 4) == 0)
+ TList[k] = lcrv;
+ // else if (strncmp(TagNames[k], "GReg", 2) == 0)
+ // TList[k] = GReg;
+ else
+ throw std::exception("Unknown Tag in Color Tables");
+ }
+
+ if (TagNames != NULL)
+ {
+ for (int i = 0; i < tag_count; ++i)
+ {
+ delete[] TagNames[i];
+ TagNames[i] = NULL;
+ }
+ delete[]TagNames;
+ TagNames = NULL;
+ }
+ for (int k = 0; k < tag_count; ++k)
+ {
+ switch (TList[k])
+ {
+ case A2B:
+ {
+ uint8_t *A2BLUT = &(data[TagSize[k][0]]);
+ int A2BLutsize = TagSize[k][1];
+ m_A2BTransform = new ColorTransf();
+ //m_A2BTransform = DBG_NEW ColorTransf();
+ m_A2BTransform->InitData(A2BLUT, A2BLutsize);
+ m_nA2BnSepIn = m_A2BTransform->GetSeparationsIn();
+ m_nA2BnSepOut = m_A2BTransform->GetSeparationsOut();
+ break;
+ }
+ case A2BR:
+ {
+ uint8_t *A2BRLUT = &(data[TagSize[k][0]]);
+ int A2BRLutsize = TagSize[k][1];
+ m_A2BRTransform = new ColorTransf();
+ //m_A2BTransform = DBG_NEW ColorTransf();
+ m_A2BRTransform->InitData(A2BRLUT, A2BRLutsize);
+ break;
+ }
+ case B2A:
+ {
+ uint8_t *B2ALUT = &(data[TagSize[k][0]]);
+ int B2ALutsize = TagSize[k][1];
+ m_B2ATransform = new ColorTransf();
+ //m_B2ATransform = DBG_NEW ColorTransf();
+ m_B2ATransform->InitData(B2ALUT, B2ALutsize);
+ m_nB2AnSepIn = m_B2ATransform->GetSeparationsIn();
+ m_nB2AnSepOut = m_B2ATransform->GetSeparationsOut();
+ break;
+ }
+ case B2AR:
+ {
+ uint8_t *B2ARLUT = &(data[TagSize[k][0]]);
+ int B2ARLutsize = TagSize[k][1];
+ m_B2ARTransform = new ColorTransf();
+ //m_B2ATransform = DBG_NEW ColorTransf();
+ m_B2ARTransform->InitData(B2ARLUT, B2ARLutsize);
+ break;
+ }
+ /* case GReg:
+ {
+ uint8_t *GRegLUT = &(conversionInput->forwarddata.data[TagSize[k][0]]);
+ int GRegLutsize = TagSize[k][1];
+ m_GRegTransform = new ColorTransf();
+ //m_B2ATransform = DBG_NEW ColorTransf();
+ m_GRegTransform->InitData(GRegLUT, GRegLutsize);
+ break;
+ } */
+ case gbd:
+ {
+ uint8_t *GBDList = &(data[TagSize[k][0]]);
+ m_GBD = new GBD();
+ //m_GBD = DBG_NEW GBD();
+ int GBDSize = TagSize[k][1];
+ m_GBD->InitData(GBDList, GBDSize);
+ break;
+ }
+ case gbdR:
+ {
+ uint8_t *GBDRList = &(data[TagSize[k][0]]);
+ m_GBDR = new GBD();
+ //m_GBD = DBG_NEW GBD();
+ int GBDRSize = TagSize[k][1];
+ m_GBDR->InitData(GBDRList, GBDRSize);
+ break;
+ }
+ case lcrv:
+ {
+ uint8_t *CurvesData = &(data[TagSize[k][0]]);
+ m_LinCurves = new Curves();
+ int CurvesSize = TagSize[k][1];
+ m_LinCurves->InitData(CurvesData, CurvesSize);
+ break;
+ }
+ case wtpt:
+ {
+ read_xyz_type(TagSize[k][0], TagSize[k][1], &m_whitepointXYZ_CT, data);
+
+ break;
+ }
+ case cprt:
+ {
+ std::string textstr;
+ read_text_type(TagSize[k][0], TagSize[k][1], &textstr, data);
+ break;
+ }
+ case desc:
+ {
+ std::string textdescstr;
+ read_text_description_type(TagSize[k][0], TagSize[k][1], textdescstr, data);
+ break;
+ }
+ default:
+ {
+ throw std::exception("Unresolved Tag in Color Tables");
+ return;
+ }
+
+ }
+ }
+
+ if (TagSize != NULL)
+ {
+ for (int i = 0; i < tag_count; ++i)
+ {
+ delete[] TagSize[i];
+ TagSize[i] = NULL;
+ }
+ delete[]TagSize;
+ TagSize = NULL;
+ }
+ if (TList != NULL)
+ {
+ delete[] TList;
+ TList = NULL;
+ }
+ if (header != NULL)
+ {
+ delete header;
+ header = NULL;
+ }
+ }
+
+
+ //Verify all relevant tags had been read
+ if (m_A2BTransform == NULL)
+ {
+ throw std::exception("Missing Forward Transform in Color Tables");
+ return;
+ }
+ if (m_A2BRTransform == NULL)
+ {
+ throw std::exception("Missing Reduced Forward Transform in Color Tables");
+ return;
+ }
+ if (m_B2ATransform == NULL)
+ {
+ throw std::exception("Missing Inverse Transform in Color Tables");
+ return;
+ }
+ if (m_B2ARTransform == NULL)
+ {
+ throw std::exception("Missing Reduced Inverse Transform in Color Tables");
+ return;
+ }
+ if (m_GBD == NULL)
+ {
+ throw std::exception("Missing Gamut Boundary Descriptor in Color Tables");
+ return;
+ }
+ if (m_GBDR == NULL)
+ {
+ throw std::exception("Missing Reduced Gamut Boundary Descriptor in Color Tables");
+ return;
+ }
+ if ((m_whitepointXYZ_CT.Get_x() == -1) && (m_whitepointXYZ_CT.Get_y() == -1) && (m_whitepointXYZ_CT.Get_z() == -1))
+ {
+ throw std::exception("Missing Whitepoint in Color Tables");
+ return;
+ }
+ if (m_LinCurves == NULL)
+ {
+ throw std::exception("Missing Linear Curves in Color Tables");
+ return;
+ }
+ return; // OK
+}
+
+CT_Header *ColorTable::read_header(uint8_t *data, int &bytesread)
+{
+ //CT_Header *Header = new CT_Header;
+ //CT_Header *Header = DBG_NEW CT_Header;
+ CT_Header *Header = new CT_Header;
+
+ // unsigned int tmp = (buffer[2 * i + 1] << 8) | buffer[2 * i];
+ uint8_t *ColorTableData = data;
+ //File Size
+ NumConversions Conv;
+ unsigned int TblSize = Conv.ByteToInt(ColorTableData, bytesread);
+ Header->SetTableSize(TblSize);
+ bytesread = 4;
+ uint8_t versionBCT[2];
+ versionBCT[0] = (unsigned int)ColorTableData[bytesread];
+ bytesread += 1;
+ versionBCT[1] = (unsigned int)ColorTableData[bytesread];
+ unsigned int TVersion[3];
+ TVersion[0] = versionBCT[0];
+ TVersion[1] = versionBCT[1] << 4;
+ TVersion[2] = versionBCT[1] & 15;
+ Header->SetTableVersion(TVersion);
+
+ bytesread += 1;
+ uint32_t tmp = Conv.ByteToInt(ColorTableData, bytesread);
+ int n = sizeof((char*)&tmp);
+ //char *tmpC = DBG_NEW char[n];
+ char *tmpC_CS = new char[n];
+ Conv.getchar(tmp, n, tmpC_CS);
+ //Header.ColorSpace = DBG_NEW char[n];
+ Header->SetColorSpace(tmpC_CS);
+ if (tmpC_CS != NULL)
+ {
+ delete [] tmpC_CS;
+ tmpC_CS = NULL;
+ }
+ bytesread += 4;
+ tmp = Conv.ByteToInt(ColorTableData, bytesread);
+ n = sizeof((char*)&tmp);
+ char *tmp_connectionspace = new char[n];
+ Conv.getchar(tmp, n, tmp_connectionspace);
+ //Header.ConnectionSpace = DBG_NEW char[n];
+ Header->SetConnectionSpace(tmp_connectionspace);
+ if (tmp_connectionspace != NULL)
+ {
+ delete[] tmp_connectionspace;
+ tmp_connectionspace = NULL;
+ }
+
+ bytesread += 4;
+
+ bytesread += 12;
+ tmp = Conv.ByteToInt(ColorTableData, bytesread);
+ n = sizeof((char*)&tmp);
+ char *tmp_DM = new char[n];
+ Conv.getchar(tmp, n, tmp_DM);
+ //Header.DeviceManufacturer = DBG_NEW char[n];
+ Header->SetDeviceManufacturer(tmp_DM);
+ // strncpy_s(Header->DeviceManufacturer, n + 1, tmpC, n);
+ //Header->DeviceManufacturer = tmpC;
+ if (tmp_DM != NULL)
+ {
+ delete [] tmp_DM;
+ tmp_DM = NULL;
+ }
+
+ bytesread += 4;
+ //read illuminant
+ double xyz[3];
+ for (int j = 0; j < 3; ++j)
+ {
+ tmp = Conv.ByteToInt(ColorTableData, bytesread);
+ xyz[j] = (double)(tmp) / 65536;
+ bytesread += 4;
+ }
+ C_RGB_XYZ_Lab XYZIllum(xyz[0], xyz[1], xyz[2]);
+ Header->SetIlluminant(XYZIllum);
+ //Read Number of Gamut Regions and Max Limits per Region
+ Header->SetNGamutRegions(ColorTableData[bytesread]);
+ bytesread++;
+ int nsize = Header->GetNGamutRegions();
+ double *GRegMaxLim = new double[nsize];
+ for (int i = 0; i < nsize; ++i)
+ {
+ tmp = Conv.ByteToShort(ColorTableData, bytesread);
+ bytesread += 2;
+ GRegMaxLim[i] = (double)tmp;
+ }
+ Header->SetGamutRegionsMaxLimit(GRegMaxLim);
+ if (GRegMaxLim != NULL)
+ {
+ delete[] GRegMaxLim;
+ GRegMaxLim = NULL;
+ }
+
+ if (bytesread < 128)
+ {
+ bytesread = 128;
+ return(Header);
+ }
+ else
+ {
+ throw std::exception("could not read Color table Header");
+ }
+}
+
+void ColorTable::read_xyz_type(int offset, int data_size, C_RGB_XYZ_Lab *XYZ, uint8_t *data)
+{
+ // 0 - 3 'XYZ '
+ //4 - 7 reserved, must be 0
+ // 8 - n array of XYZ numbers
+
+ if (data_size < 8)
+ {
+ throw std::exception("not enough data to read xyz");
+ }
+ uint8_t *buff = &(data[offset]);
+ NumConversions Conv;
+ int bytesread = 0;
+ int tmpxyz = Conv.ByteToInt(buff, bytesread);
+
+ int n = sizeof(tmpxyz);
+ //char* tmpC = DBG_NEW char[n];
+ char* tmpC = new char[n];
+ Conv.getchar(tmpxyz, n, tmpC);
+
+ char *xyztype = new char[n + 1];
+ //char *xyztype = DBG_NEW char[n + 1];
+ strncpy_s(xyztype, n + 1, tmpC, n);
+ if (strncmp(xyztype, "XYZ ", n) != 0)
+ {
+ if (xyztype != NULL)
+ {
+ delete[] xyztype;
+ xyztype = NULL;
+ }
+ if (tmpC != NULL)
+ {
+ delete[] tmpC;
+ tmpC = NULL;
+ }
+ throw std::exception("Wrong Tag Type");
+ return;
+ }
+ else
+ {
+ if (xyztype != NULL)
+ {
+ delete[] xyztype;
+ xyztype = NULL;
+ }
+ if (tmpC != NULL)
+ {
+ delete[] tmpC;
+ tmpC = NULL;
+ }
+ }
+ bytesread = 8;
+ int num_values = (data_size - 8) / 4;
+ if (floor((double)(num_values) / 3) * 3 != num_values)
+ {
+ throw std::exception("not enough Data to read xyz");
+ return;
+ }
+ double xyz[3];
+ int tmp;
+ for (int j = 0; j < 3; ++j)
+ {
+ tmp = Conv.ByteToInt(buff, bytesread);
+ xyz[j] = (double)(tmp) / 65536;
+ bytesread += 4;
+ }
+ XYZ->Set(xyz[0], xyz[1], xyz[2]);
+ return;
+}
+
+void ColorTable::read_text_type(int offset, int data_size, std::string *textstr, uint8_t *data)
+{
+ // 0 - 3 'text'
+ //4 - 7 reserved, must be 0
+ //8 - string of(data_size - 8) 7 - bit ASCII characters, including NULL
+
+ std::stringstream strstr;
+ if (data_size < 8)
+ {
+ throw std::exception("invalid Tag Name");
+ strstr << "";
+ *textstr = strstr.str();
+ return;
+ }
+
+ uint8_t *buff = &(data[offset]);
+ int bytesread = 0;
+ NumConversions Conv;
+ int tmp = Conv.ByteToInt(buff, bytesread);
+ int n = sizeof((char*)&tmp);
+ //char *tmpC = DBG_NEW char[n];
+ char *tmpC = new char[n];
+ Conv.getchar(tmp, n, tmpC);
+ char *tagtype = new char[n + 1];
+ //char *tagtype = DBG_NEW char[n + 1];
+ strncpy_s(tagtype, n + 1, tmpC, n);
+ if (strcmp(tagtype, "text") != 0)
+ {
+ throw std::exception("invalid Tag Name");
+ strstr << "";
+ *textstr = strstr.str();
+ return;
+ }
+ if (tagtype != NULL)
+ {
+ delete[] tagtype;
+ tagtype = NULL;
+ }
+ if (tmpC != NULL)
+ {
+ delete[]tmpC;
+ tmpC = NULL;
+ }
+ bytesread += 8;
+ uint8_t tmp1;
+ for (int i = bytesread; i < data_size; ++i)
+ {
+ tmp1 = buff[i];
+ strstr.put(tmp1);
+ }
+ *textstr = strstr.str();
+ return;
+}
+
+void ColorTable::read_text_description_type(int offset, int data_size, std::string textdescstr, uint8_t *data)
+{
+ // 0 - 3 'desc'
+ // 4 - 7 reserved, must be 0
+ // 8 - 11 ASCII invariant description count, including terminating NULL
+ // 12 - ASCII invariant description
+
+ uint8_t *buff = &(data[offset]);
+ int bytesread = 0;
+ NumConversions Conv;
+ int tmp = Conv.ByteToInt(buff, bytesread);
+ int n = sizeof((char*)&tmp);
+ //char *tmpC= DBG_NEW char[n];
+ char *tmpC = new char[n];
+ Conv.getchar(tmp, n, tmpC);
+ char *tagtype = new char[n + 1];
+ //char *tagtype = DBG_NEW char[n + 1];
+ strncpy_s(tagtype, n + 1, tmpC, n);
+ std::stringstream strstr;
+ if (strcmp(tagtype, "desc") != 0)
+ {
+ throw std::exception("invalid Tag Name");
+ strstr << "";
+ textdescstr = strstr.str();
+ return;
+ }
+ if (tagtype != NULL)
+ {
+ delete[] tagtype;
+ tagtype = NULL;
+ }
+ if (tmpC != NULL)
+ {
+ delete[]tmpC;
+ tmpC = NULL;
+ }
+ bytesread += 8;
+ int count = Conv.ByteToInt(buff, bytesread);
+ bytesread += 4;
+ uint8_t tmp1;
+ for (int i = 0; i < count - 1; ++i)
+ {
+ tmp1 = buff[bytesread + i];
+ strstr << tmp1;
+ }
+ textdescstr = strstr.str();
+ return;
+}
+
+void ColorTable::SetNormFactor()
+{
+ m_NormFactor = m_GamutRegionMaxLim[m_nProcessRanges - 1] / m_GamutRegionMaxLim[0];
+}
+
+void ColorTable::SetInverseNormFactor()
+{
+ if (m_NormFactor <= 0)
+ m_InvNormFactor = -1;
+ else
+ m_InvNormFactor = 1.0 / m_NormFactor;
+}
+
+void ColorTable::NormGamutRegionMaxLim()
+{
+ double GamutRegionMaxLim0 = m_GamutRegionMaxLim[0];
+ for (int i = 0; i < m_nProcessRanges; ++i)
+ m_GamutRegionMaxLim[i] = 100 * m_GamutRegionMaxLim[i] / GamutRegionMaxLim0;
+}
+
+
diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/ColorTable.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/ColorTable.h
new file mode 100644
index 000000000..9538a4011
--- /dev/null
+++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/ColorTable.h
@@ -0,0 +1,76 @@
+#ifndef _COLORTABLE_H_
+#define _COLORTABLE_H_
+
+#include "C_RGB_XYZ_Lab.h"
+#include "ColorSpace.pb-c.h"
+#include "ColorTransf.h"
+#include "CT_Header.h"
+#include "GBD.h"
+#include "Curves.h"
+
+typedef enum {
+ A2B,
+ A2BR,
+ B2A,
+ B2AR,
+ cprt,
+ gbd,
+ gbdR,
+ wtpt,
+ desc,
+ lcrv
+ // GReg
+}TagList;
+class ColorTable {
+public:
+ ColorTable();
+ ~ColorTable();
+ void InitColorTables(bool has_rddata, uint8_t *data, int nprocessranges);
+
+ int GetnB2AnSepIn( ){ return(m_nB2AnSepIn); };
+ int GetnB2AnSepOut() { return(m_nB2AnSepOut); };
+ int GetnA2BnSepIn() { return(m_nA2BnSepIn); };
+ int GetnA2BnSepOut() { return(m_nA2BnSepOut); };
+ int GetnGamutRegions() { return(m_nGamutRegions); };
+ double GetNormFactor() { return(m_NormFactor); };
+ double GetInverseNormFactor() { return(m_InvNormFactor); };
+ double *GetNormGamutRegionMaxLim() { return(m_GamutRegionMaxLim); };
+ int GetTableVersion() { return(m_TableVersion); };
+ ColorTransf *m_B2ATransform;
+ ColorTransf *m_A2BTransform;
+ ColorTransf *m_B2ARTransform;
+ ColorTransf *m_A2BRTransform;
+ GBD *m_GBD;
+ GBD *m_GBDR;
+ Curves *m_LinCurves;
+private:
+ void readColorTables(bool has_rddata, uint8_t *data, int nprocessranges);
+ void SetNormFactor();
+ void SetInverseNormFactor();
+ void NormGamutRegionMaxLim();
+ int m_nB2AnSepIn;
+ int m_nB2AnSepOut;
+ int m_nA2BnSepIn;
+ int m_nA2BnSepOut;
+ int m_nGamutRegions;
+ int m_nProcessRanges;
+ int m_TableVersion;
+ double m_NormFactor;
+ double m_InvNormFactor;
+ double *m_GamutRegionMaxLim;
+ C_RGB_XYZ_Lab m_whitepointXYZ_CT;
+ void SetnB2AnSepIn(int nB2AnSepIn) { m_nB2AnSepIn = nB2AnSepIn; };
+ void SetnB2AnSepOut(int nB2AnSepOut) { m_nB2AnSepOut = nB2AnSepOut; };
+ void SetnA2BnSepIn(int nA2BnSepIn) { m_nA2BnSepIn = nA2BnSepIn; };
+ void SetnA2BnSepOut(int nA2BnSepOut) { m_nA2BnSepOut = nA2BnSepOut; };
+ void SetnGamutRegions(int nGamutRegions) { m_nGamutRegions = nGamutRegions; };
+ void SetTableVersion(int TableVersion) { m_TableVersion = TableVersion; };
+ CT_Header *read_header(uint8_t* data, int &bytesread);
+ void read_xyz_type(int offset, int data_size, C_RGB_XYZ_Lab *xyz, uint8_t *data);
+ void read_text_type(int offset, int data_size, std::string *textstr,
+ uint8_t *data);
+ void read_text_description_type(int offset, int data_size, std::string textdescstr,
+ uint8_t *data);
+};
+
+#endif \ No newline at end of file
diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/Gradient.cpp b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/Gradient.cpp
new file mode 100644
index 000000000..0066db6b3
--- /dev/null
+++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/Gradient.cpp
@@ -0,0 +1,35 @@
+#ifdef _MSC_VER
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "Gradient.h"
+
+using namespace std;
+Gradient::Gradient() :
+ m_Lab(0), m_RGB(0),
+ m_Volume(NULL), m_GamutRegion(0), m_Offset(0.0), m_colorspace(COLOR_SPACE__RGB),
+ m_InGamut(true)
+{
+
+}
+
+
+Gradient::~Gradient()
+{
+ if (m_Volume != NULL)
+ {
+ delete[] m_Volume;
+ m_Volume = NULL;
+ }
+
+}
+
+void Gradient::SetVolumeSize(int nchannels)
+{
+ m_Volume = new double[nchannels];
+}
+
+void Gradient::SetVolumeValue(double val, int ind)
+{
+ m_Volume[ind] = val;
+}
diff --git a/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/Gradient.h b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/Gradient.h
new file mode 100644
index 000000000..278b3469d
--- /dev/null
+++ b/Software/Visual_Studio/ColorLib/Tango.ColorLib_v4/Utils/Gradient.h
@@ -0,0 +1,37 @@
+#ifndef _GRADIENT_H_
+#define _GRADIENT_H_
+
+#include "C_RGB_XYZ_Lab.h"
+#include "ColorSpace.pb-c.h"
+class Gradient {
+public:
+ Gradient();
+ ~Gradient();
+ int Get_GamutRegion() { return(m_GamutRegion); };
+ double Get_Offset() { return(m_Offset); };
+ ColorSpace Get_ColorSpace() {return(m_colorspace);};
+ C_RGB_XYZ_Lab Get_Lab() { return(m_Lab); };
+ C_RGB_XYZ_Lab Get_RGB() { return(m_RGB); };
+ bool Get_InGamut() { return(m_InGamut); };
+ void Set_GamutRegion(int GamutRegion) { m_GamutRegion = GamutRegion; };
+ void Set_Lab(C_RGB_XYZ_Lab Lab) { m_Lab = Lab; };
+ void Set_RGB(C_RGB_XYZ_Lab RGB) { m_RGB = RGB; };
+ void Set_Offset(double Offset) { m_Offset = Offset; };
+ void Set_ColorSpace(ColorSpace colorspace) { m_colorspace = colorspace; };
+ void SetVolumeSize(int nchannels);
+ void SetVolumeValue(double val, int ind);
+ void SetInGamut(bool InGamut) { m_InGamut = InGamut; };
+
+
+private:
+ C_RGB_XYZ_Lab m_Lab;
+ C_RGB_XYZ_Lab m_RGB;
+ double *m_Volume;
+ int m_GamutRegion;
+ double m_Offset;
+ ColorSpace m_colorspace;
+ bool m_InGamut;
+
+};
+
+#endif \ No newline at end of file
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsViewVM.cs
index ac9279ab8..8a89fbc8f 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsViewVM.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/ViewModels/DiagnosticsViewVM.cs
@@ -15,8 +15,10 @@ using Tango.BL.Enumerations;
using Tango.Core.Commands;
using Tango.FSE.Common;
using Tango.FSE.Common.Diagnostics;
+using Tango.FSE.Common.FileAssociation;
using Tango.FSE.Common.Notifications;
using Tango.FSE.Diagnostics.Project;
+using Tango.FSE.Diagnostics.Views;
using Tango.PMR.Diagnostics;
namespace Tango.FSE.Diagnostics.ViewModels
@@ -403,6 +405,8 @@ namespace Tango.FSE.Diagnostics.ViewModels
{
base.OnApplicationStarted();
DiagnosticsProvider.FrameReceived += DiagnosticsProvider_FrameReceived;
+
+ FileAssociationProvider.RegisterFileAssociationHandler("diagnostics", HandleDiagnosticsFileAssociation);
}
public async override void OnApplicationReady()
@@ -781,5 +785,36 @@ namespace Tango.FSE.Diagnostics.ViewModels
}
#endregion
+
+ #region File Association
+
+ private async void HandleDiagnosticsFileAssociation(FileAssociationPackage package)
+ {
+ if (!CurrentUser.HasPermission(Permissions.FSE_EditDiagnosticsProject))
+ {
+ await NotificationProvider.ShowError("Current user profile does not allow loading custom diagnostics projects.");
+ return;
+ }
+
+ if (File.Exists(package.File))
+ {
+ try
+ {
+ LogManager.Log("Opening diagnostics project from file association...");
+ await NavigationManager.NavigateTo<DiagnosticsModule>(true, nameof(DiagnosticsView));
+ using (NotificationProvider.PushTaskItem("Loading diagnostics project..."))
+ {
+ await Task.Delay(2000);
+ await LoadProject(package.File);
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error occurred while trying to handle the diagnostics file association.");
+ }
+ }
+ }
+
+ #endregion
}
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/diagnostics.tdp b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/diagnostics.tdp
index 9c75729b6..d5a250f16 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/diagnostics.tdp
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Diagnostics/diagnostics.tdp
@@ -2442,7 +2442,7 @@
},
{
"$type": "Tango.FSE.Diagnostics.Project.Widgets.Output.OutputWidget, Tango.FSE.Diagnostics",
- "IO": "GPO_TFEED_BREAK_1",
+ "IO": "GPO_LED4",
"EnableComponentSelection": false,
"ID": "419fa0da-9c51-49fc-82cf-83707c03a44a",
"Column": 10,
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Controls/RemoteDesktopControl.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Controls/RemoteDesktopControl.xaml
index 77b977b65..4e6959e5b 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Controls/RemoteDesktopControl.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Controls/RemoteDesktopControl.xaml
@@ -43,7 +43,7 @@
<Grid HorizontalAlignment="Right" VerticalAlignment="Top">
<StackPanel Margin="0 5 27 0" Orientation="Horizontal">
- <controls:ToggleIconButton IsChecked="{Binding TouchMode}" UncheckedIcon="CursorHand" CheckedIcon="CursorHand" UncheckedForeground="{StaticResource FSE_GrayBrush}" CheckedForeground="{StaticResource FSE_GreenBrush}" Cursor="Hand" ToolTip="Touch mode" IsEnabled="{Binding RemoteDesktopProvider.InSession}" Width="16" Height="16" Padding="0" />
+ <controls:ToggleIconButton Visibility="Collapsed" IsChecked="{Binding TouchMode}" UncheckedIcon="CursorHand" CheckedIcon="CursorHand" UncheckedForeground="{StaticResource FSE_GrayBrush}" CheckedForeground="{StaticResource FSE_GreenBrush}" Cursor="Hand" ToolTip="Touch mode" IsEnabled="{Binding RemoteDesktopProvider.InSession}" Width="16" Height="16" Padding="0" />
<controls:ToggleIconButton Margin="7 0 0 0" IsChecked="{Binding CursorVisible}" UncheckedIcon="CursorDefault" CheckedIcon="CursorDefault" UncheckedForeground="{StaticResource FSE_GrayBrush}" CheckedForeground="{StaticResource FSE_GreenBrush}" Cursor="Hand" ToolTip="Display remote cursor" IsEnabled="{Binding RemoteDesktopProvider.InSession}" Width="16" Height="16" Padding="0" />
<controls:IconButton Margin="7 0 0 0" Cursor="Hand" ToolTip="Take snapshot" x:Name="btnSnapshot" Click="BtnSnapshot_Click" Command="{Binding TakeSnapshotCommand}" IsEnabled="{Binding RemoteDesktopProvider.InSession}" Icon="ImagePlus" Width="24" Height="24" Padding="0" />
<controls:IconButton Margin="5 0 0 0" Cursor="Hand" ToolTip="Open in separate window" Icon="OpenInNew" Width="24" Height="24" Padding="0" Command="{Binding WindowsManager.DetachToWindowCommand}" CommandParameter="{Binding ElementName=remoteDesktopControl}" Visibility="{Binding ElementName=remoteDesktopControl,Path=(win:WindowsManagerHelper.IsDetached),Converter={StaticResource BooleanToVisibilityInverseConverter}}" />
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/RemoteDesktopView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/RemoteDesktopView.xaml
index 95e4b4a52..012c16c64 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/RemoteDesktopView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.PPCConsole/Views/RemoteDesktopView.xaml
@@ -6,6 +6,7 @@
xmlns:global="clr-namespace:Tango.FSE.PPCConsole"
xmlns:vm="clr-namespace:Tango.FSE.PPCConsole.ViewModels"
xmlns:local="clr-namespace:Tango.FSE.PPCConsole.Views"
+ xmlns:auth="clr-namespace:Tango.FSE.Common.Authorization;assembly=Tango.FSE.Common"
xmlns:controls="clr-namespace:Tango.FSE.Common.Controls;assembly=Tango.FSE.Common"
xmlns:material="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:win="clr-namespace:Tango.FSE.Common.WindowsManager;assembly=Tango.FSE.Common"
@@ -153,11 +154,11 @@
</Style.Triggers>
</Style>
</UniformGrid.Style>
- <Button IsEnabled="{Binding RemoteDesktopProvider.InSession}" Width="250" Margin="5" Style="{StaticResource FSE_Button_Polygon}" Content="Hide PPC and Open Shell" Command="{Binding HideAndOpenShellCommand}" />
+ <Button auth:AuthorizationHelper.Mode="Collapsed" auth:AuthorizationHelper.Permission="FSE_RemoteDesktopControl" IsEnabled="{Binding RemoteDesktopProvider.InSession}" Width="250" Margin="5" Style="{StaticResource FSE_Button_Polygon}" Content="Hide PPC and Open Shell" Command="{Binding HideAndOpenShellCommand}" />
- <Button IsEnabled="{Binding RemoteDesktopProvider.InSession}" Width="250" Margin="5" Style="{StaticResource FSE_Button_Polygon}" Content="Restart application"/>
+ <Button auth:AuthorizationHelper.Mode="Collapsed" auth:AuthorizationHelper.Permission="FSE_RemoteDesktopControl" IsEnabled="{Binding RemoteDesktopProvider.InSession}" Width="250" Margin="5" Style="{StaticResource FSE_Button_Polygon}" Content="Restart application"/>
- <Button IsEnabled="{Binding RemoteDesktopProvider.InSession}" Width="250" Margin="5" Style="{StaticResource FSE_Button_Polygon}" Content="Open Task Manager" Command="{Binding OpenTaskManagerCommand}" />
+ <Button auth:AuthorizationHelper.Mode="Collapsed" auth:AuthorizationHelper.Permission="FSE_RemoteDesktopControl" IsEnabled="{Binding RemoteDesktopProvider.InSession}" Width="250" Margin="5" Style="{StaticResource FSE_Button_Polygon}" Content="Open Task Manager" Command="{Binding OpenTaskManagerCommand}" />
<CheckBox Margin="5" HorizontalAlignment="Center" IsEnabled="{Binding RemoteDesktopProvider.InSession,Converter={StaticResource BooleanInverseConverter}}" IsChecked="{Binding RemoteDesktopProvider.EnableWebRtc}">Enable P2P communication channel</CheckBox>
</UniformGrid>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Content/VersionHistory/VersionHistory.aml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Content/VersionHistory/VersionHistory.aml
new file mode 100644
index 000000000..b24762998
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Content/VersionHistory/VersionHistory.aml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<topic id="338391aa-2c40-45b6-b5ad-05e86b91bfa9" revisionNumber="1">
+ <developerConceptualDocument xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <introduction>
+ <para>The topics in this section describe the various changes made to the [TODO: Project Title] over the
+life of the project.</para>
+ </introduction>
+
+ <section>
+ <title>Version History</title>
+ <content>
+ <para>Select a version below to see a description of its changes.</para>
+
+ <list class="bullet">
+ <listItem>
+ <para><link xlink:href="38a7c3b2-7174-4466-b95b-e952cdc29c3f" /></para>
+ </listItem>
+
+ <listItem>
+ <para>[TODO: Add links to each specific version page]</para>
+ </listItem>
+
+ </list>
+
+ </content>
+ </section>
+
+ <relatedTopics>
+ <link xlink:href="0f61f11a-7ea4-4d45-b34a-1f31a2c77a5a" />
+ </relatedTopics>
+
+ </developerConceptualDocument>
+</topic>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Content/VersionHistory/v1.0.0.0.aml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Content/VersionHistory/v1.0.0.0.aml
new file mode 100644
index 000000000..b02746331
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Content/VersionHistory/v1.0.0.0.aml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<topic id="38a7c3b2-7174-4466-b95b-e952cdc29c3f" revisionNumber="1">
+ <developerConceptualDocument xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <introduction>
+ <para>Version [TODO: Version] was released on [TODO: Date].
+ </para>
+ </introduction>
+
+ <section>
+ <title>Changes in This Release</title>
+ <content>
+
+ <list class="bullet">
+ <listItem>
+ <para>[TODO: Add change items here]</para>
+ </listItem>
+
+ </list>
+
+ </content>
+ </section>
+
+ <relatedTopics>
+ <link xlink:href="338391aa-2c40-45b6-b5ad-05e86b91bfa9" />
+ </relatedTopics>
+
+ </developerConceptualDocument>
+</topic>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Content/Welcome.aml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Content/Welcome.aml
new file mode 100644
index 000000000..eb51fa37f
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Content/Welcome.aml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="utf-8"?>
+<topic id="0f61f11a-7ea4-4d45-b34a-1f31a2c77a5a" revisionNumber="1">
+ <developerConceptualDocument xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+ <section>
+ <title>Welcome</title>
+ <content>
+ <para>Welcome to the Tango FSE Procedures API documentation.</para>
+ <para>This document contains a detailed description of each part of the API with some examples.</para>
+
+ <para>
+ The best way to start exploring the main capabilities of a procedure is the <codeEntityReference>T:Tango.FSE.Procedures.IProcedureContext</codeEntityReference> interface.
+ </para>
+ </content>
+ </section>
+
+ <section>
+ <title>What is a Procedure ?</title>
+ <content>
+ <list class="bullet">
+ <listItem>
+ <para>
+ A procedure is a sequence of a pre-programmed actions/commands.
+ </para>
+ </listItem>
+
+ <listItem>
+ <para>
+ A procedure can have one or more user input parameters.
+ </para>
+ </listItem>
+
+ <listItem>
+ <para>
+ A procedure can have one or more output values.
+ </para>
+ </listItem>
+ </list>
+
+ <para>
+ Procedures are not legacy “stubs”. They are a completely different creature.
+ <lineBreak/>
+ Procedures are a way for providing immediate and dynamic response for almost any scenario or issue that is being raised by customers/technicians.
+ <lineBreak/>
+ Procedure programmers can leverage an intuitive and extensive API and accomplish almost any requirement.
+ <lineBreak/>
+ Programming and managing Procedures is done through the “Procedure Designer” module.
+ </para>
+ </content>
+ </section>
+
+ <section>
+ <title>The Procedure Designer</title>
+ <content>
+ <para>
+ The procedure designer module can be seen as a fully fledged IDE (Integrated Development Environment), designed to provide the best development experience for the “procedure programmer”.
+ </para>
+ <para>
+ The procedure designer is basically a project editor. In the technical sense, a “Procedure” is basically a project.
+ </para>
+ <para>
+ A project can be composed of one or more script files that are automatically linked together.
+ </para>
+ <para>
+ A project, is represented as a single file (.pproj) and is designed to encapsulate all the files and information about the project.
+ </para>
+ <para>
+ A project can have multiple assembly references and make use of them. An assembly reference can be any DLL file from the entire .NET framework, or from Twine’s libraries.
+ </para>
+ <para>
+ A “Procedure” in the “Procedures Module” is actually a single published procedure project.
+ <lineBreak/>
+ A published procedure is a project that is saved on Twine’s global database (per environment).
+ <lineBreak/>
+ Each published project has a name, description and version, while preserving the history of the last 10 versions.
+ <lineBreak/>
+ When the user navigates to the Procedures Module, Tango FSE will retrieves all published projects from the server.
+ </para>
+ <para>
+ Accessing the procedure designer module requires the “Run Procedure Designer” permission.
+ <lineBreak/>
+ Publishing a procedure project requires the “Publish Procedure Projects” permission.
+ </para>
+
+ <legacyBold>
+ <legacyUnderline>
+ Summery:
+ </legacyUnderline>
+ </legacyBold>
+
+ <list class="bullet">
+ <listItem>
+ <para>
+ Published procedure projects are intended for all users and can be executed using the Procedures Module.
+ </para>
+ </listItem>
+
+ <listItem>
+ <para>
+ Procedure Project files are intended for Twine’s programmers and technicians and can be executed/edited using the Procedure Designer.
+ </para>
+ </listItem>
+ </list>
+
+ <para>
+ We can say that once a procedure project that is being designed for end-users, is well-tested and optimized, it can be published and be available as a “Procedure” for end-users.
+ </para>
+ </content>
+ </section>
+ </developerConceptualDocument>
+</topic>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/ContentLayout.content b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/ContentLayout.content
new file mode 100644
index 000000000..b1d5a0239
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/ContentLayout.content
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Topics>
+ <Topic id="0f61f11a-7ea4-4d45-b34a-1f31a2c77a5a" visible="True" isDefault="true" isSelected="true" title="Tango FSE Procedures API">
+ <HelpKeywords>
+ <HelpKeyword index="K" term="Welcome" />
+ </HelpKeywords>
+ </Topic>
+</Topics> \ No newline at end of file
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Help/proc-doc.chm b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Help/proc-doc.chm
new file mode 100644
index 000000000..1fb821112
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Help/proc-doc.chm
Binary files differ
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Help/proc-doc.chw b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Help/proc-doc.chw
new file mode 100644
index 000000000..f3921f60d
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Help/proc-doc.chw
Binary files differ
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Tango.FSE.Procedures.Documentation.shfbproj b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Tango.FSE.Procedures.Documentation.shfbproj
new file mode 100644
index 000000000..abb8a83f9
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/Tango.FSE.Procedures.Documentation.shfbproj
@@ -0,0 +1,229 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <!-- The configuration and platform will be used to determine which assemblies to include from solution and
+ project documentation sources -->
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>12ec97a5-c3c2-40cb-b658-ec4018b89269</ProjectGuid>
+ <SHFBSchemaVersion>2017.9.26.0</SHFBSchemaVersion>
+ <!-- AssemblyName, Name, and RootNamespace are not used by SHFB but Visual Studio adds them anyway -->
+ <AssemblyName>Tango.FSE.Procedures.Documentation</AssemblyName>
+ <RootNamespace>Tango.FSE.Procedures.Documentation</RootNamespace>
+ <Name>Tango.FSE.Procedures.Documentation</Name>
+ <!-- SHFB properties -->
+ <FrameworkVersion>.NET Framework 4.6.1</FrameworkVersion>
+ <OutputPath>.\Help\</OutputPath>
+ <HtmlHelpName>proc-doc</HtmlHelpName>
+ <Language>en-US</Language>
+ <TransformComponentArguments>
+ <Argument Key="logoFile" Value="machine_48px.png" />
+ <Argument Key="logoHeight" Value="" />
+ <Argument Key="logoWidth" Value="" />
+ <Argument Key="logoAltText" Value="" />
+ <Argument Key="logoPlacement" Value="left" />
+ <Argument Key="logoAlignment" Value="left" />
+ <Argument Key="maxVersionParts" Value="" />
+ <Argument Key="defaultLanguage" Value="cs" />
+ <Argument Key="includeEnumValues" Value="true" />
+ <Argument Key="baseSourceCodeUrl" Value="" />
+ <Argument Key="requestExampleUrl" Value="" />
+ </TransformComponentArguments>
+ <DocumentationSources>
+ <DocumentationSource sourceFile="..\Tango.FSE.Procedures\Tango.FSE.Procedures.csproj" />
+ <DocumentationSource sourceFile="..\..\Tango.FSE.Common\Tango.FSE.Common.csproj" />
+ <DocumentationSource sourceFile="..\..\..\PPC\Tango.PPC.Shared\Tango.PPC.Shared.csproj" />
+ </DocumentationSources>
+ <HelpFileFormat>HtmlHelp1</HelpFileFormat>
+ <SyntaxFilters>C#</SyntaxFilters>
+ <PresentationStyle>VS2013</PresentationStyle>
+ <CleanIntermediates>True</CleanIntermediates>
+ <KeepLogFile>True</KeepLogFile>
+ <DisableCodeBlockComponent>False</DisableCodeBlockComponent>
+ <IndentHtml>False</IndentHtml>
+ <BuildAssemblerVerbosity>OnlyWarningsAndErrors</BuildAssemblerVerbosity>
+ <SaveComponentCacheCapacity>100</SaveComponentCacheCapacity>
+ <HelpTitle>Tango FSE Procedures API</HelpTitle>
+ <HelpFileVersion>1.0.0.0</HelpFileVersion>
+ <NamingMethod>MemberName</NamingMethod>
+ <ContentPlacement>AboveNamespaces</ContentPlacement>
+ <RootNamespaceContainer>False</RootNamespaceContainer>
+ <NamespaceGrouping>False</NamespaceGrouping>
+ <MaximumGroupParts>2</MaximumGroupParts>
+ <Preliminary>False</Preliminary>
+ <SdkLinkTarget>Blank</SdkLinkTarget>
+ <VisibleItems>InheritedMembers, InheritedFrameworkMembers, ProtectedInternalAsProtected, NonBrowsable</VisibleItems>
+ <ApiFilter>
+ <Filter entryType="Namespace" fullName="" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Authentication" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Authorization" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.AutoComplete" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Behaviors" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.BugReporting" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Connection" isExposed="False">
+ <Filter entryType="Enumeration" fullName="Tango.FSE.Common.Connection.MachineConnectionTypes" filterName="MachineConnectionTypes" isExposed="True" />
+</Filter>
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Connectivity" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Console" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Controls" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Converters" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Core" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.DemoMode" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Diagnostics" isExposed="False">
+ <Filter entryType="Class" fullName="Tango.FSE.Common.Diagnostics.DiagnosticsPackage" filterName="DiagnosticsPackage" isExposed="True">
+ <Filter entryType="Property" fullName="Tango.FSE.Common.Diagnostics.DiagnosticsPackage.Frame" filterName="Frame" isExposed="False" />
+ <Filter entryType="Property" fullName="Tango.FSE.Common.Diagnostics.DiagnosticsPackage.MonitorsProperties" filterName="MonitorsProperties" isExposed="False" />
+ </Filter>
+</Filter>
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Dialogs" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Events" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.EventTriggerActions" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.FileAssociation" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.FileSystem" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Firmware" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.FSEApplication" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Graphs" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Helpers" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Logging" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.MachineUpdates" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Modules" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Navigation" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Notifications" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Performance" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.RemoteDesktop" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.RemoteJob" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.RemoteUpgrade" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Resolution" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Storage" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.SystemInfo" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Threading" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Tiles" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.Updates" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Common.WindowsManager" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Procedures" isExposed="False">
+ <Filter entryType="Enumeration" fullName="Tango.FSE.Procedures.ArrayParsingStyle" filterName="ArrayParsingStyle" isExposed="True" />
+ <Filter entryType="Interface" fullName="Tango.FSE.Procedures.IDialogController" filterName="IDialogController" isExposed="True" />
+ <Filter entryType="Interface" fullName="Tango.FSE.Procedures.IProcedureContext" filterName="IProcedureContext" isExposed="True">
+ <Filter entryType="Method" fullName="Tango.FSE.Procedures.IProcedureContext.BreakPoint" filterName="BreakPoint" isExposed="False" />
+ <Filter entryType="Property" fullName="Tango.FSE.Procedures.IProcedureContext.Results" filterName="Results" isExposed="False" />
+ <Filter entryType="Event" fullName="Tango.FSE.Procedures.IProcedureContext.BreakPointRequest" filterName="BreakPointRequest" isExposed="False" />
+ <Filter entryType="Event" fullName="Tango.FSE.Procedures.IProcedureContext.Progress" filterName="Progress" isExposed="False" />
+ </Filter>
+ <Filter entryType="Class" fullName="Tango.FSE.Procedures.Result" filterName="Result" isExposed="True">
+ <Filter entryType="Property" fullName="Tango.FSE.Procedures.Result.IsBitmap" filterName="IsBitmap" isExposed="False" />
+ <Filter entryType="Property" fullName="Tango.FSE.Procedures.Result.IsGraph" filterName="IsGraph" isExposed="False" />
+ <Filter entryType="Property" fullName="Tango.FSE.Procedures.Result.IsValueArray" filterName="IsValueArray" isExposed="False" />
+ </Filter>
+ <Filter entryType="Enumeration" fullName="Tango.FSE.Procedures.ResultType" filterName="ResultType" isExposed="True" />
+ <Filter entryType="Class" fullName="Tango.FSE.Procedures.UserInput" filterName="UserInput" isExposed="True" />
+</Filter>
+<Filter entryType="Namespace" fullName="Tango.FSE.Procedures.Contracts" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Procedures.Controls" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Procedures.Converters" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Procedures.CSV" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Procedures.Designer" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Procedures.Dialogs" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Procedures.Examples.AddResult" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Procedures.Examples.Connection" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Procedures.Examples.Csv" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Procedures.Examples.Diagnostics" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Procedures.Examples.RequestUserInputFor" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Procedures.Examples.Send" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Procedures.Examples.SendContinuous" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Procedures.Examples.Sql" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Procedures.Helpers" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Procedures.Messages" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Procedures.Navigation" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Procedures.ViewModels" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Procedures.Views" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.FSE.Procedures.Windows" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.PPC.Shared.Information" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.PPC.Shared.Jobs" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.PPC.Shared.Logs" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.PPC.Shared.Performance" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.PPC.Shared.RemoteUpgrade" isExposed="False" />
+<Filter entryType="Namespace" fullName="Tango.PPC.Shared.SQL" isExposed="True">
+ <Filter entryType="Class" fullName="Tango.PPC.Shared.SQL.ExecuteSqlRequest" filterName="ExecuteSqlRequest" isExposed="False" />
+ <Filter entryType="Class" fullName="Tango.PPC.Shared.SQL.ExecuteSqlResponse" filterName="ExecuteSqlResponse" isExposed="False" />
+</Filter>
+<Filter entryType="Namespace" fullName="Tango.PPC.Shared.Updates" isExposed="False" />
+<Filter entryType="Namespace" fullName="" isExposed="False" /></ApiFilter>
+ <ProjectSummary>This is the global summery for the help file.</ProjectSummary>
+ <NamespaceSummaries>
+ <NamespaceSummaryItem name="(global)" isDocumented="True">This is the global summery for the help file.</NamespaceSummaryItem>
+ <NamespaceSummaryItem name="Tango.FSE.Procedures" isDocumented="True">Contains a collection of interfaces and classes for the main procedures API.</NamespaceSummaryItem>
+ </NamespaceSummaries>
+ <ComponentConfigurations>
+ </ComponentConfigurations>
+ <MissingTags>Summary, Parameter, Returns, AutoDocumentCtors, TypeParameter, AutoDocumentDispose</MissingTags>
+ </PropertyGroup>
+ <!-- There are no properties for these groups. AnyCPU needs to appear in order for Visual Studio to perform
+ the build. The others are optional common platform types that may appear. -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|Win32' ">
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|Win32' ">
+ </PropertyGroup>
+ <ItemGroup>
+ <Folder Include="Content" />
+ <Folder Include="Content\VersionHistory" />
+ <Folder Include="icons" />
+ <Folder Include="media" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Content\VersionHistory\v1.0.0.0.aml" />
+ <None Include="Content\VersionHistory\VersionHistory.aml" />
+ <None Include="Content\Welcome.aml" />
+ </ItemGroup>
+ <ItemGroup>
+ <ContentLayout Include="ContentLayout.content" />
+ </ItemGroup>
+ <ItemGroup>
+ <Image Include="icons\Help.png">
+ <ImageId>Help</ImageId>
+ <AlternateText>Help</AlternateText>
+ </Image>
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="icons\machine_48px.png">
+ <ImageId>machine_48px</ImageId>
+ <AlternateText>machine 48px</AlternateText>
+ </Content>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Tango.FSE.Common\Tango.FSE.Common.csproj">
+ <Name>Tango.FSE.Common</Name>
+ <Project>{bc37cccb-7392-4f78-8d1c-e9629e6e046e}</Project>
+ <Private>False</Private>
+ </ProjectReference>
+ <ProjectReference Include="..\Tango.FSE.Procedures\Tango.FSE.Procedures.csproj">
+ <Name>Tango.FSE.Procedures</Name>
+ <Project>{1754f846-4763-4000-807f-c7bfaa145db2}</Project>
+ <Private>False</Private>
+ </ProjectReference>
+ </ItemGroup>
+ <!-- Import the SHFB build targets -->
+ <Import Project="$(SHFBROOT)\SandcastleHelpFileBuilder.targets" />
+ <!-- The pre-build and post-build event properties must appear *after* the targets file import in order to be
+ evaluated correctly. -->
+ <PropertyGroup>
+ <PreBuildEvent>
+ </PreBuildEvent>
+ <PostBuildEvent>copy /Y "$(OutputPath)proc-doc.chm" "$(SolutionDir)Build\FSE\$(Configuration)"
+</PostBuildEvent>
+ <RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/icons/Help.png b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/icons/Help.png
new file mode 100644
index 000000000..945e89fb9
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/icons/Help.png
Binary files differ
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/icons/machine_48px.png b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/icons/machine_48px.png
new file mode 100644
index 000000000..95cf615c5
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures.Documentation/icons/machine_48px.png
Binary files differ
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ArrayParsingStyle.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ArrayParsingStyle.cs
index c829a5b21..e731b7672 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ArrayParsingStyle.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ArrayParsingStyle.cs
@@ -6,9 +6,19 @@ using System.Threading.Tasks;
namespace Tango.FSE.Procedures
{
+ /// <summary>
+ /// Represents an array parsing style.
+ /// </summary>
public enum ArrayParsingStyle
{
+ /// <summary>
+ /// Formats the array separated by commas. (e.g 1,2,3,4...)
+ /// </summary>
Comma,
+
+ /// <summary>
+ /// Each item enclosed in square brackets. (e.g [1] [2] [3]...)
+ /// </summary>
SquareBrackets,
}
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/BreakPointRequestEventArgs.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/BreakPointRequestEventArgs.cs
new file mode 100644
index 000000000..768f4bb0d
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/BreakPointRequestEventArgs.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Scripting.Basic;
+using Tango.Scripting.Core;
+
+namespace Tango.FSE.Procedures
+{
+ public class BreakPointRequestEventArgs : EventArgs
+ {
+ private Action _releaseAction;
+
+ public int LineNumber { get; set; }
+ public Script Script { get; set; }
+
+ public List<ScriptBreakPointSymbol> Symbols { get; set; }
+
+ public BreakPointRequestEventArgs(Action releaseAction)
+ {
+ Symbols = new List<ScriptBreakPointSymbol>();
+ _releaseAction = releaseAction;
+ }
+
+ public void Release()
+ {
+ _releaseAction?.Invoke();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Contracts/IProcedureDesignerView.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Contracts/IProcedureDesignerView.cs
index 5797d622a..07899056c 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Contracts/IProcedureDesignerView.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Contracts/IProcedureDesignerView.cs
@@ -4,6 +4,8 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tango.FSE.Common;
+using Tango.Scripting.Basic;
+using Tango.Scripting.Core;
namespace Tango.FSE.Procedures.Contracts
{
@@ -21,5 +23,12 @@ namespace Tango.FSE.Procedures.Contracts
void ResetColrization();
void HighlightError(int position, int length);
void ClearErrors();
+ void ScrollToLine(int lineNumber);
+ void HighlightRuntimeError(int lineNumber);
+ void CloseRunTimeError();
+ List<ScriptBreakPoint> GetBreakPoints();
+ void HighlightBreakPointRequest(int lineNumber, List<ScriptBreakPointSymbol> symbols);
+ void ResetBreakPointRequest();
+ String GetCaretWord();
}
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Controls/ObjectInTreeView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Controls/ObjectInTreeView.xaml
new file mode 100644
index 000000000..d331935c8
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Controls/ObjectInTreeView.xaml
@@ -0,0 +1,27 @@
+<UserControl x:Class="Tango.FSE.Procedures.Controls.ObjectInTreeView"
+ 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:local="clr-namespace:Tango.FSE.Procedures.Controls"
+ mc:Ignorable="d"
+ d:DesignHeight="450" d:DesignWidth="800" x:Name="ObjectInTreeViewControl">
+ <TreeView ItemsSource="{Binding TreeNodes, ElementName=ObjectInTreeViewControl}" Style="{x:Null}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}" Background="Transparent" FontSize="{StaticResource FSE_SmallFontSize}" BorderThickness="0">
+ <TreeView.Resources>
+ <Style TargetType="TreeViewItem" BasedOn="{StaticResource {x:Type TreeViewItem}}">
+
+ </Style>
+ <HierarchicalDataTemplate DataType="{x:Type local:TreeNode}" ItemsSource="{Binding Path=Children}">
+ <TreeViewItem Style="{x:Null}">
+ <TreeViewItem.Header>
+ <StackPanel Orientation="Horizontal">
+ <TextBlock Text="{Binding Path=Name}"/>
+ <TextBlock Text=" : "/>
+ <TextBlock Text="{Binding Path=Value}"/>
+ </StackPanel>
+ </TreeViewItem.Header>
+ </TreeViewItem>
+ </HierarchicalDataTemplate>
+ </TreeView.Resources>
+ </TreeView>
+</UserControl>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Controls/ObjectInTreeView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Controls/ObjectInTreeView.xaml.cs
new file mode 100644
index 000000000..b1d1ee14d
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Controls/ObjectInTreeView.xaml.cs
@@ -0,0 +1,50 @@
+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.FSE.Procedures.Controls
+{
+ /// <summary>
+ /// Interaction logic for ObjectInTreeView.xaml
+ /// </summary>
+ public partial class ObjectInTreeView : UserControl
+ {
+ public ObjectInTreeView()
+ {
+ InitializeComponent();
+ }
+
+ public object ObjectToVisualize
+ {
+ get { return (object)GetValue(ObjectToVisualizeProperty); }
+ set { SetValue(ObjectToVisualizeProperty, value); }
+ }
+ public static readonly DependencyProperty ObjectToVisualizeProperty =
+ DependencyProperty.Register("ObjectToVisualize", typeof(object), typeof(ObjectInTreeView), new PropertyMetadata(null, OnObjectChanged));
+
+ private static void OnObjectChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ TreeNode tree = TreeNode.CreateTree(e.NewValue);
+ (d as ObjectInTreeView).TreeNodes = new List<TreeNode>() { tree };
+ }
+
+ public List<TreeNode> TreeNodes
+ {
+ get { return (List<TreeNode>)GetValue(TreeNodesProperty); }
+ set { SetValue(TreeNodesProperty, value); }
+ }
+ public static readonly DependencyProperty TreeNodesProperty =
+ DependencyProperty.Register("TreeNodes", typeof(List<TreeNode>), typeof(ObjectInTreeView), new PropertyMetadata(null));
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Controls/TreeNode.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Controls/TreeNode.cs
new file mode 100644
index 000000000..47407077f
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Controls/TreeNode.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Web.Script.Serialization;
+
+namespace Tango.FSE.Procedures.Controls
+{
+ public class TreeNode
+ {
+ public string Name { get; set; }
+ public string Value { get; set; }
+ public List<TreeNode> Children { get; set; } = new List<TreeNode>();
+
+ public static TreeNode CreateTree(object obj)
+ {
+ if (obj.GetType().IsValueTypeOrString())
+ {
+ return new TreeNode()
+ {
+ Name = "Value",
+ Value = obj.ToStringSafe()
+ };
+ }
+ else
+ {
+ JavaScriptSerializer jss = new JavaScriptSerializer();
+ var serialized = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
+ Dictionary<string, object> dic = jss.Deserialize<Dictionary<string, object>>(serialized);
+ var root = new TreeNode();
+ root.Name = "Root";
+ BuildTree(dic, root);
+ return root;
+ }
+ }
+
+ private static void BuildTree(object item, TreeNode node)
+ {
+ if (item is KeyValuePair<string, object>)
+ {
+ KeyValuePair<string, object> kv = (KeyValuePair<string, object>)item;
+ TreeNode keyValueNode = new TreeNode();
+ keyValueNode.Name = kv.Key;
+ keyValueNode.Value = GetValueAsString(kv.Value);
+ node.Children.Add(keyValueNode);
+ BuildTree(kv.Value, keyValueNode);
+ }
+ else if (item is ArrayList)
+ {
+ ArrayList list = (ArrayList)item;
+ int index = 0;
+ foreach (object value in list)
+ {
+ TreeNode arrayItem = new TreeNode();
+ arrayItem.Name = $"[{index}]";
+ arrayItem.Value = "";
+ node.Children.Add(arrayItem);
+ BuildTree(value, arrayItem);
+ index++;
+ }
+ }
+ else if (item is Dictionary<string, object>)
+ {
+ Dictionary<string, object> dictionary = (Dictionary<string, object>)item;
+ foreach (KeyValuePair<string, object> d in dictionary)
+ {
+ BuildTree(d, node);
+ }
+ }
+ }
+
+ private static string GetValueAsString(object value)
+ {
+ if (value == null)
+ return "null";
+ var type = value.GetType();
+ if (type.IsArray)
+ {
+ return "[]";
+ }
+
+ if (value is ArrayList)
+ {
+ var arr = value as ArrayList;
+ return $"[{arr.Count}]";
+ }
+
+ if (type.IsGenericType)
+ {
+ return "{}";
+ }
+
+ return value.ToString();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/DebugNode.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/DebugNode.cs
new file mode 100644
index 000000000..81f29c96c
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/DebugNode.cs
@@ -0,0 +1,256 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Core;
+using Tango.Core.Commands;
+
+namespace Tango.FSE.Procedures
+{
+ public class DebugNode : ExtendedObject
+ {
+ private Object _originalValue;
+
+ public String Name { get; set; }
+ public Object ParentObject { get; set; }
+
+ private Object _value;
+ public Object Value
+ {
+ get { return _value; }
+ set
+ {
+ _value = value;
+
+ if (_originalValue == null)
+ {
+ _originalValue = _value;
+ }
+
+ DisplayValue = GetDisplayValue(_value);
+ RaisePropertyChangedAuto();
+ }
+ }
+
+ public bool IsSimpleValue { get; set; }
+
+ public String Type { get; set; }
+ public PropertyInfo PropertyInfo { get; set; }
+ public FieldInfo FieldInfo { get; set; }
+
+ public Type MemberType
+ {
+ get
+ {
+ if (PropertyInfo != null)
+ {
+ return PropertyInfo.PropertyType;
+ }
+ else if (FieldInfo != null)
+ {
+ return FieldInfo.FieldType;
+ }
+ else
+ {
+ return Value.GetType();
+ }
+ }
+ }
+
+ private bool _isEdited;
+ public bool IsEdited
+ {
+ get { return _isEdited; }
+ set { _isEdited = value; RaisePropertyChangedAuto(); }
+ }
+
+ public RelayCommand UpdateValueCommand { get; set; }
+
+ public bool IsEditable
+ {
+ get
+ {
+ if (IsSimpleValue)
+ {
+ return false; //Sorry can't update simple script symbols as they are passed to me by value...
+ }
+
+ if (MemberType != null && MemberType.IsValueTypeOrString() && ((PropertyInfo != null && PropertyInfo.SetMethod != null) || FieldInfo != null))
+ {
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ private Object _displayValue;
+ public Object DisplayValue
+ {
+ get { return _displayValue; }
+ set { _displayValue = value; RaisePropertyChangedAuto(); }
+ }
+
+ public List<DebugNode> Nodes
+ {
+ get
+ {
+ return GetChildNodes();
+ }
+ }
+
+ public DebugNode()
+ {
+ UpdateValueCommand = new RelayCommand(UpdateValue);
+ }
+
+ private void UpdateValue()
+ {
+ try
+ {
+ if (IsSimpleValue && Value != null)
+ {
+ _value = Convert.ChangeType(DisplayValue, Value.GetType());
+ IsEdited = _originalValue.ToStringSafe() != Value.ToStringSafe();
+ }
+ else if (IsEditable && ((PropertyInfo != null && PropertyInfo.SetMethod != null) || FieldInfo != null))
+ {
+ if (PropertyInfo != null)
+ {
+ _value = Convert.ChangeType(DisplayValue, PropertyInfo.PropertyType);
+ PropertyInfo.SetValue(ParentObject, Value);
+ IsEdited = _originalValue.ToStringSafe() != Value.ToStringSafe();
+ }
+ else if (FieldInfo != null)
+ {
+ _value = Convert.ChangeType(DisplayValue, FieldInfo.FieldType);
+ FieldInfo.SetValue(ParentObject, Value);
+ IsEdited = _originalValue.ToStringSafe() != Value.ToStringSafe();
+ }
+ }
+ }
+ catch { }
+
+ DisplayValue = GetDisplayValue(Value);
+ }
+
+ private List<DebugNode> GetChildNodes()
+ {
+ List<DebugNode> childNodes = new List<DebugNode>();
+
+ if (Value == null) return childNodes;
+
+ var type = Value.GetType();
+
+ if (type.IsValueTypeOrString())
+ {
+ return childNodes;
+ }
+
+ if (typeof(IEnumerable).IsAssignableFrom(type) && type != typeof(String))
+ {
+ List<Object> list = (Value as IEnumerable).Cast<Object>().ToList();
+
+ for (int i = 0; i < list.Count; i++)
+ {
+ var item = list[i];
+
+ DebugNode listNode = new DebugNode();
+ listNode.Name = $"[{i}]";
+ listNode.Value = item;
+ listNode.Type = GetFriendlyName(item.GetType());
+ childNodes.Add(listNode);
+ }
+ }
+ else
+ {
+ foreach (var prop in type.GetProperties(BindingFlags.Instance | BindingFlags.Public))
+ {
+ DebugNode propNode = new DebugNode();
+ propNode.Type = GetFriendlyName(prop.PropertyType);
+ propNode.Name = prop.Name;
+ propNode.Value = prop.GetValue(Value);
+ propNode.PropertyInfo = prop;
+ propNode.ParentObject = Value;
+ childNodes.Add(propNode);
+ }
+
+ foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.Public))
+ {
+ DebugNode propNode = new DebugNode();
+ propNode.Type = GetFriendlyName(field.FieldType);
+ propNode.Name = field.Name;
+ propNode.Value = field.GetValue(Value);
+ propNode.FieldInfo = field;
+ propNode.ParentObject = Value;
+ childNodes.Add(propNode);
+ }
+ }
+
+ return childNodes;
+ }
+
+ public static DebugNode CreateNode(String name, Object obj)
+ {
+ DebugNode node = new DebugNode();
+ node.Name = name;
+ node.Value = obj;
+ node.Type = GetFriendlyName(obj.GetType());
+
+ if (obj.GetType().IsValueTypeOrString())
+ {
+ node.IsSimpleValue = true;
+ }
+
+ return node;
+ }
+
+ private static String GetFriendlyName(Type type)
+ {
+ if (type == typeof(int))
+ return "int";
+ else if (type == typeof(short))
+ return "short";
+ else if (type == typeof(byte))
+ return "byte";
+ else if (type == typeof(bool))
+ return "bool";
+ else if (type == typeof(long))
+ return "long";
+ else if (type == typeof(float))
+ return "float";
+ else if (type == typeof(double))
+ return "double";
+ else if (type == typeof(decimal))
+ return "decimal";
+ else if (type == typeof(string))
+ return "string";
+ else if (type.IsGenericType)
+ return type.Name.Split('`')[0] + "<" + string.Join(", ", type.GetGenericArguments().Select(x => GetFriendlyName(x)).ToArray()) + ">";
+ else
+ return type.Name;
+ }
+
+ private static Object GetDisplayValue(Object value)
+ {
+ if (value == null)
+ {
+ return "null";
+ }
+ else if (value.GetType().IsValueTypeOrString())
+ {
+ return value;
+ }
+ else if (typeof(IEnumerable).IsAssignableFrom(value.GetType()))
+ {
+ List<Object> list = (value as IEnumerable).Cast<Object>().ToList();
+ return $"Count = {list.Count}";
+ }
+
+ return value.ToStringSafe();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Dialogs/BreakPointValueDialogView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Dialogs/BreakPointValueDialogView.xaml
new file mode 100644
index 000000000..0c96cf33e
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Dialogs/BreakPointValueDialogView.xaml
@@ -0,0 +1,24 @@
+<UserControl x:Class="Tango.FSE.Procedures.Dialogs.BreakPointValueDialogView"
+ 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:material="http://materialdesigninxaml.net/winfx/xaml/themes"
+ xmlns:local="clr-namespace:Tango.FSE.Procedures.Dialogs"
+ mc:Ignorable="d"
+ Width="700" Height="500" d:DataContext="{d:DesignInstance Type=local:BreakPointValueDialogViewVM, IsDesignTimeCreatable=False}" Background="{StaticResource FSE_PrimaryBackgroundLightBrush}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}">
+ <Grid Margin="10">
+ <DockPanel>
+ <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
+ <material:PackIcon Kind="Cube" Width="32" Height="32" />
+ <TextBlock Margin="10 0 0 0" FontSize="{StaticResource FSE_LargeFontSize}" VerticalAlignment="Center" Text="{Binding Name}"></TextBlock>
+ </StackPanel>
+
+ <CheckBox DockPanel.Dock="Bottom" Margin="0 10 0 0" IsChecked="{Binding AsJson}">Display in JSON format</CheckBox>
+
+ <Border Margin="0 20 0 0" BorderThickness="1" BorderBrush="{StaticResource FSE_BorderBrush}" Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}" CornerRadius="5">
+ <TextBox Style="{StaticResource FSE_Rounded_Corners_TextBox_Multiline}" FontSize="{StaticResource FSE_SmallFontSize}" Foreground="{StaticResource FSE_GrayBrush}" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" IsReadOnly="True" Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}" Text="{Binding DisplayValue,Mode=OneWay}"></TextBox>
+ </Border>
+ </DockPanel>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Dialogs/BreakPointValueDialogView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Dialogs/BreakPointValueDialogView.xaml.cs
new file mode 100644
index 000000000..ec496e7fc
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Dialogs/BreakPointValueDialogView.xaml.cs
@@ -0,0 +1,28 @@
+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.FSE.Procedures.Dialogs
+{
+ /// <summary>
+ /// Interaction logic for BreakPointValueDialogView.xaml
+ /// </summary>
+ public partial class BreakPointValueDialogView : UserControl
+ {
+ public BreakPointValueDialogView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Dialogs/BreakPointValueDialogViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Dialogs/BreakPointValueDialogViewVM.cs
new file mode 100644
index 000000000..13d952ffd
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Dialogs/BreakPointValueDialogViewVM.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Core.ExtensionMethods;
+using Tango.FSE.Common;
+
+namespace Tango.FSE.Procedures.Dialogs
+{
+ public class BreakPointValueDialogViewVM : FSEDialogViewVM
+ {
+ public String Name { get; set; }
+
+ public Object DebugObject { get; set; }
+
+ private bool _asJson;
+ public bool AsJson
+ {
+ get { return _asJson; }
+ set { _asJson = value; RaisePropertyChangedAuto(); RaisePropertyChanged(nameof(DisplayValue)); }
+ }
+
+ public BreakPointValueDialogViewVM(String name, Object debugObject)
+ {
+ AutoMode = false;
+ CanCancel = true;
+ CanClose = true;
+ Name = name;
+ DebugObject = debugObject;
+ }
+
+ public String DisplayValue
+ {
+ get
+ {
+ if (DebugObject != null)
+ {
+ if (AsJson)
+ {
+ try
+ {
+ return DebugObject.ToJsonString();
+ }
+ catch
+ {
+ return DebugObject.ToString();
+ }
+ }
+ else
+ {
+ return DebugObject.ToString();
+ }
+ }
+
+ return "null";
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/AddResult/Program.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/AddResult/Program.cs
new file mode 100644
index 000000000..750dd436d
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/AddResult/Program.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Drawing;
+using Google.Protobuf;
+using Tango.BL.Entities;
+using Tango.BL.Enumerations;
+using Tango.PMR.Stubs;
+using Tango.PMR.Diagnostics;
+using Tango.FSE.Common.Connection;
+using Tango.FSE.Common.Diagnostics;
+using Tango.FSE.Procedures;
+
+namespace Tango.FSE.Procedures.Examples.AddResult
+{
+ #region Example
+ public class Program
+ {
+ public class Person
+ {
+ public int Age;
+
+ //Here we use the Description attribute in order to set a custom name
+ //for this field at the results grid and csv file.
+ [Description("First Name")]
+ public String Name;
+ }
+
+ public void OnExecute(IProcedureContext context)
+ {
+ //Add scalar result with the value 10.
+ context.AddResult(ResultType.Passed, "My Scalar Result", 10);
+
+ //Initialize a list of persons.
+ List<Person> persons = new List<Person>();
+
+ for (int i = 0; i < 100; i++)
+ {
+ Person p = new Person();
+ p.Age = i;
+ p.Name = "Name " + i;
+ persons.Add(p);
+ }
+
+ //Add the persons list as a result.
+ //This will allow the user to display a grid with all the persons in the list.
+ //The list can also be exported to CSV.
+ context.AddResult(ResultType.Passed, "Persons", persons);
+
+ //Here is how we can get only the ages from the persons list and cast them as double values.
+ List<double> ages = persons.Select(x => x.Age).Cast<double>().ToList();
+
+ //Adding the ages list as a result..
+ context.AddResult(ResultType.Passed, "Ages", ages);
+
+ //Plotting the ages list as a graph result..
+ context.AddGraphResult(ResultType.Passed, "Ages Graph", ages);
+
+
+
+ //And here is how we can draw a completely customized result by drawing a bitmap.
+ Bitmap bitmap = context.CreateBitmap(400, 200);
+ Graphics g = context.GetDrawingContext(bitmap);
+
+ //Draw a simple rectangle border.
+ g.DrawRectangle(Pens.Gray, 0, 0, 399, 199);
+
+ //Draw a diagonal red line across the rectangle.
+ g.DrawLine(Pens.Red, 0, 0, 400, 200);
+
+ //Draw a string at the center of the rect.
+ Font font = new Font("Tahoma", 24, FontStyle.Bold, GraphicsUnit.Pixel);
+ RectangleF layout = new RectangleF(0, 0, 400, 200);
+ StringFormat format = new StringFormat();
+ format.Alignment = StringAlignment.Center;
+ format.LineAlignment = StringAlignment.Center;
+ g.DrawString("Bitmap Result", font, Brushes.YellowGreen, layout, format);
+
+ //Dispose the drawing context after you done drawing.
+ g.Dispose();
+
+ context.AddBitmapResult(ResultType.Passed, "Bitmap Result", bitmap);
+ }
+ }
+ #endregion
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/Connection/Program.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/Connection/Program.cs
new file mode 100644
index 000000000..63c8cc5f7
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/Connection/Program.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Drawing;
+using Google.Protobuf;
+using Tango.BL.Entities;
+using Tango.BL.Enumerations;
+using Tango.PMR.Stubs;
+using Tango.PMR.Diagnostics;
+using Tango.FSE.Common.Connection;
+using Tango.FSE.Common.Diagnostics;
+using Tango.FSE.Procedures;
+
+namespace Tango.FSE.Procedures.Examples.Connection
+{
+ #region Example
+ public class Program
+ {
+ public void OnExecute(IProcedureContext context)
+ {
+
+ if (context.IsConnected) //Check if there is an active machine connection.
+ {
+ if (context.ConnectionType == MachineConnectionTypes.Wifi) //Check enumeration of the active connection type.
+ {
+ context.WriteLine("Machine " + context.ConnectedMachine.SerialNumber + " is connected via WiFi.");
+ }
+ }
+
+ }
+ }
+ #endregion
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/Csv/Program.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/Csv/Program.cs
new file mode 100644
index 000000000..70526436b
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/Csv/Program.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Drawing;
+using Google.Protobuf;
+using Tango.BL.Entities;
+using Tango.BL.Enumerations;
+using Tango.PMR.Stubs;
+using Tango.PMR.Diagnostics;
+using Tango.FSE.Common.Connection;
+using Tango.FSE.Common.Diagnostics;
+using Tango.FSE.Procedures;
+
+namespace Tango.FSE.Procedures.Examples.Csv
+{
+ #region Example
+ //CSV Model must contain properties, not plain fields.
+ public class Person
+ {
+ public String Name { get; set; }
+ public int Age { get; set; }
+ }
+
+ public class Program
+ {
+ //This example demonstrates CSV file writing and reading.
+ //The csv reading method also accepts a byte array so you can also read a CSV file from resource.
+ public void OnExecute(IProcedureContext context)
+ {
+ //Initialize a list of person model (see Person.csx).
+ List<Person> persons = new List<Person>();
+
+ for (int i = 0; i < 100; i++)
+ {
+ Person p = new Person();
+ p.Name = "Person " + i;
+ p.Age = i;
+ persons.Add(p);
+ }
+
+ //Request the user to choose the csv file location.
+ String csvFile = context.RequestFileSave("Select CSV File Location", "*.csv", "persons.csv");
+
+ if (csvFile != null) //Check if user selected a file and pressed 'OK'.
+ {
+ //Write the persons list to the selected csv file.
+ context.WriteCsv<Person>(csvFile, persons);
+
+ //Test csv file for reading...
+ persons = context.ReadCsv<Person>(csvFile);
+
+ //Write the reading result to the output window.
+ context.WriteLine(persons);
+ }
+ }
+ }
+ #endregion
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/Diagnostics/Program.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/Diagnostics/Program.cs
new file mode 100644
index 000000000..c783abaa1
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/Diagnostics/Program.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Drawing;
+using Google.Protobuf;
+using Tango.BL.Entities;
+using Tango.BL.Enumerations;
+using Tango.PMR.Stubs;
+using Tango.PMR.Diagnostics;
+using Tango.FSE.Common.Connection;
+using Tango.FSE.Common.Diagnostics;
+using Tango.FSE.Procedures;
+
+namespace Tango.FSE.Procedures.Examples.Diagnostics
+{
+ #region Example
+ public class Program
+ {
+ public void OnExecute(IProcedureContext context)
+ {
+ //Initialize a new list of dancer angle values.
+ List<double> dancerValues = new List<double>();
+
+ //Collect 100 samples of the middle dancer angle.
+ for (int i = 0; i < 100; i++)
+ {
+ //Get the current diagnostics package. (set 'true' to block the execution until a fresh diagnostics frame arrives)
+ DiagnosticsPackage package = context.GetDiagnosticsPackage(true);
+
+ //Add the last value in the array to the list.
+ dancerValues.Add(package.GetMonitorLastValue(TechMonitors.Dancer2Angle));
+ }
+
+ //Plot the dancer samples to a graph result.
+ context.AddGraphResult(ResultType.Passed, "Dancer Angle", dancerValues);
+ }
+ }
+ #endregion
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/RequestUserInputFor/Program.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/RequestUserInputFor/Program.cs
new file mode 100644
index 000000000..3ea277bf8
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/RequestUserInputFor/Program.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Drawing;
+using Google.Protobuf;
+using Tango.BL.Entities;
+using Tango.BL.Enumerations;
+using Tango.PMR.Stubs;
+using Tango.PMR.Diagnostics;
+using Tango.FSE.Common.Connection;
+using Tango.FSE.Common.Diagnostics;
+using Tango.FSE.Procedures;
+
+namespace Tango.FSE.Procedures.Examples.RequestUserInputFor
+{
+ #region Example
+ public enum PersonType
+ {
+ Student = 0,
+ Employee = 1,
+ Guest = 2
+ }
+
+ public class Person
+ {
+ public int Age;
+ public String name;
+ public bool Activated;
+ public PersonType Type = PersonType.Employee;
+ }
+
+ public class Program
+ {
+ public void OnExecute(IProcedureContext context)
+ {
+
+ Person p = context.RequestUserInputFor<Person>("Input Demo", "Please fill in the form");
+ context.WriteLine(p);
+
+ }
+ }
+ #endregion
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/Send/Program.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/Send/Program.cs
new file mode 100644
index 000000000..bf7c38e13
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/Send/Program.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Drawing;
+using Google.Protobuf;
+using Tango.BL.Entities;
+using Tango.BL.Enumerations;
+using Tango.PMR.Stubs;
+using Tango.PMR.Diagnostics;
+using Tango.FSE.Common.Connection;
+using Tango.FSE.Common.Diagnostics;
+using Tango.FSE.Procedures;
+
+namespace Tango.FSE.Procedures.Examples.Send
+{
+ #region Example
+ public class Program
+ {
+ public void OnExecute(IProcedureContext context)
+ {
+ //Sends a request by providing the request name and comma separated arguments.
+ CalculateResponse response1 = context.Send<CalculateResponse>("CalculateRequest", 10, 5);
+
+ //Sends a request by providing the request short name and comma separated arguments.
+ CalculateResponse response2 = context.Send<CalculateResponse>("calculate", 10, 5);
+
+ //Sends a request by providing the request short name, a timeout and comma separated arguments.
+ CalculateResponse response3 = context.Send<CalculateResponse>("calculate", TimeSpan.FromSeconds(5), 10, 5);
+
+ //Sends a request by providing a request object.
+ CalculateRequest request = new CalculateRequest();
+ request.A = 10;
+ request.B = 5;
+
+ CalculateResponse response4 = context.Send<CalculateResponse>(request);
+
+ //Sends a request by providing a request object and 5 seconds timeout.
+ CalculateResponse response5 = context.Send<CalculateResponse>(request, 5);
+ }
+ }
+ #endregion
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/SendContinuous/Program.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/SendContinuous/Program.cs
new file mode 100644
index 000000000..2f8115642
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/SendContinuous/Program.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Drawing;
+using Google.Protobuf;
+using Tango.BL.Entities;
+using Tango.BL.Enumerations;
+using Tango.PMR.Stubs;
+using Tango.PMR.Diagnostics;
+using Tango.FSE.Common.Connection;
+using Tango.FSE.Common.Diagnostics;
+using Tango.FSE.Procedures;
+
+namespace Tango.FSE.Procedures.Examples.SendContinuous
+{
+ #region Example
+ public class Program
+ {
+ private IProcedureContext _context;
+
+ public void OnExecute(IProcedureContext context)
+ {
+ //Sends a continuous request by providing the request name, a callback method and comma separated arguments.
+ context.SendContinuous<ProgressResponse>("ProgressRequest", (response) =>
+ {
+ //Each response will be provided here...
+ context.WriteLine(response);
+ }, 100, 10);
+
+
+ //Sends a continuous request by providing the request name, a callback method, a timeout, and comma separated arguments.
+ context.SendContinuous<ProgressResponse>("progress", (response) =>
+ {
+ context.WriteLine(response);
+ }, TimeSpan.FromSeconds(5), 100, 10);
+
+
+ //Sends a continuous request by providing the request object, a callback method and a 5 seconds timeout.
+ ProgressRequest request = new ProgressRequest();
+ request.Amount = 100;
+ request.Delay = 10;
+
+ context.SendContinuous<ProgressResponse>(request, (response) =>
+ {
+ context.WriteLine(response);
+ }, 5);
+
+
+ //Sends a continuous request by providing the request object, a defined callback method and a 5 seconds timeout.
+ //We need to store the context globally so the callback method will have access to it.
+ _context = context;
+ context.SendContinuous<ProgressResponse>(request, OnProgressResponse, 5);
+ }
+
+ private void OnProgressResponse(ProgressResponse response)
+ {
+ _context.WriteLine(response);
+ }
+ }
+ #endregion
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/Sql/Program.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/Sql/Program.cs
new file mode 100644
index 000000000..33072a2dd
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Examples/Sql/Program.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Drawing;
+using Google.Protobuf;
+using Tango.BL.Entities;
+using Tango.BL.Enumerations;
+using Tango.PMR.Stubs;
+using Tango.PMR.Diagnostics;
+using Tango.FSE.Common.Connection;
+using Tango.FSE.Common.Diagnostics;
+using Tango.FSE.Procedures;
+
+namespace Tango.FSE.Procedures.Examples.Sql
+{
+ #region Example
+ //Additional name spaces that are required for working with remote SQL.
+ using Tango.FSE.Common.SQL;
+ using Tango.PPC.Shared.SQL;
+
+ public class Program
+ {
+ public void OnExecute(IProcedureContext context)
+ {
+
+ //Get the remote SQL provider from the Tango IOC container.
+ IRemoteSqlProvider sql = context.GetService<IRemoteSqlProvider>();
+
+ //Create the SQL command and direct it to affect both the local machine's database and the global Twine's database.
+ RemoteSqlCommand command = new RemoteSqlCommand();
+ command.SQL = "UPDATE MACHINES SET IS_DEMO = 0 WHERE SERIAL_NUMBER = '" + context.ConnectedMachine.SerialNumber + "'";
+ command.Mode = RemoteSqlCommandMode.Both;
+
+ //Execute the command...
+ RemoteSqlCommandResult result = sql.ExecuteSqlCommand(command);
+
+ context.WriteLine("Command executed.");
+ context.WriteLine("Local Affected Rows " + result.LocalAffectedRecords);
+ context.WriteLine("Global Affected Rows " + result.GlobalAffectedRecords);
+
+ context.WriteLine("");
+
+ //Query the machine's database for all the jobs names and length.
+ command.SQL = "SELECT NAME,LAST_RUN FROM JOBS";
+ command.Mode = RemoteSqlCommandMode.Local;
+
+ result = sql.ExecuteSqlCommand(command);
+
+ //Check for errors.
+ if (!result.HasLocalError)
+ {
+ //Write the formatted results set to the console.
+ context.WriteLine(result.LocalDatSet.ToTableString());
+ context.WriteLine("");
+
+ //Iterate over the data set rows and get values.
+ foreach (RemoteSqlRow row in result.LocalDatSet.Rows)
+ {
+ String name = row.Get<String>("NAME");
+ String lastRun = row.Get<String>("LAST_RUN");
+
+ context.WriteLine(String.Format("NAME {0}, LAST_RUN {1}", name, lastRun));
+ }
+ }
+ else
+ {
+ //Write the error to console.
+ context.WriteLine(result.LocalError);
+ }
+ }
+ }
+ #endregion
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ExtensionMethods/TreeViewExtensions.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ExtensionMethods/TreeViewExtensions.cs
new file mode 100644
index 000000000..0859affc2
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ExtensionMethods/TreeViewExtensions.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Controls;
+
+public static class TreeViewExtensions
+{
+ public static void SetExpansion(this TreeView treeView, bool isExpanded) => SetExpansion((ItemsControl)treeView, isExpanded);
+
+ private static void SetExpansion(ItemsControl parent, bool isExpanded)
+ {
+ if (parent == null) return;
+
+ if (parent is TreeViewItem tvi)
+ tvi.IsExpanded = isExpanded;
+
+ if (parent.HasItems)
+ foreach (var item in parent.Items.Cast<object>()
+ .Select(i => GetTreeViewItem(parent, i, isExpanded)))
+ SetExpansion(item, isExpanded);
+ }
+
+ private static TreeViewItem GetTreeViewItem(ItemsControl parent, object item, bool isExpanded)
+ {
+ if (item is TreeViewItem tvi)
+ return tvi;
+
+ var result = ContainerFromItem(parent, item);
+ if (result == null && isExpanded)
+ {
+ parent.UpdateLayout();
+ result = ContainerFromItem(parent, item);
+ }
+ return result;
+ }
+
+ static TreeViewItem ContainerFromItem(ItemsControl parent, object item) => (TreeViewItem)parent.ItemContainerGenerator.ContainerFromItem(item);
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Helpers/ProcedureExceptionHelper.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Helpers/ProcedureExceptionHelper.cs
new file mode 100644
index 000000000..7a57681e7
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Helpers/ProcedureExceptionHelper.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+namespace Tango.FSE.Procedures.Helpers
+{
+ public static class ProcedureExceptionHelper
+ {
+ public static int? GetExceptionLineNumber(Exception ex, ProcedureProject project)
+ {
+ try
+ {
+ Regex regex = new Regex(@"OnExecute\(IProcedureContext context\) in :line (\d+)");
+ var matches = regex.Matches(ex.ToString()).OfType<Match>().ToList();
+
+ if (matches.Count > 0)
+ {
+ var match = matches.First();
+
+ if (match.Groups.Count > 1)
+ {
+ var line = match.Groups[1].Value;
+ int lineNumber = int.Parse(line) - project.Scripts.Count + 1;
+ return lineNumber;
+ }
+ }
+ }
+ catch { }
+
+ return null;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/IDialogController.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/IDialogController.cs
index 50865e66d..9462330d6 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/IDialogController.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/IDialogController.cs
@@ -7,10 +7,27 @@ using System.Windows;
namespace Tango.FSE.Procedures
{
+ /// <summary>
+ /// Represents a procedure dialog controller.
+ /// </summary>
public interface IDialogController
{
+ /// <summary>
+ /// Opens the dialog.
+ /// </summary>
void Show();
+
+ /// <summary>
+ /// Finds the dialog control of type T.
+ /// </summary>
+ /// <typeparam name="T">Type of expected control.</typeparam>
+ /// <param name="name">The name of the control in terms of 'x:Name="..."'.</param>
+ /// <returns>Returns the control if it was found.</returns>
T FindControl<T>(String name) where T : DependencyObject;
+
+ /// <summary>
+ /// Closes the dialog.
+ /// </summary>
void Close();
}
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/IProcedureContext.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/IProcedureContext.cs
index e93311d80..829da6a43 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/IProcedureContext.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/IProcedureContext.cs
@@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
using System.Linq;
+using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -14,61 +15,105 @@ using Tango.FSE.Common.Connection;
using Tango.FSE.Common.Diagnostics;
using Tango.Integration.Operation;
using Tango.Scripting.Basic;
+using Tango.Scripting.Editors.Intellisense;
namespace Tango.FSE.Procedures
{
+ /// <summary>
+ /// Represents the main procedures API.
+ /// </summary>
+ /// <seealso cref="Tango.Scripting.Basic.IContext" />
public interface IProcedureContext : IContext
{
/// <summary>
/// Occurs when the procedure is reporting about some progress.
/// </summary>
+ [HideIntellisense]
event EventHandler<TangoProgressChangedEventArgs<double>> Progress;
/// <summary>
+ /// Occurs when a procedure object break point request occurs through the IDE break points.
+ /// </summary>
+ [HideIntellisense]
+ event EventHandler<BreakPointRequestEventArgs> BreakPointRequest;
+
+ /// <summary>
/// Gets the list of current results.
/// </summary>
+ [HideIntellisense]
ReadOnlyCollection<Result> Results { get; }
/// <summary>
/// Adds a new procedure result.
+ /// The value object can be a primitive, a collection of primitives or a collection of complex types.
/// </summary>
- /// <param name="type">The result type.</param>
- /// <param name="name">The result name.</param>
- /// <param name="value">The result value.</param>
- /// <returns></returns>
+ /// <param name="type">Result type.</param>
+ /// <param name="name">Result title.</param>
+ /// <param name="value">Result value.</param>
+ /// <returns>The result instance.</returns>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to add various procedure results.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/AddResult/Program.cs" title="Add results" region="Example" />
+ /// </example>
Result AddResult(ResultType type, String name, object value);
/// <summary>
- /// Adds a new procedure graph result.
+ /// Adds a new procedure result that will be displayed as a graph with X/Y axis.
+ /// The specified values will be plotted as Y axis values while the X axis will be auto generated by each value index.
/// </summary>
- /// <param name="type">The type.</param>
- /// <param name="name">The name.</param>
- /// <param name="values">The values.</param>
- /// <returns></returns>
+ /// <param name="type">Result type.</param>
+ /// <param name="name">Result title.</param>
+ /// <param name="values">Graph Y axis values.</param>
+ /// <returns>The result instance.</returns>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to add various procedure results.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/AddResult/Program.cs" title="Add results" region="Example" />
+ /// </example>
Result AddGraphResult(ResultType type, String name, IEnumerable<double> values);
/// <summary>
- /// Adds a new procedure bitmap result.
+ /// Adds a new procedure result with custom appearance by providing a bitmap to draw as the result.
+ /// Use the <see cref="CreateBitmap(int, int)"/> to create a new bitmap.
+ /// Then, <see cref="GetDrawingContext(Bitmap)"/> to get the bitmap drawing context in order to start drawing.
/// </summary>
- /// <param name="type">The type.</param>
- /// <param name="name">The name.</param>
- /// <param name="bitmap">The bitmap.</param>
- /// <returns></returns>
+ /// <param name="type">Result type.</param>
+ /// <param name="name">Result title.</param>
+ /// <param name="bitmap">Result bitmap.</param>
+ /// <returns>The result instance.</returns>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to add various procedure results.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/AddResult/Program.cs" title="Add results" region="Example" />
+ /// </example>
Result AddBitmapResult(ResultType type, String name, Bitmap bitmap);
/// <summary>
- /// Creates a new bitmap.
+ /// Creates a new bitmap to be provided as a bitmap result via <see cref="AddBitmapResult(ResultType, string, Bitmap)"/>.
/// </summary>
/// <param name="width">The bitmap width.</param>
/// <param name="height">The bitmap height.</param>
- /// <returns></returns>
+ /// <returns>The bitmap instance.</returns>
Bitmap CreateBitmap(int width, int height);
/// <summary>
/// Creates a new drawing context for the specified bitmap.
/// </summary>
+ /// <remarks>
+ /// Please use <see cref="Graphics.Dispose"/> when finish drawing.
+ /// </remarks>
/// <param name="bitmap">The bitmap.</param>
- /// <returns></returns>
+ /// <returns>The drawing context.</returns>
Graphics GetDrawingContext(Bitmap bitmap);
/// <summary>
@@ -76,6 +121,7 @@ namespace Tango.FSE.Procedures
/// </summary>
/// <param name="result">The result.</param>
/// <returns></returns>
+ [HideIntellisense]
Result AddResult(Result result);
/// <summary>
@@ -90,84 +136,174 @@ namespace Tango.FSE.Procedures
void ClearResults();
/// <summary>
- /// Sends a request by name with optional comma separated arguments.
+ /// Sends a stub request by name, with optional timeout and comma separated arguments.
/// </summary>
- /// <param name="messageName">Name of the message.</param>
- /// <param name="timeout">The timeout in seconds.</param>
- /// <param name="args">The arguments separated by commas.</param>
- /// <returns></returns>
+ /// <remarks>
+ /// This method accepts only stub messages.
+ /// </remarks>
+ /// <param name="messageName">Full or shortened name of the message (e.g "CalculateRequest" or "calculate").</param>
+ /// <param name="timeout">Request timeout.</param>
+ /// <param name="args">Request arguments separated by commas.</param>
+ /// <returns>The corresponding response message.</returns>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to send a request to the machine and get a response using the various different Send method overrides.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/Send/Program.cs" title="Send a request" region="Example" />
+ /// </example>
IMessage Send(String messageName, TimeSpan? timeout = null, params Object[] args);
/// <summary>
/// Sends a request by name with optional comma separated arguments.
/// </summary>
- /// <param name="messageName">Name of the message.</param>
- /// <param name="args">The arguments separated by commas.</param>
- /// <returns></returns>
+ /// <remarks>
+ /// This method accepts only stub messages.
+ /// </remarks>
+ /// <param name="messageName">Full or shortened name of the message (e.g "CalculateRequest" or "calculate").</param>
+ /// <param name="args">Request arguments separated by commas.</param>
+ /// <returns>The corresponding response message.</returns>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to send a request to the machine and get a response using the various different Send method overrides.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/Send/Program.cs" title="Send a request" region="Example" />
+ /// </example>
IMessage Send(String messageName, params Object[] args);
/// <summary>
- /// Sends a request by name with optional comma separated arguments.
+ /// Sends a request by name with optional timeout and comma separated arguments.
/// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="messageName">Name of the message.</param>
- /// <param name="timeout">The timeout in seconds.</param>
- /// <param name="args">The arguments separated by commas.</param>
- /// <returns></returns>
+ /// <remarks>
+ /// This method accepts only stub messages.
+ /// </remarks>
+ /// <typeparam name="T">Type of expected response message.</typeparam>
+ /// <param name="messageName">Full or shortened name of the message (e.g "CalculateRequest" or "calculate").</param>
+ /// <param name="timeout">The request timeout.</param>
+ /// <param name="args">Request arguments separated by commas.</param>
+ /// <returns>The corresponding response message of type T.</returns>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to send a request to the machine and get a response using the various different Send method overrides.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/Send/Program.cs" title="Send a request" region="Example" />
+ /// </example>
T Send<T>(String messageName, TimeSpan? timeout = null, params Object[] args) where T : class, IMessage;
/// <summary>
/// Sends a request by name with optional comma separated arguments.
/// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="messageName">Name of the message.</param>
- /// <param name="args">The arguments separated by commas.</param>
- /// <returns></returns>
+ /// <remarks>
+ /// This method accepts only stub messages.
+ /// </remarks>
+ /// <typeparam name="T">Type of expected response message.</typeparam>
+ /// <param name="messageName">Full or shortened name of the message (e.g "CalculateRequest" or "calculate").</param>
+ /// <param name="args">Request arguments separated by commas.</param>
+ /// <returns>The corresponding response message of type T.</returns>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to send a request to the machine and get a response using the various different Send method overrides.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/Send/Program.cs" title="Send a request" region="Example" />
+ /// </example>
T Send<T>(String messageName, params Object[] args) where T : class, IMessage;
/// <summary>
- /// Sends the specified message.
+ /// Sends the specified request message.
/// </summary>
- /// <param name="message">The message.</param>
- /// <param name="timeout">The timeout in seconds.</param>
- /// <returns></returns>
+ /// <param name="message">Request message instance.</param>
+ /// <param name="timeout">Request timeout in seconds. (leave empty to get the default timeout)</param>
+ /// <returns>The corresponding response message.</returns>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to send a request to the machine and get a response using the various different Send method overrides.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/Send/Program.cs" title="Send a request" region="Example" />
+ /// </example>
IMessage Send(IMessage message, int? timeout = null);
/// <summary>
- /// Sends the specified message.
+ /// Sends the specified request message.
/// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="message">The message.</param>
- /// <param name="timeout">The timeout in seconds.</param>
- /// <returns></returns>
+ /// <typeparam name="T">Type of expected response message.</typeparam>
+ /// <param name="message">Request message instance.</param>
+ /// <param name="timeout">Request timeout in seconds. (leave empty to get the default timeout)</param>
+ /// <returns>The corresponding response message of type T.</returns>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to send a request to the machine and get a response using the various different Send method overrides.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/Send/Program.cs" title="Send a request" region="Example" />
+ /// </example>
T Send<T>(IMessage message, int? timeout = null) where T : class, IMessage;
/// <summary>
- /// Sends the specified continuous message.
+ /// Sends the specified continuous request message.
/// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="message">The message.</param>
- /// <param name="callback">Callback for continuous responses.</param>
- /// <param name="timeout">The timeout in seconds.</param>
+ /// <typeparam name="T">Type of expected continuous response message.</typeparam>
+ /// <param name="message">Request message instance.</param>
+ /// <param name="callback">Specify a callback method to handle the incoming response messages.</param>
+ /// <param name="timeout">First and continuous request timeout in seconds. (leave empty to get the default timeout)</param>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to send a continuous request to the machine and get a continuous response using the various different SendContinuous method overrides.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/SendContinuous/Program.cs" title="Send a continuous request" region="Example" />
+ /// </example>
void SendContinuous<T>(IMessage message, Action<T> callback, int? timeout) where T : class, IMessage;
/// <summary>
- /// Sends a continuous message with optional comma separated arguments.
+ /// Sends a continuous request message with optional timeout and comma separated arguments.
/// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="messageName">Name of the message.</param>
- /// <param name="callback">Callback for continuous responses.</param>
- /// <param name="timeout">The timeout in seconds.</param>
- /// <param name="args">The arguments.</param>
- void SendContinuous<T>(String messageName, Action<T> callback, int? timeout, params Object[] args) where T : class, IMessage;
+ /// <remarks>
+ /// This method accepts only stub messages.
+ /// </remarks>
+ /// <typeparam name="T">Type of expected continuous response message.</typeparam>
+ /// <param name="messageName">Full or shortened name of the message (e.g "CalculateRequest" or "calculate").</param>
+ /// <param name="callback">Specify a callback method to handle the incoming response messages.</param>
+ /// <param name="timeout">First and continuous request timeout in seconds. (leave empty to get the default timeout)</param>
+ /// <param name="args">Request arguments separated by commas.</param>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to send a continuous request to the machine and get a continuous response using the various different SendContinuous method overrides.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/SendContinuous/Program.cs" title="Send a continuous request" region="Example" />
+ /// </example>
+ void SendContinuous<T>(String messageName, Action<T> callback, TimeSpan? timeout, params Object[] args) where T : class, IMessage;
/// <summary>
- /// Sends a continuous message with optional comma separated arguments.
+ /// Sends a continuous request message with optional timeout and comma separated arguments.
/// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="messageName">Name of the message.</param>
- /// <param name="callback">Callback for continuous responses.</param>
- /// <param name="args">The arguments.</param>
+ /// <remarks>
+ /// This method accepts only stub messages.
+ /// </remarks>
+ /// <typeparam name="T">Type of expected continuous response message.</typeparam>
+ /// <param name="messageName">Full or shortened name of the message (e.g "CalculateRequest" or "calculate").</param>
+ /// <param name="callback">Specify a callback method to handle the incoming response messages.</param>
+ /// <param name="args">Request arguments separated by commas.</param>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to send a continuous request to the machine and get a continuous response using the various different SendContinuous method overrides.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/SendContinuous/Program.cs" title="Send a continuous request" region="Example" />
+ /// </example>
void SendContinuous<T>(String messageName, Action<T> callback, params Object[] args) where T : class, IMessage;
/// <summary>
@@ -177,6 +313,11 @@ namespace Tango.FSE.Procedures
void WriteLine(Object obj);
/// <summary>
+ /// Writes a carriage return to the output window.
+ /// </summary>
+ void WriteLine();
+
+ /// <summary>
/// Writes the specified object string representation to the output window.
/// </summary>
/// <param name="obj">The object.</param>
@@ -200,21 +341,21 @@ namespace Tango.FSE.Procedures
/// Writes the specified array to the output window using the specified parsing style.
/// </summary>
/// <param name="array">The array.</param>
- /// <param name="style">The style.</param>
+ /// <param name="style">Array parsing style.</param>
void WriteLineArray(IEnumerable array, ArrayParsingStyle style);
/// <summary>
/// Reads the specified file as string.
/// </summary>
/// <param name="path">The file path.</param>
- /// <returns></returns>
+ /// <returns>The file text content.</returns>
String GetFileText(String path);
/// <summary>
- /// Read the specified file bytes
+ /// Read the specified file bytes.
/// </summary>
/// <param name="path">The file path.</param>
- /// <returns></returns>
+ /// <returns>The file byte array.</returns>
byte[] GetFileBytes(String path);
/// <summary>
@@ -223,7 +364,7 @@ namespace Tango.FSE.Procedures
void Clear();
/// <summary>
- /// Writes a string content to the specified file.
+ /// Writes a string to the specified file.
/// If the file already exists it will be overwritten.
/// </summary>
/// <param name="filePath">The file path.</param>
@@ -240,29 +381,29 @@ namespace Tango.FSE.Procedures
/// <summary>
/// Get the value of a user input by key.
/// </summary>
- /// <typeparam name="T"></typeparam>
+ /// <typeparam name="T">Type of expected value.</typeparam>
/// <param name="key">The input key.</param>
- /// <returns></returns>
+ /// <returns>The input value.</returns>
T GetInput<T>(String key);
/// <summary>
/// Gets the value of a user input as an array.
/// User input must be a comma separated string.
/// </summary>
- /// <typeparam name="T"></typeparam>
+ /// <typeparam name="T">Type of expected values.</typeparam>
/// <param name="key">The input key.</param>
- /// <returns></returns>
+ /// <returns>List containing the input array.</returns>
List<T> GetInputArray<T>(String key);
/// <summary>
/// Get the value of a user input by key.
/// </summary>
/// <param name="key">The input key.</param>
- /// <returns></returns>
+ /// <returns>The input value.</returns>
Object GetInput(String key);
/// <summary>
- /// Fails the current procedure with the specified error message.
+ /// Fails the procedure with the specified error message.
/// </summary>
/// <param name="message">The error message.</param>
void Fail(String message);
@@ -300,22 +441,40 @@ namespace Tango.FSE.Procedures
bool ShowWarningQuestion(String message);
/// <summary>
- /// Request a user input for the specified primitive or complex type.
+ /// Request user input for the specified primitive or complex type (model).
/// </summary>
- /// <typeparam name="T"></typeparam>
+ /// <typeparam name="T">Type of input (primitive or complex)</typeparam>
/// <param name="title">The request title.</param>
/// <param name="message">The request message.</param>
- /// <returns></returns>
+ /// <returns>Request result of type T.</returns>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to create a model and request the user to fill or modify that model.
+ /// The model can contain primitives, arrays (comma separated), enums and booleans.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/RequestUserInputFor/Program.cs" title="Request user input" region="Example" />
+ /// </example>
T RequestUserInputFor<T>(String title, String message);
/// <summary>
/// Request a user input for the specified primitive or complex type (model).
/// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="model">The existing model.</param>
+ /// <typeparam name="T">Type of input (primitive or complex)</typeparam>
+ /// <param name="model">Existing model (default values).</param>
/// <param name="title">The request title.</param>
/// <param name="message">The request message.</param>
- /// <returns></returns>
+ /// <returns>Request result of type T.</returns>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to create a model and request the user to fill or modify that model.
+ /// The model can contain primitives, arrays (comma separated), enums and booleans.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/RequestUserInputFor/Program.cs" title="Request user input" region="Example" />
+ /// </example>
T RequestUserInputFor<T>(T model, String title, String message);
/// <summary>
@@ -323,7 +482,7 @@ namespace Tango.FSE.Procedures
/// </summary>
/// <param name="message">The message.</param>
/// <param name="extension">Extension filter (default "*.*").</param>
- /// <returns></returns>
+ /// <returns>The full path to the selected file or null if user canceled.</returns>
String RequestFileOpen(String message, String extension = "*.*");
/// <summary>
@@ -332,142 +491,215 @@ namespace Tango.FSE.Procedures
/// <param name="message">The message.</param>
/// <param name="extension">Extension filter (default "*.*").</param>
/// <param name="defaultFileName">Optional default file name.</param>
- /// <returns></returns>
+ /// <returns>The full path to the selected file or null if user canceled.</returns>
String RequestFileSave(String message, String extension = "*.*", String defaultFileName = null);
/// <summary>
- /// Updates the procedure progress.
+ /// Updates the procedure user progress.
/// </summary>
- /// <param name="message">The message.</param>
- /// <param name="isIndeterminate">Is the progress indeterminate (not need to set value and max).</param>
+ /// <param name="message">The progress message.</param>
+ /// <param name="isIndeterminate">Is the progress indeterminate (no need to set value and max).</param>
/// <param name="value">The progress value.</param>
- /// <param name="maximum">The maximum progress .</param>
+ /// <param name="maximum">The maximum progress.</param>
void UpdateProgress(String message, bool isIndeterminate = true, double value = 0, double maximum = 100);
/// <summary>
- /// Gets the latest diagnostics package.
+ /// Gets the current diagnostics package.
/// </summary>
- /// <param name="waitForNext">Waits for a fresh package.</param>
- /// <returns></returns>
+ /// <param name="waitForNext">Blocks the execution until a fresh diagnostics frame is available.
+ /// This will guarantee that you will get a distinct package each time.
+ /// </param>
+ /// <returns>The diagnostics package.</returns>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to collect 100 middle dancer samples and plot them as a graph result.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/Diagnostics/Program.cs" title="Collect dancer samples" region="Example" />
+ /// </example>
+ /// <seealso cref="AddGraphResult(ResultType, string, IEnumerable{double})"/>
DiagnosticsPackage GetDiagnosticsPackage(bool waitForNext = false);
/// <summary>
- /// Pauses the script execution for the specified time in milliseconds.
+ /// Pauses the procedure execution for the specified time in milliseconds.
/// </summary>
- /// <param name="milliseconds">The milliseconds.</param>
+ /// <param name="milliseconds">Milliseconds.</param>
void Sleep(int milliseconds);
/// <summary>
/// Runs the specified action asynchronously.
/// </summary>
/// <param name="action">The action.</param>
- /// <returns></returns>
+ /// <returns>The thread instance that has been created for the task.</returns>
Thread RunAsync(Action action);
/// <summary>
- /// Loads the specified procedure dialog on the main UI thread.
+ /// Loads the specified procedure dialog on the main UI thread as a standard FSE dialog.
/// </summary>
/// <param name="name">The name of the dialog file.</param>
- /// <returns></returns>
+ /// <returns>The dialog controller.</returns>
IDialogController LoadDialog(String name);
/// <summary>
/// Loads the specified procedure dialog as a window on the current thread.
/// </summary>
- /// <param name="name">The name.</param>
- /// <param name="windowTitle">The window title</param>
- /// <returns></returns>
+ /// <param name="name">The name of the dialog.</param>
+ /// <param name="windowTitle">The window title.</param>
+ /// <returns>The dialog controller.</returns>
IDialogController LoadDialogAsWindow(String name, String windowTitle);
/// <summary>
/// Gets the type of the current machine connection.
+ /// It is recommended to use <see cref="IsConnected"/> before, to ensure active machine connection.
/// </summary>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to check for valid machine connection, check the connection type and get the connected machine's serial number.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/Connection/Program.cs" title="Validate connection" region="Example" />
+ /// </example>
MachineConnectionTypes ConnectionType { get; }
/// <summary>
/// Gets or sets a value indicating whether a machine is currently connected.
/// </summary>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to check for valid machine connection, check the connection type and get the connected machine's serial number.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/Connection/Program.cs" title="Validate connection" region="Example" />
+ /// </example>
bool IsConnected { get; }
/// <summary>
/// Gets the currently connected machine entity.
/// </summary>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to check for valid machine connection, check the connection type and get the connected machine's serial number.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/Connection/Program.cs" title="Validate connection" region="Example" />
+ /// </example>
Machine ConnectedMachine { get; }
/// <summary>
- /// Gets a registered injected service from the Tango FSE application.
+ /// Gets the specified service of type T from the global Tango FSE IOC container..
/// </summary>
/// <typeparam name="T">Type of service</typeparam>
- /// <returns></returns>
+ /// <returns>The service instance.</returns>
T GetService<T>();
/// <summary>
/// Gets the specified resource as byte array.
/// </summary>
/// <param name="resourceName">Name of the resource.</param>
- /// <returns></returns>
+ /// <returns>Resource bytes.</returns>
byte[] GetResourceBytes(String resourceName);
/// <summary>
/// Gets the specified resource as UTF-8 string.
/// </summary>
/// <param name="resourceName">Name of the resource.</param>
- /// <returns></returns>
+ /// <returns>Resource text.</returns>
String GetResourceString(String resourceName);
/// <summary>
- /// Copies the specified resource to a temporary path and opens it using the default application.
+ /// Copies the specified resource to a temporary path and opens it using the default windows application.
/// </summary>
/// <param name="resourceName">Name of the resource.</param>
void OpenResource(String resourceName);
/// <summary>
- /// Gets the specified procedure variable.
+ /// Gets the specified procedure variable value.
/// </summary>
/// <param name="name">The name of the variable.</param>
- /// <returns></returns>
+ /// <returns>The variable value.</returns>
Object GetVariable(String name);
/// <summary>
- /// Gets the specified procedure variable.
+ /// Gets the specified procedure variable value.
/// </summary>
+ /// <typeparam name="T">Type of expected variable value.</typeparam>
/// <param name="name">The name of the variable.</param>
- /// <returns></returns>
+ /// <returns>The variable value of type T.</returns>
T GetVariable<T>(String name);
/// <summary>
/// Gets the specified procedure variable value as an array.
- /// User value must be a comma separated string.
+ /// Value must be a comma separated string.
/// </summary>
/// <param name="name">The name of the variable.</param>
- /// <returns></returns>
+ /// <returns>List containing the variable values.</returns>
List<T> GetVariableArray<T>(String name);
/// <summary>
/// Reads the specified csv file to a list of type T.
/// The given type T model must contain properties not fields.
/// </summary>
- /// <typeparam name="T"></typeparam>
+ /// <typeparam name="T">CSV model type.</typeparam>
/// <param name="file">The file path.</param>
- /// <returns></returns>
+ /// <returns>A list containing all the CSV rows as models of type T.</returns>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates CSV file writing and reading.
+ /// The csv reading method also accepts a byte array so you can also read a CSV file from a procedure resource.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/Csv/Program.cs" title="Read/Write CSV" region="Example" />
+ /// </example>
List<T> ReadCsv<T>(String file) where T : class, new();
/// <summary>
/// Reads the specified csv byte array to a list of type T.
/// The given type T model must contain properties not fields.
/// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="data">The data.</param>
- /// <returns></returns>
+ /// <typeparam name="T">CSV model type.</typeparam>
+ /// <param name="data">The byte array.</param>
+ /// <returns>A list containing all the CSV rows as models of type T.</returns>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates CSV file writing and reading.
+ /// The csv reading method also accepts a byte array so you can also read a CSV file from a procedure resource.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/Csv/Program.cs" title="Read/Write CSV" region="Example" />
+ /// </example>
List<T> ReadCsv<T>(byte[] data) where T : class, new();
/// <summary>
/// Writes a CSV file to the specified file.
/// The given type T model must contain properties not fields.
/// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="file">The file path.</param>
+ /// <typeparam name="T">CSV model type.</typeparam>
+ /// <param name="file">The output file path.</param>
/// <param name="items">The items to write.</param>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates CSV file writing and reading.
+ /// The csv reading method also accepts a byte array so you can also read a CSV file from a procedure resource.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/Csv/Program.cs" title="Read/Write CSV" region="Example" />
+ /// </example>
void WriteCsv<T>(String file, List<T> items);
+
+ /// <summary>
+ /// Request a breakpoint operation from the host IDE (internal use only).
+ /// </summary>
+ /// <param name="file">The file.</param>
+ /// <param name="lineNumber">The line number.</param>
+ /// <param name="symbolsMap">The symbols map.</param>
+ [HideIntellisense]
+ void BreakPoint(String file, int lineNumber, params Object[] symbolsMap);
}
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Navigation/RunProcedureNavigationObject.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Navigation/RunProcedureNavigationObject.cs
new file mode 100644
index 000000000..c19857c21
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Navigation/RunProcedureNavigationObject.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.FSE.Procedures.Navigation
+{
+ public class RunProcedureNavigationObject
+ {
+ public ProcedureProject Project { get; set; }
+ public bool StartProcedure { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ProcedureContext.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ProcedureContext.cs
index ef5664772..8089d5437 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ProcedureContext.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ProcedureContext.cs
@@ -9,6 +9,7 @@ using System.Linq;
using System.Reactive.Concurrency;
using System.Reactive.Linq;
using System.Reflection;
+using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -25,9 +26,11 @@ using Tango.FSE.Common.Diagnostics;
using Tango.FSE.Common.Notifications;
using Tango.FSE.Common.Threading;
using Tango.FSE.Procedures.Dialogs;
+using Tango.FSE.Procedures.Helpers;
using Tango.Integration.Operation;
using Tango.PMR;
using Tango.Scripting.Basic;
+using Tango.Scripting.Core;
namespace Tango.FSE.Procedures
{
@@ -38,6 +41,10 @@ namespace Tango.FSE.Procedures
private Dictionary<String, ProcedureInput> _inputs;
private DiagnosticsFrame _lastDiagnosticsFrame;
+ public event EventHandler<TangoProgressChangedEventArgs<double>> Progress;
+
+ public event EventHandler<BreakPointRequestEventArgs> BreakPointRequest;
+
[TangoInject]
private IMachineProvider MachineProvider { get; set; }
@@ -87,7 +94,7 @@ namespace Tango.FSE.Procedures
var stubType = MessageFactory.GetAvailableRequestStubs().SingleOrDefault(x => x.Name.ToLower() == messageName.ToLower() || x.Name.Replace("Request", "").ToLower() == messageName.ToLower());
if (stubType == null)
{
- throw new ArgumentException("Invalid stub '" + messageName + "'.");
+ throw new ArgumentException($"Stub '{messageName}' could not be located on the PMR.");
}
var stubProps = stubType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
@@ -161,7 +168,7 @@ namespace Tango.FSE.Procedures
return Send(messageName, timeout) as T;
}
- public void SendContinuous<T>(IMessage messageName, Action<T> callback, int? timeout = null) where T : class, IMessage
+ public void SendContinuous<T>(IMessage message, Action<T> callback, int? timeout = null) where T : class, IMessage
{
TaskCompletionSource<object> completion = new TaskCompletionSource<object>();
@@ -172,7 +179,7 @@ namespace Tango.FSE.Procedures
timespan = TimeSpan.FromMilliseconds(timeout.Value);
}
- MachineProvider.MachineOperator.SendContinuousRequest(messageName, new Transport.TransportContinuousRequestConfig()
+ MachineProvider.MachineOperator.SendContinuousRequest(message, new Transport.TransportContinuousRequestConfig()
{
Timeout = timespan,
ContinuousTimeout = timespan
@@ -194,7 +201,7 @@ namespace Tango.FSE.Procedures
completion.Task.GetAwaiter().GetResult();
}
- public void SendContinuous<T>(string messageName, Action<T> callback, int? timeout = null, params object[] args) where T : class, IMessage
+ public void SendContinuous<T>(string messageName, Action<T> callback, TimeSpan? timeout = null, params object[] args) where T : class, IMessage
{
var stubType = MessageFactory.GetAvailableRequestStubs().SingleOrDefault(x => x.Name.ToLower() == messageName.ToLower() || x.Name.Replace("Request", "").ToLower() == messageName.ToLower());
if (stubType == null)
@@ -235,7 +242,7 @@ namespace Tango.FSE.Procedures
}
}
- SendContinuous<IMessage>(request, callback as Action<IMessage>, timeout);
+ SendContinuous<IMessage>(request, callback as Action<IMessage>, timeout != null ? (int?)timeout.Value.TotalSeconds : null);
}
public void SendContinuous<T>(string messageName, Action<T> callback, params object[] args) where T : class, IMessage
@@ -243,6 +250,11 @@ namespace Tango.FSE.Procedures
SendContinuous<T>(messageName, callback, null, args);
}
+ public void WriteLine()
+ {
+ _logger?.WriteLine(String.Empty);
+ }
+
public void WriteLine(object obj)
{
String line = "null";
@@ -298,16 +310,19 @@ namespace Tango.FSE.Procedures
public void WriteToFile(string filePath, string content)
{
+ EnsureFileLocation(filePath);
File.WriteAllText(filePath, content);
}
public void WriteToFile(string filePath, byte[] data)
{
+ EnsureFileLocation(filePath);
File.WriteAllBytes(filePath, data);
}
public void AppendToFile(string filePath, string content)
{
+ EnsureFileLocation(filePath);
File.AppendAllText(filePath, content);
}
@@ -561,8 +576,6 @@ namespace Tango.FSE.Procedures
});
}
- public event EventHandler<TangoProgressChangedEventArgs<double>> Progress;
-
public Result AddBitmapResult(ResultType type, String name, Bitmap bitmap)
{
return AddResult(new Result()
@@ -799,5 +812,52 @@ namespace Tango.FSE.Procedures
csvFile.Dispose();
}
+
+ public void BreakPoint(string file, int lineNumber, params object[] symbolsMap)
+ {
+ if (BreakPointRequest != null && symbolsMap.Length > 0)
+ {
+ bool released = false;
+
+ BreakPointRequestEventArgs args = new BreakPointRequestEventArgs(() =>
+ {
+ released = true;
+ });
+
+ args.LineNumber = lineNumber;
+ args.Script = _project.Scripts.SingleOrDefault(x => x.Name == file);
+
+ for (int i = 0; i < symbolsMap.Length; i += 4)
+ {
+ args.Symbols.Add(new ScriptBreakPointSymbol()
+ {
+ Name = symbolsMap[i].ToString(),
+ Offset = (int)symbolsMap[i + 1],
+ Length = (int)symbolsMap[i + 2],
+ SymbolObject = symbolsMap[i + 3],
+ });
+ }
+
+ DispatcherProvider.Invoke(() =>
+ {
+ BreakPointRequest?.Invoke(this, args);
+ });
+
+ while (!released)
+ {
+ Thread.Sleep(100);
+ }
+ }
+ }
+
+ private void EnsureFileLocation(String file)
+ {
+ String dir = Path.GetDirectoryName(file);
+
+ if (!Directory.Exists(dir))
+ {
+ Directory.CreateDirectory(dir);
+ }
+ }
}
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Resources/main_template.csx b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Resources/main_template.csx
index 8a2516cac..26e4fcb1c 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Resources/main_template.csx
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Resources/main_template.csx
@@ -20,7 +20,6 @@ public class Program
{
public void OnExecute(IProcedureContext context)
{
-
context.AddResult(ResultType.Passed, "My Value Name", "Test for this value has passed.");
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Result.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Result.cs
index 8b7724eca..dc98957d4 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Result.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Result.cs
@@ -9,10 +9,24 @@ using Tango.Core.ExtensionMethods;
namespace Tango.FSE.Procedures
{
+ /// <summary>
+ /// Represents a procedure result.
+ /// </summary>
public class Result
{
+ /// <summary>
+ /// Gets or sets the type.
+ /// </summary>
public ResultType Type { get; set; }
+
+ /// <summary>
+ /// Gets or sets the result name.
+ /// </summary>
public String Name { get; set; }
+
+ /// <summary>
+ /// Gets or sets the result value.
+ /// </summary>
public Object Value { get; set; }
[JsonIgnore]
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ResultType.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ResultType.cs
index 2eea5ec7f..84c912143 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ResultType.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ResultType.cs
@@ -6,10 +6,22 @@ using System.Threading.Tasks;
namespace Tango.FSE.Procedures
{
+ /// <summary>
+ /// Represents a procedure result type.
+ /// </summary>
public enum ResultType
{
+ /// <summary>
+ /// Positive result.
+ /// </summary>
Passed,
+ /// <summary>
+ /// Negative result.
+ /// </summary>
Failed,
+ /// <summary>
+ /// Partial success.
+ /// </summary>
Warning,
}
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/SqlResult.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/SqlResult.cs
deleted file mode 100644
index caf4cae32..000000000
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/SqlResult.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Tango.FSE.Procedures
-{
- public class SqlResult
- {
- public int AffectedRecords { get; set; }
- public List<Dictionary<String, Object>> Rows { get; set; }
-
- public SqlResult()
- {
- Rows = new List<Dictionary<string, object>>();
- }
- }
-}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Tango.FSE.Procedures.csproj b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Tango.FSE.Procedures.csproj
index fcd5c7603..b7e4b238c 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Tango.FSE.Procedures.csproj
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Tango.FSE.Procedures.csproj
@@ -35,6 +35,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>..\..\..\Build\FSE\Release\Tango.FSE.Procedures.xml</DocumentationFile>
+ <NoWarn>1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<Reference Include="ControlzEx, Version=3.0.2.4, Culture=neutral, processorArchitecture=MSIL">
@@ -80,6 +81,7 @@
<Reference Include="System.Reactive.Windows.Threading, Version=3.0.1000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\System.Reactive.Windows.Threading.3.1.1\lib\net45\System.Reactive.Windows.Threading.dll</HintPath>
</Reference>
+ <Reference Include="System.Web.Extensions" />
<Reference Include="System.Windows" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
@@ -100,12 +102,18 @@
</ItemGroup>
<ItemGroup>
<Compile Include="ArrayParsingStyle.cs" />
+ <Compile Include="BreakPointRequestEventArgs.cs" />
<Compile Include="Contracts\IProcedureDesignerView.cs" />
+ <Compile Include="Controls\ObjectInTreeView.xaml.cs">
+ <DependentUpon>ObjectInTreeView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Controls\TreeNode.cs" />
<Compile Include="Converters\BitmapToBitmapSourceConverter.cs" />
<Compile Include="CreateGroup.cs" />
<Compile Include="CreateItem.cs" />
<Compile Include="CSV\CsvColumn.cs" />
<Compile Include="CSV\CsvRow.cs" />
+ <Compile Include="DebugNode.cs" />
<Compile Include="Designer\ProjectModel.cs" />
<Compile Include="Designer\ScriptTabModel.cs" />
<Compile Include="DialogController.cs" />
@@ -114,6 +122,10 @@
<DependentUpon>AddReferenceAssemblyView.xaml</DependentUpon>
</Compile>
<Compile Include="Dialogs\AddReferenceAssemblyViewVM.cs" />
+ <Compile Include="Dialogs\BreakPointValueDialogView.xaml.cs">
+ <DependentUpon>BreakPointValueDialogView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Dialogs\BreakPointValueDialogViewVM.cs" />
<Compile Include="Dialogs\InputSelectionConfigurationDialogView.xaml.cs">
<DependentUpon>InputSelectionConfigurationDialogView.xaml</DependentUpon>
</Compile>
@@ -142,10 +154,21 @@
<DependentUpon>UserInputDialogView.xaml</DependentUpon>
</Compile>
<Compile Include="Dialogs\UserInputDialogViewVM.cs" />
+ <Compile Include="Examples\AddResult\Program.cs" />
+ <Compile Include="Examples\Connection\Program.cs" />
+ <Compile Include="Examples\Csv\Program.cs" />
+ <Compile Include="Examples\Diagnostics\Program.cs" />
+ <Compile Include="Examples\RequestUserInputFor\Program.cs" />
+ <Compile Include="Examples\SendContinuous\Program.cs" />
+ <Compile Include="Examples\Send\Program.cs" />
+ <Compile Include="Examples\Sql\Program.cs" />
+ <Compile Include="ExtensionMethods\TreeViewExtensions.cs" />
+ <Compile Include="Helpers\ProcedureExceptionHelper.cs" />
<Compile Include="IDialogController.cs" />
<Compile Include="IProcedureContext.cs" />
<Compile Include="IProcedureLogger.cs" />
<Compile Include="Messages\ProcedureProjectPublishedOrSuppressed.cs" />
+ <Compile Include="Navigation\RunProcedureNavigationObject.cs" />
<Compile Include="ProcedureDialog.cs" />
<Compile Include="ProcedureInputSelection.cs" />
<Compile Include="ProcedureInputType.cs" />
@@ -160,7 +183,6 @@
<Compile Include="ProcedureFailedException.cs" />
<Compile Include="ProcedureInput.cs" />
<Compile Include="ProcedureProject.cs" />
- <Compile Include="SqlResult.cs" />
<Compile Include="UserInput.cs" />
<Compile Include="ViewModelLocator.cs" />
<Compile Include="ProceduresModule.cs" />
@@ -222,6 +244,10 @@
<EmbeddedResource Include="Resources\procedure_dialog_template.zip" />
</ItemGroup>
<ItemGroup>
+ <ProjectReference Include="..\..\..\PPC\Tango.PPC.Shared\Tango.PPC.Shared.csproj">
+ <Project>{208c8bd8-72c6-4e3c-acaa-351091a2acc7}</Project>
+ <Name>Tango.PPC.Shared</Name>
+ </ProjectReference>
<ProjectReference Include="..\..\..\Scripting\Tango.Scripting.Basic\Tango.Scripting.Basic.csproj">
<Project>{2b29a699-1d65-463a-8250-a2ce81d019c9}</Project>
<Name>Tango.Scripting.Basic</Name>
@@ -300,10 +326,18 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
+ <Page Include="Controls\ObjectInTreeView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
<Page Include="Dialogs\AddReferenceAssemblyView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
+ <Page Include="Dialogs\BreakPointValueDialogView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
<Page Include="Dialogs\InputSelectionConfigurationDialogView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -386,6 +420,7 @@
<ItemGroup>
<Resource Include="Images\blend.png" />
</ItemGroup>
+ <ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\..\packages\MaterialDesignThemes.3.0.1\build\MaterialDesignThemes.targets" Condition="Exists('..\..\..\packages\MaterialDesignThemes.3.0.1\build\MaterialDesignThemes.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Themes/Generic.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Themes/Generic.xaml
index 06e60997d..3917368f2 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Themes/Generic.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Themes/Generic.xaml
@@ -2,6 +2,10 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:realTimeGraphX="clr-namespace:RealTimeGraphX.WPF;assembly=RealTimeGraphX.WPF"
xmlns:commonGraph="clr-namespace:Tango.FSE.Common.Graphs;assembly=Tango.FSE.Common"
+ xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
+ xmlns:material="http://materialdesigninxaml.net/winfx/xaml/themes"
+ xmlns:controls="clr-namespace:Tango.FSE.Common.Controls;assembly=Tango.FSE.Common"
+ xmlns:views="clr-namespace:Tango.FSE.Procedures.Views"
xmlns:local="clr-namespace:Tango.FSE.Procedures.Themes">
<Style x:Key="FocusVisual">
@@ -467,4 +471,221 @@
</Style.Triggers>
</Style>
+ <Style x:Key="FSE_Debug_TreeViewItemFocusVisualStyle">
+ <Setter Property="Control.Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <Rectangle/>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <PathGeometry x:Key="TreeArrow" Figures="M0,0 L0,6 L6,0 z"/>
+
+ <Style x:Key="FSE_Debug_ExpandCollapseToggleStyle" TargetType="{x:Type ToggleButton}">
+ <Setter Property="Focusable" Value="False"/>
+ <Setter Property="Width" Value="20"/>
+ <Setter Property="Height" Value="20"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type ToggleButton}">
+ <Border Background="Transparent" Height="20" Padding="5,5,5,5" Width="20">
+ <Path x:Name="ExpandPath" Data="{StaticResource TreeArrow}" Fill="Transparent" Stroke="{StaticResource FSE_PrimaryForegroundBrush}">
+ <Path.RenderTransform>
+ <RotateTransform Angle="135" CenterY="3" CenterX="3"/>
+ </Path.RenderTransform>
+ </Path>
+ </Border>
+ <ControlTemplate.Triggers>
+ <Trigger Property="IsChecked" Value="True">
+ <Setter Property="RenderTransform" TargetName="ExpandPath">
+ <Setter.Value>
+ <RotateTransform Angle="180" CenterY="3" CenterX="3"/>
+ </Setter.Value>
+ </Setter>
+ <Setter Property="Fill" TargetName="ExpandPath" Value="{StaticResource FSE_PrimaryForegroundBrush}"/>
+ <Setter Property="Stroke" TargetName="ExpandPath" Value="{StaticResource FSE_PrimaryForegroundBrush}"/>
+ </Trigger>
+ <Trigger Property="IsMouseOver" Value="True">
+ <Setter Property="Stroke" TargetName="ExpandPath" Value="{StaticResource FSE_PrimaryAccentBrush}"/>
+ <Setter Property="Fill" TargetName="ExpandPath" Value="Transparent"/>
+ </Trigger>
+ <MultiTrigger>
+ <MultiTrigger.Conditions>
+ <Condition Property="IsMouseOver" Value="True"/>
+ <Condition Property="IsChecked" Value="True"/>
+ </MultiTrigger.Conditions>
+ <Setter Property="Stroke" TargetName="ExpandPath" Value="{StaticResource FSE_PrimaryAccentBrush}"/>
+ <Setter Property="Fill" TargetName="ExpandPath" Value="{StaticResource FSE_PrimaryAccentBrush}"/>
+ </MultiTrigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style x:Key="FSE_Debug_TreeViewItemStyle" TargetType="{x:Type TreeViewItem}">
+ <Setter Property="Background" Value="Transparent"/>
+ <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
+ <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
+ <Setter Property="Foreground" Value="{StaticResource FSE_PrimaryForegroundBrush}"/>
+ <Setter Property="FocusVisualStyle" Value="{StaticResource FSE_Debug_TreeViewItemFocusVisualStyle}"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type TreeViewItem}">
+ <Grid>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition MinWidth="19" Width="Auto"/>
+ <ColumnDefinition Width="Auto"/>
+ <ColumnDefinition Width="*"/>
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition/>
+ </Grid.RowDefinitions>
+ <ToggleButton x:Name="Expander" ClickMode="Press" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource FSE_Debug_ExpandCollapseToggleStyle}"/>
+ <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="1" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
+ <ContentPresenter x:Name="PART_Header" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
+ </Border>
+ <ItemsPresenter x:Name="ItemsHost" Grid.ColumnSpan="2" Grid.Column="1" Grid.Row="1"/>
+ </Grid>
+ <ControlTemplate.Triggers>
+ <Trigger Property="IsExpanded" Value="false">
+ <Setter Property="Visibility" TargetName="ItemsHost" Value="Collapsed"/>
+ </Trigger>
+ <Trigger Property="HasItems" Value="false">
+ <Setter Property="Visibility" TargetName="Expander" Value="Hidden"/>
+ </Trigger>
+ <Trigger Property="IsSelected" Value="true">
+
+ </Trigger>
+ <MultiTrigger>
+ <MultiTrigger.Conditions>
+ <Condition Property="IsSelected" Value="true"/>
+ <Condition Property="IsSelectionActive" Value="false"/>
+ </MultiTrigger.Conditions>
+
+ </MultiTrigger>
+ <Trigger Property="IsEnabled" Value="false">
+ <Setter Property="Foreground" Value="{StaticResource FSE_GrayBrush}"/>
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ <Style.Triggers>
+ <Trigger Property="VirtualizingPanel.IsVirtualizing" Value="true">
+ <Setter Property="ItemsPanel">
+ <Setter.Value>
+ <ItemsPanelTemplate>
+ <VirtualizingStackPanel/>
+ </ItemsPanelTemplate>
+ </Setter.Value>
+ </Setter>
+ </Trigger>
+ </Style.Triggers>
+ </Style>
+
+ <Style x:Key="FSE_Debug_TreeViewStyle" TargetType="{x:Type TreeView}">
+ <Style.Resources>
+ <Style TargetType="TreeViewItem" BasedOn="{StaticResource FSE_Debug_TreeViewItemStyle}">
+
+ </Style>
+ </Style.Resources>
+ <Setter Property="Background" Value="Transparent"/>
+ <Setter Property="BorderBrush" Value="Transparent"/>
+ <Setter Property="BorderThickness" Value="0"/>
+ <Setter Property="Padding" Value="0"/>
+ <Setter Property="Foreground" Value="{StaticResource FSE_PrimaryForegroundBrush}"/>
+ <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
+ <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
+ <Setter Property="ScrollViewer.PanningMode" Value="Both"/>
+ <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
+ <Setter Property="VerticalContentAlignment" Value="Center"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type TreeView}">
+ <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="true">
+ <ScrollViewer x:Name="_tv_scrollviewer_" Background="{TemplateBinding Background}" CanContentScroll="false" Focusable="false" HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}">
+ <ItemsPresenter/>
+ </ScrollViewer>
+ </Border>
+ <ControlTemplate.Triggers>
+ <Trigger Property="IsEnabled" Value="false">
+ <Setter Property="Background" TargetName="Bd" Value="Transparent"/>
+ </Trigger>
+ <Trigger Property="VirtualizingPanel.IsVirtualizing" Value="true">
+ <Setter Property="CanContentScroll" TargetName="_tv_scrollviewer_" Value="true"/>
+ </Trigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ <Style.Triggers>
+ <Trigger Property="VirtualizingPanel.IsVirtualizing" Value="true">
+ <Setter Property="ItemsPanel">
+ <Setter.Value>
+ <ItemsPanelTemplate>
+ <VirtualizingStackPanel/>
+ </ItemsPanelTemplate>
+ </Setter.Value>
+ </Setter>
+ </Trigger>
+ </Style.Triggers>
+ </Style>
+
+
+ <Style x:Key="FSE_Debug_TextBoxStyle" TargetType="TextBox">
+ <Setter Property="Background" Value="Transparent"></Setter>
+ <Setter Property="BorderBrush" Value="{StaticResource FSE_BorderBrush}"></Setter>
+ <Setter Property="BorderThickness" Value="0"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource FSE_PrimaryForegroundBrush}"></Setter>
+ <Setter Property="CaretBrush" Value="{StaticResource FSE_PrimaryForegroundBrush}"></Setter>
+ </Style>
+
+ <DataTemplate x:Key="TreeViewDataTemplate">
+ <DockPanel>
+ <material:PackIcon Kind="Cube" VerticalAlignment="Center" Width="12" Height="12" Foreground="{StaticResource FSE_PrimaryForegroundBrush}" />
+ <DockPanel Margin="2 0 0 0">
+ <Border BorderThickness="0.5" BorderBrush="{StaticResource FSE_BorderBrush}" Padding="2">
+ <TextBlock Margin="0 0 0 0" Width="100" Text="{Binding Name}" ToolTip="{Binding Name}" TextWrapping="NoWrap" TextTrimming="CharacterEllipsis"></TextBlock>
+ </Border>
+ <DockPanel>
+ <TextBlock DockPanel.Dock="Right" Margin="10 -1 10 0" Foreground="{StaticResource FSE_GrayBrush}" VerticalAlignment="Center">
+ <Run>[</Run>
+ <Run Text="{Binding Type}"></Run>
+ <Run>]</Run>
+ </TextBlock>
+ <Border Height="20" Margin="0 0 0 0" BorderThickness="0.5" BorderBrush="{StaticResource FSE_BorderBrush}" Padding="2">
+ <DockPanel>
+ <controls:IconButton Icon="Search" Padding="0" ToolTip="Display full value" Width="20" Height="20" VerticalAlignment="Center" Style="{StaticResource FSE_IconButton_Flat_Pressed_Highlight}" Cursor="Hand" Command="{Binding RelativeSource={RelativeSource AncestorType=views:ProcedureDesignerView},Path=DataContext.DisplayDebugNodeValueCommand}" CommandParameter="{Binding}" />
+ <TextBox ToolTip="{Binding DisplayValue}" IsEnabled="{Binding IsEditable}" TextWrapping="NoWrap" MinWidth="100" MaxWidth="100" Margin="2 0 0 0" Text="{Binding DisplayValue,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
+ <TextBox.Style>
+ <Style TargetType="TextBox" BasedOn="{StaticResource FSE_Debug_TextBoxStyle}">
+ <Setter Property="FontWeight" Value="Normal"></Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding IsEdited}" Value="True">
+ <Setter Property="FontWeight" Value="SemiBold"></Setter>
+ <Setter Property="Foreground" Value="Red"></Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </TextBox.Style>
+ <i:Interaction.Triggers>
+ <i:EventTrigger EventName="LostFocus">
+ <i:InvokeCommandAction Command="{Binding UpdateValueCommand}" />
+ </i:EventTrigger>
+ </i:Interaction.Triggers>
+ <TextBox.InputBindings>
+ <KeyBinding Key="Return" Command="{Binding UpdateValueCommand}" />
+ </TextBox.InputBindings>
+ </TextBox>
+ </DockPanel>
+ </Border>
+ </DockPanel>
+ </DockPanel>
+ </DockPanel>
+ </DataTemplate>
+
</ResourceDictionary> \ No newline at end of file
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/UserInput.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/UserInput.cs
index f5d3472d8..043b5bbae 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/UserInput.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/UserInput.cs
@@ -6,10 +6,21 @@ using System.Threading.Tasks;
namespace Tango.FSE.Procedures
{
+ /// <summary>
+ /// Can be used to decorate a property or field in order to set their custom name when using <see cref="IProcedureContext.RequestUserInputFor{T}(string, string)"/>
+ /// </summary>
+ /// <seealso cref="System.Attribute" />
public class UserInput : Attribute
{
+ /// <summary>
+ /// Gets or sets the field/property custom name.
+ /// </summary>
public String Name { get; set; }
+ /// <summary>
+ /// Initializes a new instance of the <see cref="UserInput"/> class.
+ /// </summary>
+ /// <param name="name">The field name.</param>
public UserInput(String name)
{
Name = name;
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ViewModels/ProcedureDesignerViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ViewModels/ProcedureDesignerViewVM.cs
index 68c8538b8..e9c476a20 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ViewModels/ProcedureDesignerViewVM.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ViewModels/ProcedureDesignerViewVM.cs
@@ -8,6 +8,7 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
+using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
@@ -20,11 +21,14 @@ using Tango.Core.Commands;
using Tango.Core.ExtensionMethods;
using Tango.Core.Helpers;
using Tango.FSE.Common;
+using Tango.FSE.Common.FileAssociation;
using Tango.FSE.Common.Navigation;
using Tango.FSE.Common.Notifications;
using Tango.FSE.Procedures.Contracts;
using Tango.FSE.Procedures.Dialogs;
using Tango.FSE.Procedures.Messages;
+using Tango.FSE.Procedures.Navigation;
+using Tango.FSE.Procedures.Views;
using Tango.Integration.Operation;
using Tango.Scripting.Basic;
using Tango.Scripting.Editors;
@@ -58,6 +62,8 @@ namespace Tango.FSE.Procedures.ViewModels
private String PROJECT_DIALOG_FILTER = $"Procedure Project Files|*.pproj";
private bool _isProjectChanged;
private TaskItem _symbolsTaskItem;
+ private BreakPointRequestEventArgs _lastBreakPointRequestArgs;
+ private String _lastProjectStringForCompilation;
#region Properties
@@ -200,6 +206,34 @@ namespace Tango.FSE.Procedures.ViewModels
}
}
+ private Exception _runtimeException;
+ public Exception RuntimeException
+ {
+ get { return _runtimeException; }
+ set { _runtimeException = value; RaisePropertyChangedAuto(); }
+ }
+
+ private bool _runtimeErrorFree;
+ public bool RuntimeErrorFree
+ {
+ get { return _runtimeErrorFree; }
+ set { _runtimeErrorFree = value; RaisePropertyChangedAuto(); }
+ }
+
+ private bool _isBreakPoint;
+ public bool IsBreakPoint
+ {
+ get { return _isBreakPoint; }
+ set { _isBreakPoint = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); }
+ }
+
+ private bool _isReadOnly;
+ public bool IsReadOnly
+ {
+ get { return _isReadOnly; }
+ set { _isReadOnly = value; RaisePropertyChangedAuto(); }
+ }
+
#endregion
#region Commands
@@ -244,6 +278,11 @@ namespace Tango.FSE.Procedures.ViewModels
public RelayCommand<ProcedureResource> RemoveResourceCommand { get; set; }
public RelayCommand<ProcedureResource> OpenResourceCommand { get; set; }
public RelayCommand<ProcedureResource> ExportResourceCommand { get; set; }
+ public RelayCommand CloseRuntimeErrorCommand { get; set; }
+ public RelayCommand ContinueProjectCommand { get; set; }
+ public RelayCommand OpenHelpCommand { get; set; }
+ public RelayCommand<DebugNode> DisplayDebugNodeValueCommand { get; set; }
+ public RelayCommand RunOnProceduresModuleCommand { get; set; }
#endregion
@@ -256,6 +295,7 @@ namespace Tango.FSE.Procedures.ViewModels
FontSize = 13;
ReplaceText = String.Empty;
+ RuntimeErrorFree = true;
LoadedAssemblies = new ObservableCollection<Assembly>();
ResultsViewVM = new ResultsViewVM();
@@ -271,7 +311,8 @@ namespace Tango.FSE.Procedures.ViewModels
OpenScripts = new ObservableCollection<Script>();
OpenScriptCommand = new RelayCommand<Script>(OpenScript);
CloseScriptCommand = new RelayCommand<Script>(CloseScript);
- RunProjectCommand = new RelayCommand(RunProject, () => ProjectRunner != null && ProjectRunner.CanRun);
+ RunProjectCommand = new RelayCommand(RunProject, () => ProjectRunner != null && (ProjectRunner.CanRun || IsBreakPoint));
+ RunOnProceduresModuleCommand = new RelayCommand(RunOnProceduresModule, () => ProjectRunner != null && (ProjectRunner.CanRun || IsBreakPoint));
StopProjectCommand = new RelayCommand(StopProject, () => ProjectRunner != null && ProjectRunner.IsRunning);
CompileProjectCommand = new RelayCommand(async () => await CompileProject(), () => ProjectRunner != null && ProjectRunner.CanCompile);
AddReferenceAssemblyCommand = new RelayCommand(AddReferenceAssembly);
@@ -309,6 +350,10 @@ namespace Tango.FSE.Procedures.ViewModels
RemoveResourceCommand = new RelayCommand<ProcedureResource>(RemoveProcedureResource);
OpenResourceCommand = new RelayCommand<ProcedureResource>(OpenProcedureResource);
ExportResourceCommand = new RelayCommand<ProcedureResource>(ExportProcedureResource);
+ CloseRuntimeErrorCommand = new RelayCommand(CloseRunTimeError);
+ ContinueProjectCommand = new RelayCommand(ContinueProject);
+ OpenHelpCommand = new RelayCommand(OpenHelpFile);
+ DisplayDebugNodeValueCommand = new RelayCommand<DebugNode>(DisplayDebugNodeValue);
}
#endregion
@@ -410,6 +455,8 @@ namespace Tango.FSE.Procedures.ViewModels
LogManager.Log(ex, "Error generating procedure designer auto creation groups.");
}
});
+
+ FileAssociationProvider.RegisterFileAssociationHandler("designer", HandlerProcedureFileAssociation);
}
public override void OnNavigatedTo()
@@ -464,6 +511,8 @@ namespace Tango.FSE.Procedures.ViewModels
private void StopProject()
{
ProjectRunner.Stop();
+ ContinueProject();
+ IsReadOnly = false;
}
private async Task<bool> CompileProject()
@@ -523,15 +572,35 @@ namespace Tango.FSE.Procedures.ViewModels
private async void RunProject()
{
+ if (IsBreakPoint)
+ {
+ ContinueProject();
+ return;
+ }
+
try
{
if (await CompileProject())
{
+ IsReadOnly = true;
SelectedToolWindow = ToolWindows.Output;
ResultsViewVM.Results = new List<Result>();
Logger.Clear();
Logger.WriteLine("Running project...");
+
var context = new ProcedureContext(Project, this);
+
+ context.BreakPointRequest += Context_BreakPointRequest;
+
+ try
+ {
+ Project.BreakPoints = View.GetBreakPoints();
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error initializing break points for project.");
+ }
+
await ProjectRunner.Run(context);
ResultsViewVM.Results = context.Results.ToList();
@@ -546,17 +615,55 @@ namespace Tango.FSE.Procedures.ViewModels
{
Logger.WriteLine("Project ran to completion with zero results.");
}
+
+ IsReadOnly = false;
}
}
catch (OperationCanceledException)
{
+ IsReadOnly = false;
Logger.WriteLine("Project terminated by user.");
}
catch (Exception ex)
{
+ IsReadOnly = false;
SelectedToolWindow = ToolWindows.Output;
Logger.WriteLine("Project terminated with error:");
Logger.WriteLine(ex.FlattenMessage());
+
+ try
+ {
+ int? lineNumber = Helpers.ProcedureExceptionHelper.GetExceptionLineNumber(ex, Project);
+
+ if (lineNumber != null)
+ {
+ OpenScript(Project.Scripts.FirstOrDefault(x => x.IsEntryPoint));
+ RuntimeException = ex;
+ View.HighlightRuntimeError(lineNumber.Value);
+ RuntimeErrorFree = false;
+ IsReadOnly = true;
+ }
+ }
+ catch (Exception exx)
+ {
+ LogManager.Log(exx, "Error occurred while trying to show procedure runtime error.");
+ }
+ }
+ finally
+ {
+ Project.BreakPoints.Clear();
+ }
+ }
+
+ private async void RunOnProceduresModule()
+ {
+ if (await CompileProject())
+ {
+ await NavigationManager.NavigateWithObject<ProceduresModule, ProcedureRunnerView, RunProcedureNavigationObject>(new RunProcedureNavigationObject()
+ {
+ Project = Project,
+ StartProcedure = true
+ });
}
}
@@ -602,27 +709,39 @@ namespace Tango.FSE.Procedures.ViewModels
_compileTimer.Stop();
- if (Project != null)
+ if (Project != null && !Project.IsCompiling && !Project.IsRunning)
{
- CompilationErrors = (await Project.Compile()).Errors;
+ String projectString = String.Empty;
- if (CompilationErrors.Count > 0 && (SelectedToolWindow == ToolWindows.Output || SelectedToolWindow == ToolWindows.Results))
- {
- SelectedToolWindow = ToolWindows.Errors;
- }
+ projectString = String.Join(Environment.NewLine, Project.Scripts.ToList().Select(x => x.Code));
+ projectString += String.Join(Environment.NewLine, Project.ReferenceAssemblies.ToList().Select(x => x.Name));
- InvokeUI(() =>
+ if (_lastProjectStringForCompilation != projectString)
{
- View.ClearErrors();
+ _lastProjectStringForCompilation = projectString;
- foreach (var error in CompilationErrors)
+ CompilationErrors = (await Project.Compile()).Errors;
+
+ if (CompilationErrors.Count > 0 && (SelectedToolWindow == ToolWindows.Output || SelectedToolWindow == ToolWindows.Results))
{
- if (error.File == SelectedScript.Name)
+ SelectedToolWindow = ToolWindows.Errors;
+ }
+
+ InvokeUI(() =>
+ {
+ View.ClearErrors();
+
+ foreach (var error in CompilationErrors)
{
- View.HighlightError(error.Position, error.Length);
+ if (error.File == SelectedScript.Name)
+ {
+ View.HighlightError(error.Position, error.Length);
+ }
}
- }
- });
+ });
+ }
+
+ _lastProjectStringForCompilation = projectString;
}
_compileTimer.Start();
@@ -792,6 +911,12 @@ namespace Tango.FSE.Procedures.ViewModels
private void OpenProject(String file)
{
+ if (Project != null && Project.IsRunning)
+ {
+ NotificationProvider.ShowError("Cannot load a project while another project is running.");
+ return;
+ }
+
try
{
Project = ProcedureProject.FromJson(File.ReadAllText(file));
@@ -1288,5 +1413,146 @@ namespace Tango.FSE.Procedures.ViewModels
}
#endregion
+
+ #region Runtime Error
+
+ private void CloseRunTimeError()
+ {
+ View.CloseRunTimeError();
+ RuntimeErrorFree = true;
+ IsReadOnly = false;
+ }
+
+ #endregion
+
+ #region BreakPoint Request
+
+ private void Context_BreakPointRequest(object sender, BreakPointRequestEventArgs e)
+ {
+ try
+ {
+ _lastBreakPointRequestArgs = e;
+ OpenScript(e.Script);
+ View.HighlightBreakPointRequest(e.LineNumber, e.Symbols);
+ IsBreakPoint = true;
+ }
+ catch (Exception ex)
+ {
+ e.Release();
+ LogManager.Log(ex, "Error initializing runtime debug request.");
+ }
+ }
+
+ private void ContinueProject()
+ {
+ if (_lastBreakPointRequestArgs != null)
+ {
+ View.ResetBreakPointRequest();
+ IsBreakPoint = false;
+ _lastBreakPointRequestArgs.Release();
+ _lastBreakPointRequestArgs = null;
+ }
+ }
+
+ private async void DisplayDebugNodeValue(DebugNode debugNode)
+ {
+ if (debugNode != null)
+ {
+ await NotificationProvider.ShowDialog(new BreakPointValueDialogViewVM(debugNode.Name, debugNode.Value));
+ }
+ }
+
+ #endregion
+
+ #region Help
+
+ private void OpenHelpFile()
+ {
+ String word = View.GetCaretWord();
+
+ if (word != null)
+ {
+ String memberSign = null;
+ String typeFullName = null;
+
+ if (typeof(IProcedureContext).GetProperties(BindingFlags.Instance | BindingFlags.Public).Any(x => x.Name == word))
+ {
+ memberSign = "P";
+ }
+
+ if (memberSign == null)
+ {
+ if (typeof(IProcedureContext).GetMethods(BindingFlags.Instance | BindingFlags.Public).Any(x => x.Name == word))
+ {
+ memberSign = "M";
+ }
+ }
+
+ if (memberSign == null)
+ {
+ var type = typeof(IProcedureContext).Assembly.GetTypes().FirstOrDefault(x => x.Name == word);
+ if (type != null)
+ {
+ memberSign = "T";
+ typeFullName = type.FullName.Replace(".", "_");
+ }
+ }
+
+ if (memberSign != null)
+ {
+ String url = String.Empty;
+
+ if (memberSign == "T")
+ {
+ url = $"{typeFullName}.htm";
+ }
+ else
+ {
+ url = $"Tango_FSE_Procedures_IProcedureContext_{word}.htm";
+ }
+
+ Process pp = new Process();
+ pp.StartInfo.FileName = "hh.exe";
+ pp.StartInfo.Arguments = $"ms-its:{Path.Combine(AssemblyHelper.GetCurrentAssemblyFolder(), "proc-doc.chm")}::/html/{memberSign}_{url}";
+ pp.StartInfo.WindowStyle = ProcessWindowStyle.Maximized;
+ pp.Start();
+ return;
+ }
+ }
+
+ Process p = new Process();
+ p.StartInfo.FileName = Path.Combine(AssemblyHelper.GetCurrentAssemblyFolder(), "proc-doc.chm");
+ p.StartInfo.WindowStyle = ProcessWindowStyle.Maximized;
+ p.Start();
+ }
+
+ #endregion
+
+ #region File Association
+
+ private void HandlerProcedureFileAssociation(FileAssociationPackage package)
+ {
+ if (!CurrentUser.HasPermission(Permissions.FSE_RunProcedureDesigner))
+ {
+ NotificationProvider.ShowError("Current user profile does not allow running the procedure designer.");
+ return;
+ }
+
+ if (File.Exists(package.File))
+ {
+ try
+ {
+ LogManager.Log("Opening procedure project from file association...");
+ NavigationManager.NavigateTo<ProceduresModule>(true, nameof(ProcedureDesignerView));
+ OpenProject(package.File);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error occurred while trying to handle the procedure file association.");
+ }
+ }
+ }
+
+ #endregion
}
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ViewModels/ProcedureRunnerViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ViewModels/ProcedureRunnerViewVM.cs
index da5ecf324..6ccc77669 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ViewModels/ProcedureRunnerViewVM.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/ViewModels/ProcedureRunnerViewVM.cs
@@ -1,24 +1,21 @@
using System;
-using System.Collections;
using System.Collections.Generic;
-using System.ComponentModel;
+using System.IO;
using System.Linq;
-using System.Reflection;
-using System.Text;
using System.Threading.Tasks;
using Tango.BL.Entities;
using Tango.Core;
using Tango.Core.Commands;
-using Tango.CSV;
using Tango.FSE.Common;
-using Tango.FSE.Procedures.CSV;
-using Tango.FSE.Procedures.Dialogs;
+using Tango.FSE.Common.FileAssociation;
+using Tango.FSE.Common.Navigation;
using Tango.FSE.Procedures.Messages;
+using Tango.FSE.Procedures.Navigation;
using Tango.FSE.Procedures.Views;
namespace Tango.FSE.Procedures.ViewModels
{
- public class ProcedureRunnerViewVM : FSEViewModel, IProcedureLogger
+ public class ProcedureRunnerViewVM : FSEViewModel, IProcedureLogger, INavigationObjectReceiver<RunProcedureNavigationObject>
{
public enum RunnerView
{
@@ -27,6 +24,8 @@ namespace Tango.FSE.Procedures.ViewModels
}
private bool _requiresReloadingOfProjects;
+ private bool _isFromNavigation;
+ private RunProcedureNavigationObject _navigationObject;
private RunnerView _selectedView;
public RunnerView SelectedView
@@ -117,10 +116,23 @@ namespace Tango.FSE.Procedures.ViewModels
RegisterForMessage<ProcedureProjectPublishedOrSuppressed>((x) => _requiresReloadingOfProjects = true);
}
+ public override void OnApplicationStarted()
+ {
+ base.OnApplicationStarted();
+
+ FileAssociationProvider.RegisterFileAssociationHandler("procedure", HandlerProcedureFileAssociation);
+ }
+
private async void StartProject()
{
try
{
+ if (IsRunning)
+ {
+ await NotificationProvider.ShowError("Cannot execute a procedure while another procedure is running.");
+ return;
+ }
+
IsRunning = true;
FailedError = null;
ResultsViewVM.Results = new List<Result>();
@@ -181,6 +193,29 @@ namespace Tango.FSE.Procedures.ViewModels
{
LoadPublishedProcedureProjects();
}
+
+ if (_isFromNavigation)
+ {
+ if (!IsRunning)
+ {
+ RunningProcedureProject = _navigationObject.Project;
+ RaisePropertyChanged(nameof(HasProcedureInputs));
+ ProjectRunner = new ProjectRunner(RunningProcedureProject);
+ ProjectRunner.StateChanged += (x, e) => InvalidateRelayCommands();
+ Status = "Ready";
+ InvalidateRelayCommands();
+ SelectedView = RunnerView.ProcedureRunnerExecutionView;
+
+ if (_navigationObject.StartProcedure)
+ {
+ StartProject();
+ }
+ }
+ else
+ {
+ NotificationProvider.ShowError("Cannot execute a procedure while another procedure is running.");
+ }
+ }
}
private async void LoadPublishedProcedureProjects()
@@ -222,9 +257,18 @@ namespace Tango.FSE.Procedures.ViewModels
if (SelectedView == RunnerView.ProcedureRunnerExecutionView && !IsRunning)
{
SelectedView = RunnerView.ProcedureRunnerCatalogView;
+
+ if (_isFromNavigation)
+ {
+ _isFromNavigation = false;
+ return Task.FromResult(true);
+ }
+
return Task.FromResult(false);
}
+ _isFromNavigation = false;
+
return base.OnNavigateBackRequest();
}
@@ -242,5 +286,31 @@ namespace Tango.FSE.Procedures.ViewModels
{
//Do nothing
}
+
+ public void OnNavigatedToWithObject(RunProcedureNavigationObject obj)
+ {
+ _isFromNavigation = true;
+ _navigationObject = obj;
+ }
+
+ private async void HandlerProcedureFileAssociation(FileAssociationPackage package)
+ {
+ if (File.Exists(package.File))
+ {
+ try
+ {
+ ProcedureProject project = ProcedureProject.FromJson(File.ReadAllText(package.File));
+ LogManager.Log("Loading procedure from file association...");
+ await NavigationManager.NavigateWithObject<ProceduresModule, ProcedureRunnerView, RunProcedureNavigationObject>(new RunProcedureNavigationObject()
+ {
+ Project = project
+ });
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error occurred while trying to handler the procedure file association.");
+ }
+ }
+ }
}
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Views/ProcedureDesignerView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Views/ProcedureDesignerView.xaml
index 82f799d7b..a271e9d07 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Views/ProcedureDesignerView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Views/ProcedureDesignerView.xaml
@@ -8,6 +8,7 @@
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:components="clr-namespace:Tango.SharedUI.Components;assembly=Tango.SharedUI"
xmlns:vm="clr-namespace:Tango.FSE.Procedures.ViewModels"
+ xmlns:localControls="clr-namespace:Tango.FSE.Procedures.Controls"
xmlns:material="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:editors="clr-namespace:Tango.Scripting.Editors;assembly=Tango.Scripting.Editors"
xmlns:controls="clr-namespace:Tango.FSE.Common.Controls;assembly=Tango.FSE.Common"
@@ -22,6 +23,7 @@
<UserControl.InputBindings>
<KeyBinding Key="F5" Command="{Binding RunProjectCommand}" />
<KeyBinding Key="F6" Command="{Binding CompileProjectCommand}" />
+ <KeyBinding Key="F7" Command="{Binding RunOnProceduresModuleCommand}" />
<KeyBinding Modifiers="Ctrl" Key="S" Command="{Binding SaveProjectCommand}" />
<KeyBinding Modifiers="Ctrl+Shift" Key="S" Command="{Binding SaveAsProjectCommand}" />
<KeyBinding Modifiers="Ctrl" Key="N" Command="{Binding NewProjectCommand}" />
@@ -31,13 +33,14 @@
<KeyBinding Key="F3" Command="{Binding FindNextCommand}" />
<KeyBinding Modifiers="Ctrl" Key="OemPlus" Command="{Binding IncreaseFontSizeCommand}" />
<KeyBinding Modifiers="Ctrl" Key="OemMinus" Command="{Binding DecreaseFontSizeCommand}" />
+ <KeyBinding Key="F1" Command="{Binding OpenHelpCommand}" />
</UserControl.InputBindings>
<Grid>
<Grid>
<DockPanel>
- <Menu IsMainMenu="True" DockPanel.Dock="Top">
- <MenuItem Header="_File">
+ <Menu IsMainMenu="True" DockPanel.Dock="Top" IsHitTestVisible="{Binding RuntimeErrorFree}">
+ <MenuItem Header="_File" IsEnabled="{Binding ProjectRunner.CanRun}">
<MenuItem Header="_New" MinWidth="250" Command="{Binding NewProjectCommand}" InputGestureText="Ctrl+N">
<MenuItem.Icon>
<material:PackIcon Kind="FileDocument" />
@@ -72,7 +75,7 @@
</MenuItem.Icon>
</MenuItem>
</MenuItem>
- <MenuItem Header="_Edit">
+ <MenuItem Header="_Edit" IsEnabled="{Binding ProjectRunner.CanRun}">
<MenuItem MinWidth="250" Header="_Undo" Command="Undo">
<MenuItem.Icon>
<material:PackIcon Kind="Undo" />
@@ -143,8 +146,14 @@
<material:PackIcon Kind="Stop" Foreground="{StaticResource FSE_RedBrush}" />
</MenuItem.Icon>
</MenuItem>
+ <Separator/>
+ <MenuItem Header="Run On Procedures" ToolTip="Run this project using the standard procedures module" Command="{Binding RunOnProceduresModuleCommand}" InputGestureText="F7" Visibility="{Binding ProjectRunner.CanRun,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <MenuItem.Icon>
+ <material:PackIcon Kind="PlayBox" Foreground="{StaticResource FSE_PrimaryAccentBrush}" />
+ </MenuItem.Icon>
+ </MenuItem>
</MenuItem>
- <MenuItem Header="_Wizard" ItemsSource="{Binding CreateGroups}">
+ <MenuItem Header="_Wizard" ItemsSource="{Binding CreateGroups}" IsEnabled="{Binding ProjectRunner.CanRun}">
<MenuItem.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource {x:Type MenuItem}}">
<Setter Property="Command" Value="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.CreateItemCommand}" />
@@ -157,26 +166,33 @@
</HierarchicalDataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>
- <MenuItem Header="Publish">
+ <MenuItem Header="Publish" IsEnabled="{Binding ProjectRunner.CanRun}">
<MenuItem Header="_Publish Project" InputGestureText="Ctrl+P" Command="{Binding TogglePublishPanelCommand}" MinWidth="250">
<MenuItem.Icon>
<material:PackIcon Kind="Publish" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
+ <MenuItem Header="Help">
+ <MenuItem Header="API Documentation" InputGestureText="F1" Command="{Binding OpenHelpCommand}" MinWidth="250">
+ <MenuItem.Icon>
+ <material:PackIcon Kind="HelpCircleOutline" />
+ </MenuItem.Icon>
+ </MenuItem>
+ </MenuItem>
</Menu>
- <Grid DockPanel.Dock="Top">
+ <Grid DockPanel.Dock="Top" IsHitTestVisible="{Binding RuntimeErrorFree}">
<!--Toolbar-->
<ToolBar ClipToBounds="False" Background="Transparent" HorizontalAlignment="Center" ToolBarTray.IsLocked="True">
- <Button ToolTip="Save" Command="{Binding SaveProjectCommand}">
+ <Button ToolTip="Save" Command="{Binding SaveProjectCommand}" IsEnabled="{Binding ProjectRunner.CanRun}">
<material:PackIcon Kind="ContentSave" />
</Button>
<Separator />
- <Button Command="Undo" ToolTip="Undo" ToolBar.OverflowMode="AsNeeded">
+ <Button Command="Undo" ToolTip="Undo" ToolBar.OverflowMode="AsNeeded" IsEnabled="{Binding ProjectRunner.CanRun}">
<material:PackIcon Kind="Undo" />
</Button>
- <Button Command="Redo" ToolTip="Redo" ToolBar.OverflowMode="AsNeeded">
+ <Button Command="Redo" ToolTip="Redo" ToolBar.OverflowMode="AsNeeded" IsEnabled="{Binding ProjectRunner.CanRun}">
<material:PackIcon Kind="Redo" />
</Button>
<Separator/>
@@ -187,10 +203,16 @@
<material:PackIcon Kind="ContentCopy" />
</Button>
<Separator />
- <Button Command="Paste" ToolTip="Paste" ToolBar.OverflowMode="AsNeeded">
+ <Button Command="Paste" ToolTip="Paste" ToolBar.OverflowMode="AsNeeded" IsEnabled="{Binding ProjectRunner.CanRun}">
<material:PackIcon Kind="ContentPaste" />
</Button>
<Separator/>
+ <Button Width="125" ToolTip="Continue (F5)" ToolBar.OverflowMode="AsNeeded" Command="{Binding ContinueProjectCommand}" Visibility="{Binding IsBreakPoint,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <DockPanel>
+ <material:PackIcon Kind="Play" Foreground="{StaticResource FSE_GreenBrush}" />
+ <TextBlock Margin="10 2 0 0" VerticalAlignment="Center">Continue</TextBlock>
+ </DockPanel>
+ </Button>
<Button Width="120" ToolTip="Run (F5)" ToolBar.OverflowMode="AsNeeded" Command="{Binding RunProjectCommand}" Visibility="{Binding ProjectRunner.IsRunning,Converter={StaticResource BooleanToVisibilityInverseConverter}}" IsEnabled="{Binding ProjectRunner.CanRun}">
<DockPanel>
<material:PackIcon Kind="Play" Foreground="{StaticResource FSE_GreenBrush}" />
@@ -206,7 +228,7 @@
</ToolBar>
</Grid>
- <Grid DockPanel.Dock="Bottom" Height="25" Background="#007BA5" TextElement.FontSize="{StaticResource FSE_SmallFontSize}">
+ <Grid DockPanel.Dock="Bottom" Height="25" Background="#007BA5" TextElement.FontSize="{StaticResource FSE_SmallFontSize}" IsHitTestVisible="{Binding RuntimeErrorFree}">
<!--Status Bar-->
<Grid>
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal" Margin="5 0 0 0">
@@ -231,7 +253,7 @@
<ColumnDefinition MaxWidth="500" MinWidth="250" Width="134*"/>
</Grid.ColumnDefinitions>
- <Grid Width="350" Margin="0 33 0 0" Visibility="{Binding IsPublishPanelOpened,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <Grid IsHitTestVisible="{Binding RuntimeErrorFree}" Width="350" Margin="0 33 0 0" Visibility="{Binding IsPublishPanelOpened,Converter={StaticResource BooleanToVisibilityConverter}}">
<Border BorderThickness="0 0 5 0" BorderBrush="{StaticResource FSE_PrimaryBackgroundBrush}">
<DockPanel Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}">
<Border DockPanel.Dock="Top" Padding="5" Background="{StaticResource FSE_PrimaryBackgroundLightBrush}" BorderThickness="0 1 0 0" BorderBrush="{StaticResource FSE_BorderBrush}">
@@ -304,7 +326,7 @@
<RowDefinition MinHeight="30" Height="210*"/>
</Grid.RowDefinitions>
- <Grid Grid.Column="2">
+ <Grid Grid.Column="2" IsHitTestVisible="{Binding RuntimeErrorFree}">
<!--Code Editor-->
<DockPanel>
<Grid DockPanel.Dock="Top" Height="35">
@@ -413,10 +435,13 @@
<ItemsControl.ItemTemplate>
<DataTemplate>
<editors:ScriptEditor
+ IsReadOnly="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.IsReadOnly}"
+ ScriptSource="{Binding}"
ReferenceAssemblies="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.LoadedAssemblies}"
AdditionalScripts="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.Project.AdditionalScripts}"
FontSize="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.FontSize}"
- Code="{Binding Code,Mode=TwoWay}">
+ Code="{Binding Code,Mode=TwoWay}"
+ BreakPointSymbolPressed="ScriptEditor_BreakPointSymbolPressed">
<editors:ScriptEditor.ContextMenu>
<ContextMenu>
@@ -492,13 +517,14 @@
</Border>
</Border>
</Grid>
+
</Grid>
</DockPanel>
</Grid>
- <GridSplitter Grid.Row="1" Height="5" HorizontalAlignment="Stretch" VerticalAlignment="Center" />
+ <GridSplitter IsHitTestVisible="{Binding RuntimeErrorFree}" Grid.Row="1" Height="5" HorizontalAlignment="Stretch" VerticalAlignment="Center" />
- <Grid Grid.Row="2">
+ <Grid Grid.Row="2" IsHitTestVisible="{Binding RuntimeErrorFree}">
<!--Output & Error Tabs-->
<TabControl SelectedIndex="{Binding SelectedToolWindow,Mode=TwoWay,Converter={StaticResource EnumToIntConverter}}" ItemContainerStyle="{StaticResource FSE_TabItem_VisualStudio_Output}" TabStripPlacement="Bottom" Margin="0" Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}" BorderThickness="0">
<TabItem Header="OUTPUT">
@@ -630,7 +656,7 @@
</Button>
<controls:FSERoundedCornersComboBox Height="25" FontSize="{StaticResource FSE_SmallFontSize}" ItemsSource="{Binding SelectionInputs}" SelectedValue="{Binding Value}" SelectedValuePath="Value" DisplayMemberPath="Name"/>
</DockPanel>
- </StackPanel>
+ </StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
@@ -639,7 +665,7 @@
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
- <StackPanel>
+ <StackPanel Margin="0 0 0 7">
<TextBlock Margin="2 0 0 2" FontSize="{StaticResource FSE_SmallerFontSize}">Value</TextBlock>
<DockPanel>
<ToggleButton x:Name="chkInput" Cursor="Hand" IsChecked="{Binding Value}" FocusVisualStyle="{x:Null}" HorizontalAlignment="Left" />
@@ -734,11 +760,73 @@
</TabItem>
</TabControl>
</Grid>
+
+ <Canvas Grid.Column="1" Grid.RowSpan="4" Background="Transparent" Margin="95 35 0 0" x:Name="runTimeErrorCanvas" IsHitTestVisible="True" Visibility="Hidden">
+ <DockPanel x:Name="runTimeErrorDock" Canvas.Top="200" Canvas.Left="0">
+ <Grid x:Name="runTimeErrorLineGrid" DockPanel.Dock="Bottom" Width="50" Height="50" HorizontalAlignment="Left">
+ <Line RenderTransformOrigin="0.5,0.5" x:Name="runTimeErrorLine" X1="0" Y1="50" X2="50" Y2="0" Stroke="{StaticResource FSE_ErrorBrush}">
+ <Line.RenderTransform>
+ <RotateTransform Angle="0" x:Name="runTimeErrorLineTransform" />
+ </Line.RenderTransform>
+ </Line>
+ </Grid>
+ <Border Margin="50 0 0 0" Width="500" Height="250" BorderBrush="{StaticResource FSE_BorderBrush}" BorderThickness="1" Background="{StaticResource FSE_PrimaryBackgroundMidBrush}">
+ <DockPanel>
+ <DockPanel DockPanel.Dock="Top" Height="25" Background="{StaticResource FSE_PrimaryBackgroundLightBrush}">
+ <controls:IconButton Width="20" Height="20" Cursor="Hand" ToolTip="Close" Padding="0" Icon="Close" DockPanel.Dock="Right" Margin="0 0 5 0" Command="{Binding CloseRuntimeErrorCommand}" />
+ <material:PackIcon Margin="5 0 0 0" Kind="AlertOctagon" VerticalAlignment="Center" />
+ <TextBlock Margin="5 2 0 0" VerticalAlignment="Center" FontSize="{StaticResource FSE_SmallFontSize}">Runtime Error</TextBlock>
+ </DockPanel>
+ <Grid>
+ <DockPanel>
+ <TextBlock Margin="10" DockPanel.Dock="Top" Text="{Binding RuntimeException.Message,Mode=OneWay}" TextWrapping="Wrap" FontSize="{StaticResource FSE_SmallFontSize}" Foreground="{StaticResource FSE_ErrorBrush}"></TextBlock>
+ <TextBox Style="{x:Null}" Margin="5 10 10 10"
+ HorizontalScrollBarVisibility="Hidden"
+ VerticalScrollBarVisibility="Auto"
+ AcceptsReturn="True"
+ TextWrapping="NoWrap"
+ BorderThickness="0"
+ Padding="5"
+ BorderBrush="{StaticResource FSE_BorderBrush}"
+ Background="Transparent"
+ Foreground="{StaticResource FSE_GrayBrush}"
+ CaretBrush="{StaticResource FSE_PrimaryForegroundBrush}"
+ FontSize="{StaticResource FSE_SmallFontSize}" Text="{Binding RuntimeException,Mode=OneWay}"
+ IsReadOnly="True">
+
+ </TextBox>
+ </DockPanel>
+ </Grid>
+ </DockPanel>
+ </Border>
+ </DockPanel>
+ </Canvas>
+
+ <Canvas Grid.Column="1" Grid.RowSpan="4" Background="Transparent" Margin="95 35 0 0" x:Name="runTimeBreakPointCanvas" IsHitTestVisible="True" Visibility="Hidden" MouseUp="RunTimeBreakPointCanvas_MouseUp">
+ <DockPanel x:Name="runTimeBreakPointDock" Canvas.Top="200" Canvas.Left="0">
+ <Border BorderBrush="{StaticResource FSE_BorderBrush}" MaxHeight="300" MaxWidth="700" BorderThickness="1" Background="{StaticResource FSE_PrimaryBackgroundMidBrush}" Padding="2" TextElement.FontSize="{StaticResource FSE_SmallFontSize}">
+ <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
+ <TreeView Style="{StaticResource FSE_Debug_TreeViewStyle}" x:Name="runTimeBreakPointTreeView">
+ <TreeView.Resources>
+ <HierarchicalDataTemplate ItemsSource="{Binding Nodes}" DataType="{x:Type global:DebugNode}">
+ <ContentControl Content="{Binding}" ContentTemplate="{StaticResource TreeViewDataTemplate}" />
+ </HierarchicalDataTemplate>
+ </TreeView.Resources>
+ <TreeViewItem ItemsSource="{Binding Nodes}">
+ <TreeViewItem.Header>
+ <ContentControl Content="{Binding}" ContentTemplate="{StaticResource TreeViewDataTemplate}" />
+ </TreeViewItem.Header>
+ </TreeViewItem>
+ </TreeView>
+ </ScrollViewer>
+ </Border>
+ </DockPanel>
+ </Canvas>
</Grid>
<GridSplitter Grid.Column="2" Width="5" HorizontalAlignment="Center" VerticalAlignment="Stretch" Margin="0 33 0 30" />
- <Grid Grid.Column="3">
+ <Grid Grid.Column="3" IsHitTestVisible="{Binding RuntimeErrorFree}">
<Grid Margin="0 33 0 29">
<!--Project Explorer-->
<DockPanel Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}">
@@ -766,13 +854,13 @@
<TextBlock Margin="5 0 0 0" Text="{Binding Project.Name}" VerticalAlignment="Center"></TextBlock>
</DockPanel>
- <DockPanel Margin="5 10 0 0">
+ <DockPanel Margin="5 10 0 0" IsEnabled="{Binding ProjectRunner.CanRun}">
<controls:ToggleIconButton Width="20" Height="20" x:Name="chkReference" UncheckedIcon="ChevronRight" CheckedIcon="ChevronDown" Cursor="Hand" IsChecked="True" />
<controls:IconButton VerticalAlignment="Center" DockPanel.Dock="Right" Icon="Add" Foreground="{StaticResource FSE_GreenBrush}" Command="{Binding AddReferenceAssemblyCommand}" ToolTip="Add Reference" />
<TextBlock Margin="5 0 0 0" VerticalAlignment="Center" Text="Reference Assemblies"/>
</DockPanel>
- <ListBox Margin="25 5 0 0" ItemsSource="{Binding Project.ReferenceAssemblies}" Visibility="{Binding ElementName=chkReference,Path=IsChecked,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <ListBox IsHitTestVisible="{Binding ProjectRunner.CanRun}" Margin="25 5 0 0" ItemsSource="{Binding Project.ReferenceAssemblies}" Visibility="{Binding ElementName=chkReference,Path=IsChecked,Converter={StaticResource BooleanToVisibilityConverter}}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<Setter Property="ContextMenu">
@@ -798,13 +886,13 @@
</ListBox.ItemTemplate>
</ListBox>
- <DockPanel Margin="5 10 0 0">
+ <DockPanel Margin="5 10 0 0" IsEnabled="{Binding ProjectRunner.CanRun}">
<controls:ToggleIconButton Width="20" Height="20" x:Name="chkResources" UncheckedIcon="ChevronRight" CheckedIcon="ChevronDown" Cursor="Hand" IsChecked="True" />
<controls:IconButton VerticalAlignment="Center" DockPanel.Dock="Right" Icon="Add" Foreground="{StaticResource FSE_GreenBrush}" Command="{Binding AddResourceCommand}" ToolTip="Add Resource" />
<TextBlock Margin="5 0 0 0" VerticalAlignment="Center" Text="Resources"/>
</DockPanel>
- <ListBox Margin="25 5 0 0" ItemsSource="{Binding Project.Resources}" Visibility="{Binding ElementName=chkResources,Path=IsChecked,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <ListBox IsHitTestVisible="{Binding ProjectRunner.CanRun}" Margin="25 5 0 0" ItemsSource="{Binding Project.Resources}" Visibility="{Binding ElementName=chkResources,Path=IsChecked,Converter={StaticResource BooleanToVisibilityConverter}}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<Setter Property="ContextMenu">
@@ -846,13 +934,13 @@
</ListBox.ItemTemplate>
</ListBox>
- <DockPanel Margin="5 10 0 0">
+ <DockPanel Margin="5 10 0 0" IsEnabled="{Binding ProjectRunner.CanRun}">
<controls:ToggleIconButton Width="20" Height="20" x:Name="chkDialogs" UncheckedIcon="ChevronRight" CheckedIcon="ChevronDown" Cursor="Hand" IsChecked="True" />
<controls:IconButton VerticalAlignment="Center" DockPanel.Dock="Right" Icon="Add" Foreground="{StaticResource FSE_GreenBrush}" Command="{Binding AddDialogCommand}" ToolTip="Add Dialog" />
<TextBlock Margin="5 0 0 0" VerticalAlignment="Center" Text="Dialogs"/>
</DockPanel>
- <ListBox Margin="25 5 0 0" ItemsSource="{Binding Project.Dialogs}" Visibility="{Binding ElementName=chkDialogs,Path=IsChecked,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <ListBox IsHitTestVisible="{Binding ProjectRunner.CanRun}" Margin="25 5 0 0" ItemsSource="{Binding Project.Dialogs}" Visibility="{Binding ElementName=chkDialogs,Path=IsChecked,Converter={StaticResource BooleanToVisibilityConverter}}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<EventSetter Event="PreviewMouseDoubleClick" Handler="OnDialogItemDoubleClick"></EventSetter>
@@ -888,17 +976,16 @@
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<EventSetter Event="PreviewMouseDoubleClick" Handler="OnScriptItemDoubleClick"></EventSetter>
-
<Setter Property="ContextMenu">
<Setter.Value>
- <ContextMenu>
- <MenuItem MinWidth="180" IsEnabled="{Binding IsEntryPoint,Converter={StaticResource BooleanInverseConverter}}" Header="Rename" Command="{Binding Source={StaticResource proxy},Path=Data.RenameLibraryCommand}" CommandParameter="{Binding}">
+ <ContextMenu IsEnabled="{Binding Source={StaticResource proxy},Path=Data.ProjectRunner.CanRun}">
+ <MenuItem MinWidth="180" IsEnabled="{Binding IsEntryPoint,Converter={StaticResource BooleanInverseConverter}}" Header="Rename" Command="{Binding Source={StaticResource proxy},Path=Data.RenameLibraryCommand}" CommandParameter="{Binding}">
<MenuItem.Icon>
<material:PackIcon Kind="Rename" />
</MenuItem.Icon>
</MenuItem>
<Separator/>
- <MenuItem MinWidth="180" IsEnabled="{Binding IsEntryPoint,Converter={StaticResource BooleanInverseConverter}}" Header="Delete" Command="{Binding Source={StaticResource proxy},Path=Data.DeleteLibraryCommand}" CommandParameter="{Binding}">
+ <MenuItem MinWidth="180" IsEnabled="{Binding IsEntryPoint,Converter={StaticResource BooleanInverseConverter}}" Header="Delete" Command="{Binding Source={StaticResource proxy},Path=Data.DeleteLibraryCommand}" CommandParameter="{Binding}">
<MenuItem.Icon>
<material:PackIcon Kind="Delete" Foreground="{StaticResource FSE_RedBrush}" />
</MenuItem.Icon>
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Views/ProcedureDesignerView.xaml.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Views/ProcedureDesignerView.xaml.cs
index 1e5deb04a..6746e794f 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Views/ProcedureDesignerView.xaml.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Procedures/Views/ProcedureDesignerView.xaml.cs
@@ -14,8 +14,11 @@ using System.Windows.Navigation;
using System.Windows.Shapes;
using Tango.FSE.Procedures.Contracts;
using Tango.FSE.Procedures.ViewModels;
+using Tango.Logging;
using Tango.Scripting.Basic;
+using Tango.Scripting.Core;
using Tango.Scripting.Editors;
+using Tango.SharedUI.Helpers;
namespace Tango.FSE.Procedures.Views
{
@@ -92,7 +95,7 @@ namespace Tango.FSE.Procedures.Views
if (editor != null)
{
- int count = editor.ReplaceAll(text, replace);
+ int count = editor.ReplaceAll(text, replace);
ColorizeKeyword(text);
return count;
}
@@ -137,5 +140,126 @@ namespace Tango.FSE.Procedures.Views
{
GetAllEditors().ForEach(x => x.ClearErrors());
}
+
+ public void ScrollToLine(int lineNumber)
+ {
+ GetCurrentEditor().ScrollToLine(lineNumber);
+ }
+
+ public void HighlightRuntimeError(int lineNumber)
+ {
+ ScrollToLine(lineNumber);
+ var editor = GetCurrentEditor();
+ editor.HighlightErrorLine(lineNumber);
+ UIHelper.DoEvents();
+ Point? p = editor.GetLineVisualPosition(lineNumber);
+
+ if (p != null)
+ {
+ Point point = p.Value;
+ point = new Point(point.X, point.Y - editor.VerticalOffset);
+ double height = editor.ActualHeight;
+
+ if (point.Y > runTimeErrorDock.ActualHeight)
+ {
+ DockPanel.SetDock(runTimeErrorLineGrid, Dock.Bottom);
+ runTimeErrorLineTransform.Angle = 0;
+ Canvas.SetTop(runTimeErrorDock, point.Y - runTimeErrorDock.ActualHeight);
+ }
+ else
+ {
+ DockPanel.SetDock(runTimeErrorLineGrid, Dock.Top);
+ runTimeErrorLineTransform.Angle = 90;
+ Canvas.SetTop(runTimeErrorDock, point.Y);
+ }
+
+ Canvas.SetLeft(runTimeErrorDock, Math.Min(point.X, editor.ActualWidth - 110 - runTimeErrorDock.ActualWidth));
+
+ runTimeErrorCanvas.Visibility = Visibility.Visible;
+ }
+ }
+
+ public void CloseRunTimeError()
+ {
+ runTimeErrorCanvas.Visibility = Visibility.Hidden;
+ GetCurrentEditor().ResetColorizationByKeyword();
+ }
+
+ public void HighlightDebugRequest(Object toDebug, int lineNumber)
+ {
+ ScrollToLine(lineNumber);
+ var editor = GetCurrentEditor();
+ editor.HighlightDebugLine(lineNumber);
+ UIHelper.DoEvents();
+ Point? p = editor.GetLineVisualPosition(lineNumber);
+
+ if (p != null)
+ {
+ Point point = p.Value;
+
+ }
+ }
+
+ public List<ScriptBreakPoint> GetBreakPoints()
+ {
+ List<ScriptBreakPoint> breakPoints = new List<ScriptBreakPoint>();
+
+ foreach (var editor in GetAllEditors())
+ {
+ breakPoints.AddRange(editor.GetBreakPoints());
+ }
+
+ return breakPoints;
+ }
+
+ public void HighlightBreakPointRequest(int lineNumber, List<ScriptBreakPointSymbol> symbols)
+ {
+ UIHelper.DoEvents();
+ ScrollToLine(lineNumber);
+ var editor = GetCurrentEditor();
+ editor.HighlightBreakPoint(lineNumber, symbols);
+ UIHelper.DoEvents();
+ }
+
+ public void ResetBreakPointRequest()
+ {
+ GetCurrentEditor().ResetBreakPointLine();
+ runTimeBreakPointCanvas.Visibility = Visibility.Hidden;
+ }
+
+ private void ScriptEditor_BreakPointSymbolPressed(object sender, BreakPointSymbolPressedEventArgs e)
+ {
+ try
+ {
+ var editor = GetCurrentEditor();
+ var point = new Point(e.Position.X, e.Position.Y - editor.VerticalOffset);
+ Canvas.SetTop(runTimeBreakPointDock, point.Y);
+ Canvas.SetLeft(runTimeBreakPointDock, Math.Min(point.X, editor.ActualWidth - 110 - runTimeBreakPointDock.ActualWidth));
+
+
+ try
+ {
+ runTimeBreakPointTreeView.SetExpansion(false);
+ }
+ catch { }
+
+ runTimeBreakPointTreeView.DataContext = DebugNode.CreateNode(e.BreakPointSymbol.Name, e.BreakPointSymbol.SymbolObject);
+ runTimeBreakPointCanvas.Visibility = Visibility.Visible;
+ }
+ catch (Exception ex)
+ {
+ LogManager.Default.Log(ex, "Error initializing break point debug window.");
+ }
+ }
+
+ private void RunTimeBreakPointCanvas_MouseUp(object sender, MouseButtonEventArgs e)
+ {
+ runTimeBreakPointCanvas.Visibility = Visibility.Hidden;
+ }
+
+ public string GetCaretWord()
+ {
+ return GetCurrentEditor()?.GetCaretWord();
+ }
}
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/ApplicationUpgradeGeneratedViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/ApplicationUpgradeGeneratedViewVM.cs
index 003aebab0..b90d73cc4 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/ApplicationUpgradeGeneratedViewVM.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/ApplicationUpgradeGeneratedViewVM.cs
@@ -136,7 +136,7 @@ namespace Tango.FSE.Upgrade.ViewModels
{
CanUpgradeNowError = null;
- if (!IsUpgradeNowSelected) return;
+ //if (!IsUpgradeNowSelected) return;
if (SelectedMachine == null)
{
@@ -181,7 +181,7 @@ namespace Tango.FSE.Upgrade.ViewModels
Handler = await RemoteUpgradeManager.PerformRemoteApplicationUpgrade(TemporaryTupFile, !SuppressFirmwareUpgrade);
await Handler.WaitForCompletion();
IsCompleted = true;
- await MachineProvider.DisconnectAndWaitForReconnection(TimeSpan.FromSeconds(20), TimeSpan.FromMinutes(1));
+ await MachineProvider.DisconnectAndWaitForReconnection(TimeSpan.FromSeconds(20), TimeSpan.FromMinutes(1), "The remote machine is now performing final upgrade operations.");
}
catch (OperationCanceledException)
{
@@ -237,7 +237,6 @@ namespace Tango.FSE.Upgrade.ViewModels
IsUpgradeNow = false;
IsUpgradeNowSelected = false;
TemporaryTupFile = null;
- InvalidateCanUpgradeNow();
InvalidateRelayCommands();
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/FirmwareUpgradeGeneratedViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/FirmwareUpgradeGeneratedViewVM.cs
index 57cd3aa43..ce01b5804 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/FirmwareUpgradeGeneratedViewVM.cs
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/ViewModels/FirmwareUpgradeGeneratedViewVM.cs
@@ -5,10 +5,13 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tango.BL.Entities;
+using Tango.BL.Enumerations;
using Tango.Core.Commands;
using Tango.FSE.Common;
+using Tango.FSE.Common.FileAssociation;
using Tango.FSE.Common.Navigation;
using Tango.FSE.Common.RemoteUpgrade;
+using Tango.FSE.Upgrade.Views;
using static Tango.FSE.Upgrade.ViewModels.FirmwareUpgradeGeneratedViewVM;
namespace Tango.FSE.Upgrade.ViewModels
@@ -102,14 +105,14 @@ namespace Tango.FSE.Upgrade.ViewModels
base.OnApplicationStarted();
MachineProvider.MachineConnected += (_, __) => InvalidateCanUpgradeNow();
MachineProvider.MachineDisconnected += (_, __) => InvalidateCanUpgradeNow();
+
+ FileAssociationProvider.RegisterFileAssociationHandler("tfp", HandleTfpFileAssociation);
}
private void InvalidateCanUpgradeNow()
{
CanUpgradeNowError = null;
- if (!IsUpgradeNowSelected) return;
-
if (!MachineProvider.IsConnected)
{
CanUpgradeNow = false;
@@ -158,7 +161,7 @@ namespace Tango.FSE.Upgrade.ViewModels
Handler = await RemoteUpgradeManager.PerformRemoteFirmwareUpgrade(TfpFileLocation);
await Handler.WaitForCompletion();
IsCompleted = true;
- await MachineProvider.DisconnectAndWaitForReconnection(TimeSpan.FromSeconds(20), TimeSpan.FromMinutes(1));
+ await MachineProvider.DisconnectAndWaitForReconnection(TimeSpan.FromSeconds(20), TimeSpan.FromMinutes(1),"The remote machine is now performing final upgrade operations.");
}
catch (OperationCanceledException)
{
@@ -201,8 +204,6 @@ namespace Tango.FSE.Upgrade.ViewModels
IsCompleted = false;
SelectedVersion = null;
IsUpgradeNowSelected = true;
- TfpFileLocation = null;
- InvalidateCanUpgradeNow();
InvalidateRelayCommands();
}
@@ -211,6 +212,7 @@ namespace Tango.FSE.Upgrade.ViewModels
SelectedVersion = obj.SelectedVersion;
TfpFileLocation = obj.TfpFileLocation;
IsUsingExistingTfp = obj.IsExistingTfpFile;
+ InvalidateCanUpgradeNow();
}
public async override Task<bool> OnNavigateBackRequest()
@@ -237,5 +239,39 @@ namespace Tango.FSE.Upgrade.ViewModels
return true;
}
+
+ private void HandleTfpFileAssociation(FileAssociationPackage package)
+ {
+ if (!IsFree)
+ {
+ NotificationProvider.ShowError("Cannot perform firmware upgrade while another upgrade is running.");
+ return;
+ }
+
+ if (!CurrentUser.HasPermission(Permissions.FSE_RemoteUpgradeOnline))
+ {
+ NotificationProvider.ShowError("Current user profile does not allow online remote upgrade.");
+ return;
+ }
+
+ if (File.Exists(package.File))
+ {
+ try
+ {
+ LogManager.Log("Performing remote firmware upgrade from file association...");
+ Handler = new RemoteUpgradeHandler("Ready");
+ IsCompleted = false;
+ TfpFileLocation = package.File;
+ IsUsingExistingTfp = true;
+ InvalidateCanUpgradeNow();
+ NavigationManager.NavigateTo<UpgradeModule>(true);
+ ModularNavigationManager.NavigateTo(Navigation.RemoteUpgradeView.FirmwareUpgradeGeneratedView);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error occurred while trying to handle the tfp file association.");
+ }
+ }
+ }
}
}
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/ApplicationUpgradeGeneratedView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/ApplicationUpgradeGeneratedView.xaml
index c1f60d813..572785ee4 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/ApplicationUpgradeGeneratedView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/ApplicationUpgradeGeneratedView.xaml
@@ -12,11 +12,11 @@
d:DesignHeight="720" d:DesignWidth="1280" d:DataContext="{d:DesignInstance Type=vm:ApplicationUpgradeGeneratedViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.ApplicationUpgradeGeneratedViewVM}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}">
<Grid IsEnabled="{Binding IsFree}">
<Grid IsEnabled="{Binding IsCompleted,Converter={StaticResource BooleanInverseConverter}}">
- <StackPanel>
- <TextBlock FontSize="{StaticResource FSE_LargeFontSize}" Foreground="{StaticResource FSE_GreenBrush}">Application Upgrade Ready!</TextBlock>
+ <StackPanel Visibility="{Binding IsCompleted,Converter={StaticResource BooleanToVisibilityInverseConverter}}">
+ <TextBlock FontSize="{StaticResource FSE_LargeFontSize}" Foreground="{StaticResource FSE_GreenBrush}">Full Upgrade Ready!</TextBlock>
<TextBlock Margin="0 10 0 0" Foreground="{StaticResource FSE_GrayBrush}" LineHeight="20">
- <Run>Your machine application and firmware upgrade is ready.</Run>
+ <Run>Your machine application and firmware upgrade is ready.</Run>
</TextBlock>
<StackPanel Visibility="{Binding IsUpgradeNow,Converter={StaticResource BooleanToVisibilityConverter}}" Margin="0 5 0 0" >
@@ -60,6 +60,14 @@
</StackPanel>
</StackPanel>
+ <StackPanel Visibility="{Binding IsCompleted,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <TextBlock FontSize="{StaticResource FSE_LargeFontSize}" Foreground="{StaticResource FSE_GreenBrush}">Full Upgrade Completed!</TextBlock>
+
+ <TextBlock Margin="0 10 0 0" Foreground="{StaticResource FSE_GrayBrush}" LineHeight="20">
+ The remote machine should perform the final update operations and automatically reconnect.
+ </TextBlock>
+ </StackPanel>
+
<StackPanel VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="1000">
<DockPanel>
<Grid DockPanel.Dock="Right" >
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeGeneratedView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeGeneratedView.xaml
index a9d6034fd..c40389600 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeGeneratedView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeGeneratedView.xaml
@@ -12,7 +12,7 @@
d:DesignHeight="720" d:DesignWidth="1280" d:DataContext="{d:DesignInstance Type=vm:FirmwareUpgradeGeneratedViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.FirmwareUpgradeGeneratedViewVM}" Foreground="{StaticResource FSE_PrimaryForegroundBrush}">
<Grid IsEnabled="{Binding IsFree}">
<Grid IsEnabled="{Binding IsCompleted,Converter={StaticResource BooleanInverseConverter}}">
- <StackPanel>
+ <StackPanel Visibility="{Binding IsCompleted,Converter={StaticResource BooleanToVisibilityInverseConverter}}">
<TextBlock FontSize="{StaticResource FSE_LargeFontSize}" Foreground="{StaticResource FSE_GreenBrush}">Firmware Upgrade Ready!</TextBlock>
<TextBlock Margin="0 10 0 0" Foreground="{StaticResource FSE_GrayBrush}" LineHeight="20">
@@ -49,6 +49,14 @@
</StackPanel>
</StackPanel>
+ <StackPanel Visibility="{Binding IsCompleted,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <TextBlock FontSize="{StaticResource FSE_LargeFontSize}" Foreground="{StaticResource FSE_GreenBrush}">Firmware Upgrade Completed!</TextBlock>
+
+ <TextBlock Margin="0 10 0 0" Foreground="{StaticResource FSE_GrayBrush}" LineHeight="20">
+ The remote machine should perform the final update operations and automatically reconnect.
+ </TextBlock>
+ </StackPanel>
+
<StackPanel VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="1000">
<DockPanel>
<Grid DockPanel.Dock="Right" >
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeView.xaml b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeView.xaml
index 6aeb0fcb1..3e93300c0 100644
--- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeView.xaml
+++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Upgrade/Views/FirmwareUpgradeView.xaml
@@ -60,7 +60,7 @@
</StackPanel>
</DockPanel>
- <RadioButton x:Name="chkExisting" IsEnabled="{Binding MachineProvider.IsConnected}" IsChecked="{Binding ElementName=chkDownload,Path=IsChecked,Converter={StaticResource BooleanInverseConverter},Mode=TwoWay}" Margin="0 20 0 0" VerticalContentAlignment="Center" Cursor="Hand" Padding="25 0 0 0">
+ <RadioButton x:Name="chkExisting" IsChecked="{Binding ElementName=chkDownload,Path=IsChecked,Converter={StaticResource BooleanInverseConverter},Mode=TwoWay}" Margin="0 20 0 0" VerticalContentAlignment="Center" Cursor="Hand" Padding="25 0 0 0">
<DockPanel>
<Image Source="../Images/tfp_ready.png" Width="48" Height="48" />
<TextBlock Margin="20 0 0 0" VerticalAlignment="Center">I already have the .tfp file and just want to upgrade the currently connected machine. (requires an active machine connection)</TextBlock>
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/BugReporting/ApplicationStartedAfterCrashException.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/BugReporting/ApplicationStartedAfterCrashException.cs
new file mode 100644
index 000000000..946e9bbfe
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/BugReporting/ApplicationStartedAfterCrashException.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.FSE.Common.BugReporting
+{
+ public class ApplicationStartedAfterCrashException : Exception
+ {
+ public ApplicationStartedAfterCrashException(String message) : base(message)
+ {
+
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Connection/IMachineProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Connection/IMachineProvider.cs
index 4d552d856..9a98477b8 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Connection/IMachineProvider.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Connection/IMachineProvider.cs
@@ -79,7 +79,8 @@ namespace Tango.FSE.Common.Connection
/// </summary>
/// <param name="beginDelay">The amount of time to wait before starting reconnection attempts.</param>
/// <param name="timeout">The timeout for when to drop the reconnection attempt.</param>
+ /// <param name="message">The message to display to the user</param>
/// <returns></returns>
- Task DisconnectAndWaitForReconnection(TimeSpan beginDelay, TimeSpan timeout);
+ Task DisconnectAndWaitForReconnection(TimeSpan beginDelay, TimeSpan timeout, String message = null);
}
}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Connection/MachineConnectionTypes.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Connection/MachineConnectionTypes.cs
index 1ed8447b6..ef233dda8 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Connection/MachineConnectionTypes.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Connection/MachineConnectionTypes.cs
@@ -7,17 +7,36 @@ using Tango.FSE.Common.Connection;
namespace Tango.FSE.Common.Connection
{
+ /// <summary>
+ /// Represents the available machine connection end-point types.
+ /// </summary>
public enum MachineConnectionTypes
{
+ /// <summary>
+ /// Local USB connection.
+ /// </summary>
USB,
+ /// <summary>
+ /// Local area network.
+ /// </summary>
Wifi,
+ /// <summary>
+ /// Via cloud/machine service.
+ /// </summary>
SignalR,
+ /// <summary>
+ /// In-Memory emulator.
+ /// </summary>
Emulator,
}
}
public static class ExtensionMethods
{
+ /// <summary>
+ /// Determines whether the connection is a remote connection (WiFi/SignalR).
+ /// </summary>
+ /// <param name="type">The type.</param>
public static bool IsRemote(this MachineConnectionTypes type)
{
return type == MachineConnectionTypes.Wifi || type == MachineConnectionTypes.SignalR;
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Diagnostics/DiagnosticsPackage.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Diagnostics/DiagnosticsPackage.cs
index d546a8c17..5413dd8ec 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Diagnostics/DiagnosticsPackage.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Diagnostics/DiagnosticsPackage.cs
@@ -11,12 +11,15 @@ using Tango.PMR.Diagnostics;
namespace Tango.FSE.Common.Diagnostics
{
+ /// <summary>
+ /// Represents a machine diagnostics frame package.
+ /// </summary>
public class DiagnosticsPackage
{
private static Dictionary<String, PropertyInfo> _monitorsProperties;
/// <summary>
- /// Gets or sets the frame.
+ /// Gets or sets the diagnostics frame.
/// </summary>
public DiagnosticsFrame Frame { get; set; }
@@ -48,21 +51,20 @@ namespace Tango.FSE.Common.Diagnostics
}
/// <summary>
- /// Gets the monitor value by the specified monitor using reflections.
+ /// Gets the monitor value by the specified <see cref="TechMonitors"/> enumeration.
/// </summary>
- /// <param name="monitor">The monitor.</param>
- /// <returns></returns>
+ /// <param name="monitor">The monitor enumeration.</param>
+ /// <returns>The monitor object.</returns>
public object GetMonitorObject(TechMonitors monitor)
{
return MonitorsProperties[monitor.ToString()].GetValue(Frame.Data.Monitors);
}
/// <summary>
- /// Gets the last data point from a protobuf repeated field.
+ /// Gets the last data point of a repeated field monitor by the specified <see cref="TechMonitors"/> enumeration.
/// </summary>
- /// <param name="monitor">The monitor.</param>
- /// <param name="value">The value.</param>
- /// <returns></returns>
+ /// <param name="monitor">The monitor enumeration.</param>
+ /// <returns>Last value in the array.</returns>
public double GetMonitorLastValue(TechMonitors monitor)
{
var value = GetMonitorObject(monitor);
@@ -71,11 +73,10 @@ namespace Tango.FSE.Common.Diagnostics
}
/// <summary>
- /// Gets the data array from a protobuf repeated field.
+ /// Gets the data array from a protobuf repeated monitor by the specified <see cref="TechMonitors"/> enumeration.
/// </summary>
- /// <param name="monitor">The monitor.</param>
- /// <param name="value">The value.</param>
- /// <returns></returns>
+ /// <param name="monitor">The monitor enumeration.</param>
+ /// <returns>List of double values representing the monitor data points.</returns>
public List<double> GetMonitorArray(TechMonitors monitor)
{
var value = GetMonitorObject(monitor);
@@ -85,8 +86,8 @@ namespace Tango.FSE.Common.Diagnostics
/// <summary>
/// Gets the data matrix from a protobuf repeated field of <see cref="DoubleArray"/>.
/// </summary>
- /// <param name="monitor">The monitor.</param>
- /// <returns></returns>
+ /// <param name="monitor">The monitor enumeration.</param>
+ /// <returns>A matrix of double values.</returns>
public List<List<double>> GetMonitorMatrix(TechMonitors monitor)
{
var value = GetMonitorObject(monitor);
@@ -98,7 +99,7 @@ namespace Tango.FSE.Common.Diagnostics
/// Gets the state of the digital interface.
/// </summary>
/// <param name="interface">The interface.</param>
- /// <returns></returns>
+ /// <returns>Digital interface state object.</returns>
public DigitalInterfaceState GetDigitalInterfaceState(TechIos @interface)
{
return Frame.Data.DigitalInterfaceStates.SingleOrDefault(x => x.InterfaceIO == (InterfaceIOs)@interface);
@@ -108,7 +109,7 @@ namespace Tango.FSE.Common.Diagnostics
/// Gets the state of the specified valve.
/// </summary>
/// <param name="valve">The valve.</param>
- /// <returns></returns>
+ /// <returns>Valve state object.</returns>
public ValveState GetValveState(TechValves valve)
{
return Frame.Data.ValvesStates.SingleOrDefault(x => x.ValveType == (ValveType)valve);
@@ -118,7 +119,7 @@ namespace Tango.FSE.Common.Diagnostics
/// Gets the state of the specified heater.
/// </summary>
/// <param name="heater">The heater.</param>
- /// <returns></returns>
+ /// <returns>Heater state object.</returns>
public HeaterState GetHeaterState(TechHeaters heater)
{
return Frame.Data.HeatersStates.SingleOrDefault(x => x.HeaterType == (HeaterType)heater);
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEApplication/IFSEApplicationManager.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEApplication/IFSEApplicationManager.cs
index c3f54d0e2..5f72fbd29 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEApplication/IFSEApplicationManager.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEApplication/IFSEApplicationManager.cs
@@ -64,6 +64,11 @@ namespace Tango.FSE.Common.FSEApplication
void Restart();
/// <summary>
+ /// Activates the main window if it's not in focus.
+ /// </summary>
+ void ActivateMainWindow();
+
+ /// <summary>
/// Gets the application version.
/// </summary>
Version Version { get; }
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSESettings.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSESettings.cs
index 0592aa6cc..c85a5fd35 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSESettings.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSESettings.cs
@@ -137,6 +137,16 @@ namespace Tango.FSE.Common
public String LastReportArea { get; set; }
/// <summary>
+ /// Gets or sets a value indicating whether the application has terminated unexpectedly.
+ /// </summary>
+ public bool TerminatedExpectedly { get; set; }
+
+ /// <summary>
+ /// Gets or sets the file association service port.
+ /// </summary>
+ public int FileAssociationServicePort { get; set; }
+
+ /// <summary>
/// Initializes a new instance of the <see cref="FSESettings"/> class.
/// </summary>
public FSESettings()
@@ -152,6 +162,8 @@ namespace Tango.FSE.Common
AutoMachineReconnectionTimeoutSeconds = 10;
AutoCheckForUpdates = true;
EnableAdaptiveScaling = true;
+ TerminatedExpectedly = true;
+ FileAssociationServicePort = 1800;
}
}
} \ No newline at end of file
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs
index d6e3a5b52..07d2a7a5b 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/FSEViewModel.cs
@@ -43,6 +43,7 @@ using Tango.FSE.Common.Tiles;
using Tango.FSE.Common.RemoteJob;
using Tango.FSE.Common.WindowsManager;
using Tango.FSE.Common.DemoMode;
+using Tango.FSE.Common.FileAssociation;
namespace Tango.FSE.Common
{
@@ -229,6 +230,12 @@ namespace Tango.FSE.Common
public IDemoModeManager DemoModeManager { get; set; }
/// <summary>
+ /// Gets or sets the file association provider.
+ /// </summary>
+ [TangoInject]
+ public IFileAssociationProvider FileAssociationProvider { get; set; }
+
+ /// <summary>
/// Gets or sets the FSE service.
/// </summary>
[TangoInject]
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/FileAssociation/FileAssociationPackage.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/FileAssociation/FileAssociationPackage.cs
new file mode 100644
index 000000000..ec072e7b1
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/FileAssociation/FileAssociationPackage.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.FSE.Common.FileAssociation
+{
+ public class FileAssociationPackage
+ {
+ public String TargetName { get; set; }
+ public String File { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/FileAssociation/IFileAssociationProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/FileAssociation/IFileAssociationProvider.cs
new file mode 100644
index 000000000..2517ba82c
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/FileAssociation/IFileAssociationProvider.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.FSE.Common.FileAssociation
+{
+ public interface IFileAssociationProvider : INotifyApplicationStarted, INotifyApplicationReady
+ {
+ bool HasStartArgsPackage { get; }
+ void RegisterFileAssociationHandler(String targetName, Action<FileAssociationPackage> handler);
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/FileSystem/IFileSystemProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/FileSystem/IFileSystemProvider.cs
index 9f54b6958..a97a44f81 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.Common/FileSystem/IFileSystemProvider.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/FileSystem/IFileSystemProvider.cs
@@ -66,9 +66,10 @@ namespace Tango.FSE.Common.FileSystem
/// </summary>
/// <param name="localSourcePath">The local source path.</param>
/// <param name="remotePath">The remote destination path.</param>
+ /// <param name="forRemoteUpgrade">Indicates whether this upload operation is performed for a remote upgrade.</param>
/// <returns></returns>
/// <exception cref="System.IO.FileNotFoundException">Could not locate the local file or directory to upload.</exception>
- Task<FileSystemHandler> Upload(String localSourcePath, String remotePath);
+ Task<FileSystemHandler> Upload(String localSourcePath, String remotePath, bool forRemoteUpgrade = false);
/// <summary>
/// Copies the specified remote file or folder to the specified target remote folder.
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Helpers/LogsHelper.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Helpers/LogsHelper.cs
new file mode 100644
index 000000000..eac030fb8
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Helpers/LogsHelper.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Logging;
+
+namespace Tango.FSE.Common.Helpers
+{
+ public static class LogsHelper
+ {
+ private static LogSafe _logSafe;
+
+ public static void SetLogSafe(LogSafe logSafe)
+ {
+ _logSafe = logSafe;
+ }
+
+ public static LogSafe GetLogSafe()
+ {
+ return _logSafe;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Navigation/INavigationManager.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/Navigation/INavigationManager.cs
index ddcc5dc8f..2efd3c75d 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Navigation/INavigationManager.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Navigation/INavigationManager.cs
@@ -106,9 +106,10 @@ namespace Tango.FSE.Common.Navigation
/// <typeparam name="TView">The type of the view.</typeparam>
/// <typeparam name="TPass">The type of the pass.</typeparam>
/// <param name="obj">The object.</param>
- /// <param name="pushToHistory">if set to <c>true</c> [push to history].</param>
+ /// <param name="pushToHistory">Push the current view to history ?.</param>
+ /// <param name="force">Force the navigation even if we are on the same view.</param>
/// <returns></returns>
- Task<bool> NavigateWithObject<TModule, TView, TPass>(TPass obj, bool pushToHistory = true)
+ Task<bool> NavigateWithObject<TModule, TView, TPass>(TPass obj, bool pushToHistory = true, bool force = false)
where TModule : IFSEModule;
/// <summary>
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/SQL/IRemoteSqlProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/SQL/IRemoteSqlProvider.cs
index d3b6660bf..e41d864c3 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.Common/SQL/IRemoteSqlProvider.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/SQL/IRemoteSqlProvider.cs
@@ -7,10 +7,32 @@ using Tango.PPC.Shared.SQL;
namespace Tango.FSE.Common.SQL
{
+ /// <summary>
+ /// Represents a remote SQL provider.
+ /// Can be used to execute commands against the remote machine's database and the global twine's database.
+ /// </summary>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to set the connected machine's demo state and query for the connected machine's jobs.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/Sql/Program.cs" title="Remote SQL" region="Example" />
+ /// </example>
public interface IRemoteSqlProvider
{
+ /// <summary>
+ /// Executes the SQL command asynchronously.
+ /// </summary>
+ /// <param name="command">The command.</param>
+ /// <returns>Remote command result.</returns>
Task<RemoteSqlCommandResult> ExecuteSqlCommandAsync(RemoteSqlCommand command);
+ /// <summary>
+ /// Executes the SQL command.
+ /// </summary>
+ /// <param name="command">The command.</param>
+ /// <returns>Remote command result.</returns>
RemoteSqlCommandResult ExecuteSqlCommand(RemoteSqlCommand command);
}
}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/SQL/RemoteSqlCommand.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/SQL/RemoteSqlCommand.cs
index 95f94ad08..99d0f1878 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.Common/SQL/RemoteSqlCommand.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/SQL/RemoteSqlCommand.cs
@@ -6,12 +6,37 @@ using System.Threading.Tasks;
namespace Tango.FSE.Common.SQL
{
+ /// <summary>
+ /// Represents a SQL command that can be executed by a <see cref="IRemoteSqlProvider"/>.
+ /// </summary>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to set the connected machine's demo state and query for the connected machine's jobs.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/Sql/Program.cs" title="Remote SQL" region="Example" />
+ /// </example>
public class RemoteSqlCommand
{
+ /// <summary>
+ /// Gets or sets the command execution mode.
+ /// </summary>
public RemoteSqlCommandMode Mode { get; set; }
+
+ /// <summary>
+ /// Gets or sets the SQL query.
+ /// </summary>
public String SQL { get; set; }
+
+ /// <summary>
+ /// Gets or sets the command timeout.
+ /// </summary>
public int Timeout { get; set; }
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RemoteSqlCommand"/> class.
+ /// </summary>
public RemoteSqlCommand()
{
Timeout = 30;
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/SQL/RemoteSqlCommandMode.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/SQL/RemoteSqlCommandMode.cs
index 1b05e8e86..702f35e8a 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.Common/SQL/RemoteSqlCommandMode.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/SQL/RemoteSqlCommandMode.cs
@@ -7,8 +7,16 @@ using System.Threading.Tasks;
namespace Tango.FSE.Common.SQL
{
/// <summary>
- /// Represents an SQL command mode.
+ /// Represents an SQL command execution mode.
/// </summary>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to set the connected machine's demo state and query for the connected machine's jobs.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/Sql/Program.cs" title="Remote SQL" region="Example" />
+ /// </example>
public enum RemoteSqlCommandMode
{
/// <summary>
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/SQL/RemoteSqlCommandResult.cs b/Software/Visual_Studio/FSE/Tango.FSE.Common/SQL/RemoteSqlCommandResult.cs
index 34ab74a68..da21ae24d 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.Common/SQL/RemoteSqlCommandResult.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/SQL/RemoteSqlCommandResult.cs
@@ -7,22 +7,68 @@ using Tango.PPC.Shared.SQL;
namespace Tango.FSE.Common.SQL
{
+ /// <summary>
+ /// Represents a <see cref="RemoteSqlCommand"/> result.
+ /// </summary>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to set the connected machine's demo state and query for the connected machine's jobs.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/Sql/Program.cs" title="Remote SQL" region="Example" />
+ /// </example>
public class RemoteSqlCommandResult
{
+ /// <summary>
+ /// Gets or sets the connected machine's database affected records.
+ /// </summary>
public int LocalAffectedRecords { get; set; }
+
+ /// <summary>
+ /// Gets or sets the data set retrieved from the connected machine's database.
+ /// </summary>
public RemoteSqlDataSet LocalDatSet { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether the query against the connected machine's database has encountered an error.
+ /// </summary>
public bool HasLocalError { get; set; }
+
+ /// <summary>
+ /// Gets or sets the error encountered by the query when it was executed against the connected machine's database.
+ /// Relevant only if <see cref="HasLocalError"/> equals true.
+ /// </summary>
public String LocalError { get; set; }
+ /// <summary>
+ /// Gets or sets the global database affected records.
+ /// </summary>
public int GlobalAffectedRecords { get; set; }
- public RemoteSqlDataSet GLobalDataSet { get; set; }
+
+ /// <summary>
+ /// Gets or sets the data set retrieved from the global database.
+ /// </summary>
+ public RemoteSqlDataSet GlobalDataSet { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether the query against the global database has encountered an error.
+ /// </summary>
public bool HasGlobalError { get; set; }
+
+ /// <summary>
+ /// Gets or sets the error encountered by the query when it was executed against the global database.
+ /// Relevant only if <see cref="HasGlobalError"/> equals true.
+ /// </summary>
public String GlobalError { get; set; }
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RemoteSqlCommandResult"/> class.
+ /// </summary>
public RemoteSqlCommandResult()
{
LocalDatSet = new RemoteSqlDataSet();
- GLobalDataSet = new RemoteSqlDataSet();
+ GlobalDataSet = new RemoteSqlDataSet();
}
}
}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj b/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj
index e0c41d7a9..0584d2e0b 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj
+++ b/Software/Visual_Studio/FSE/Tango.FSE.Common/Tango.FSE.Common.csproj
@@ -25,6 +25,8 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+ <DocumentationFile>..\..\Build\FSE\Debug\Tango.FSE.Common.xml</DocumentationFile>
+ <NoWarn>1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -33,6 +35,8 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
+ <DocumentationFile>..\..\Build\FSE\Release\Tango.FSE.Common.xml</DocumentationFile>
+ <NoWarn>1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<Reference Include="ControlzEx, Version=3.0.2.4, Culture=neutral, processorArchitecture=MSIL">
@@ -112,6 +116,7 @@
<Compile Include="AutoComplete\AutoCompleteSource.cs" />
<Compile Include="Behaviors\CircularProgressBarBehavior.cs" />
<Compile Include="Behaviors\StyleBehavior.cs" />
+ <Compile Include="BugReporting\ApplicationStartedAfterCrashException.cs" />
<Compile Include="BugReporting\Bug.cs" />
<Compile Include="BugReporting\BugAttachement.cs" />
<Compile Include="BugReporting\BugType.cs" />
@@ -174,6 +179,8 @@
<Compile Include="ExtensionMethods\IExternalBridgeClientExtensions.cs" />
<Compile Include="ExtensionMethods\IFSEViewExtensions.cs" />
<Compile Include="ExtensionMethods\ViewModelExtensionMethods.cs" />
+ <Compile Include="FileAssociation\FileAssociationPackage.cs" />
+ <Compile Include="FileAssociation\IFileAssociationProvider.cs" />
<Compile Include="FileSystem\FileSystemHandler.cs" />
<Compile Include="FileSystem\FileSystemHandlerStatus.cs" />
<Compile Include="FileSystem\FileSystemHandlerType.cs" />
@@ -187,6 +194,7 @@
<Compile Include="Graphs\GraphHelper.cs" />
<Compile Include="Helpers\DesignModeHelper.cs" />
<Compile Include="Helpers\EncryptionHelper.cs" />
+ <Compile Include="Helpers\LogsHelper.cs" />
<Compile Include="Helpers\ResourceHelper.cs" />
<Compile Include="INotifyApplicationStarted.cs" />
<Compile Include="INotifyApplicationReady.cs" />
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml.cs
index 8e0208c0f..de0594703 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/App.xaml.cs
@@ -1,22 +1,28 @@
-using System;
+using Newtonsoft.Json;
+using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics;
+using System.Globalization;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
+using System.Windows.Markup;
using Tango.Core.DI;
using Tango.Core.Helpers;
using Tango.FSE.Common;
using Tango.FSE.Common.BugReporting;
+using Tango.FSE.Common.FileAssociation;
using Tango.FSE.Common.Helpers;
using Tango.FSE.Common.Notifications;
+using Tango.FSE.UI.FileAssociation;
using Tango.Integration.Operation;
using Tango.Logging;
using Tango.Settings;
+using ZetaIpc.Runtime.Client;
namespace Tango.FSE.UI
{
@@ -29,6 +35,10 @@ namespace Tango.FSE.UI
private LogManager LogManager = LogManager.Default;
private HashSet<String> _ignoredGlobalExceptions;
+ public static bool IsStartedAfterCrash { get; private set; }
+ public static String StartedAfterCrashError { get; private set; }
+ private static Mutex mutex = new Mutex(true, "{8F6F0AC4-B9A1-45fd-A8CF-72F0TANGOFSE}");
+
public App() : base()
{
_ignoredGlobalExceptions = new HashSet<string>();
@@ -45,6 +55,55 @@ namespace Tango.FSE.UI
protected override void OnStartup(StartupEventArgs e)
{
+ try
+ {
+ if (e.Args != null)
+ {
+ if (e.Args.Length == DefaultFileAssociationProvider.FILE_ASSOCIATION_ARGS_COUNT)
+ {
+ if (e.Args[0] == DefaultFileAssociationProvider.FILE_ASSOCIATION_PREFIX)
+ {
+ if (mutex.WaitOne(TimeSpan.Zero, true))
+ {
+ //This is the first instance. Do nothing...
+ mutex.ReleaseMutex();
+ }
+ else
+ {
+ //MessageBox.Show($"Run Procedure {e.Args[2]} on another instance.");
+ var settings = SettingsManager.Default.GetOrCreate<FSESettings>();
+ var ipcClient = new IpcClient();
+ ipcClient.Initialize(settings.FileAssociationServicePort);
+ ipcClient.Send(JsonConvert.SerializeObject(new FileAssociationPackage()
+ {
+ TargetName = e.Args[1],
+ File = e.Args[2]
+ }));
+ Thread.Sleep(1000);
+ Environment.Exit(0);
+ return;
+ }
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine(ex);
+ }
+
+ //Set culture info.
+ var enUSCulture = new CultureInfo("en-US");
+
+ Thread.CurrentThread.CurrentCulture = enUSCulture;
+ Thread.CurrentThread.CurrentUICulture = enUSCulture;
+ CultureInfo.DefaultThreadCurrentCulture = enUSCulture;
+ CultureInfo.DefaultThreadCurrentUICulture = enUSCulture;
+
+ FrameworkElement.LanguageProperty.OverrideMetadata(
+ typeof(FrameworkElement),
+ new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));
+
ThreadPool.SetMaxThreads(1000, 1000);
ThreadsHelper.SetDisptacher(Dispatcher);
@@ -67,8 +126,8 @@ namespace Tango.FSE.UI
operatorLogger.EnableMaxFileSizeLimit = true;
}
- LogManager.Log("Application Started...");
- LogManager.Log($"Application Version: '{AssemblyHelper.GetCurrentAssemblyVersion()}'.");
+ LogsHelper.SetLogSafe(LogManager.CreateLogSafe());
+ LogManager.Log($"Application Started... Version: '{AssemblyHelper.GetCurrentAssemblyVersion()}'.");
WebRequest.DefaultWebProxy = null;
@@ -77,10 +136,49 @@ namespace Tango.FSE.UI
exceptionTrapper = new WpfGlobalExceptionTrapper();
exceptionTrapper.Initialize(this);
exceptionTrapper.ApplicationCrashed += ExceptionTrapper_ApplicationCrashed;
+
+ if (!Debugger.IsAttached)
+ {
+ ProcessLastApplicationTermination();
+ }
}
#region Global Exception Trapping
+ private void ProcessLastApplicationTermination()
+ {
+ try
+ {
+ LogManager.Log("Analyzing previous application termination state...");
+
+ var settings = SettingsManager.Default.GetOrCreate<FSESettings>();
+
+ if (!settings.TerminatedExpectedly)
+ {
+ GetLastApplicationCrashFromWindows();
+ }
+
+ settings.TerminatedExpectedly = false;
+ settings.Save();
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error occurred while processing application last termination state.");
+ }
+ }
+
+ private async void GetLastApplicationCrashFromWindows()
+ {
+ //Try find event log crash reports from the last 60 minutes...
+ var logItem = await exceptionTrapper.GetLastApplicationCrashEventLog(60);
+ if (logItem != null)
+ {
+ IsStartedAfterCrash = true;
+ StartedAfterCrashError = logItem.Message;
+ LogManager.Log(logItem);
+ }
+ }
+
/// <summary>
/// Handles the ApplicationCrashed event of the ExceptionTrapper.
/// </summary>
@@ -106,7 +204,7 @@ namespace Tango.FSE.UI
try
{
- LogManager.Log(e.Exception, "Application Crashed!");
+ LogManager.Log(e.Exception, LogCategory.Critical, "Application Crashed!");
LogManager.Log("Trying to recover from application crash...");
try
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/BugReporting/DefaultBugReporter.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/BugReporting/DefaultBugReporter.cs
index 594b04abb..a99752091 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/BugReporting/DefaultBugReporter.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/BugReporting/DefaultBugReporter.cs
@@ -121,7 +121,7 @@ namespace Tango.FSE.UI.BugReporting
item.Iteration = Project.Iterations.FirstOrDefault();
- var twineUser = Project.Members.SingleOrDefault(x => x.Email.ToLower() == AuthenticationProvider.CurrentUser.Email);
+ var twineUser = Project.Members.SingleOrDefault(x => x.Email.ToLower().Trim() == AuthenticationProvider.CurrentUser.Email.ToLower().Trim());
if (twineUser != null && bug.AssignedTo != null)
{
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs
index 759bcb4d5..6e1ec93a6 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Connection/DefaultMachineProvider.cs
@@ -347,8 +347,9 @@ namespace Tango.FSE.UI.Connection
/// </summary>
/// <param name="beginDelay">The amount of time to wait before starting reconnection attempts.</param>
/// <param name="timeout">The timeout for when to drop the reconnection attempt.</param>
+ /// <param name="message">The message to display to the user</param>
/// <returns></returns>
- public async Task DisconnectAndWaitForReconnection(TimeSpan beginDelay, TimeSpan timeout)
+ public async Task DisconnectAndWaitForReconnection(TimeSpan beginDelay, TimeSpan timeout, String message = null)
{
LogManager.Log("Starting disconnect and wait for machine procedure...");
LogManager.Log("Disconnecting from current machine...");
@@ -371,7 +372,7 @@ namespace Tango.FSE.UI.Connection
}
bool aborted = false;
- MachineWaitForConnectionViewVM vm = new MachineWaitForConnectionViewVM(MachineOperator, (int)timeout.TotalSeconds);
+ MachineWaitForConnectionViewVM vm = new MachineWaitForConnectionViewVM(MachineOperator, (int)timeout.TotalSeconds, message);
ThreadFactory.StartNew(() =>
{
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionLostViewVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionLostViewVM.cs
index dc08c87d1..b21c3788e 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionLostViewVM.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineConnectionLostViewVM.cs
@@ -91,11 +91,14 @@ namespace Tango.FSE.UI.Dialogs
private void _timer_Tick(object sender, EventArgs e)
{
- RemainingSeconds--;
-
- if (RemainingSeconds == 0)
+ if (IsVisible)
{
- Accept();
+ RemainingSeconds--;
+
+ if (RemainingSeconds == 0)
+ {
+ Accept();
+ }
}
}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineWaitForConnectionView.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineWaitForConnectionView.xaml
index 802b229f0..9c83de67c 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineWaitForConnectionView.xaml
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineWaitForConnectionView.xaml
@@ -29,7 +29,7 @@
<StackPanel DockPanel.Dock="Top" Margin="0 10 0 0">
<TextBlock TextWrapping="Wrap" LineHeight="24">
- <Run>The connection with the machine had been lost due to a controlled disconnection.</Run>
+ <Run Text="{Binding Message}"></Run>
<LineBreak/>
<Run>This dialog will close as soon as the connection reestablishes.</Run>
</TextBlock>
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineWaitForConnectionViewVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineWaitForConnectionViewVM.cs
index 6b1dbb0b2..8d22720c2 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineWaitForConnectionViewVM.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Dialogs/MachineWaitForConnectionViewVM.cs
@@ -32,13 +32,31 @@ namespace Tango.FSE.UI.Dialogs
set { _remainingSeconds = value; RaisePropertyChangedAuto(); }
}
+ private String _message;
+ /// <summary>
+ /// Gets or sets the message.
+ /// </summary>
+ public String Message
+ {
+ get { return _message; }
+ set { _message = value; RaisePropertyChangedAuto(); }
+ }
+
+
/// <summary>
/// Initializes a new instance of the <see cref="MachineWaitForConnectionViewVM"/> class.
/// </summary>
/// <param name="machine">The machine.</param>
/// <param name="autoReconnectTimeout">The automatic reconnect timeout in seconds.</param>
- public MachineWaitForConnectionViewVM(IExternalBridgeClient machine, int autoReconnectTimeout)
+ public MachineWaitForConnectionViewVM(IExternalBridgeClient machine, int autoReconnectTimeout, String message = null)
{
+ Message = message;
+
+ if (Message == null)
+ {
+ Message = "The connection with the machine had been lost due to a controlled disconnection.";
+ }
+
AutoMode = true;
OKText = "CANCEL";
CanClose = false;
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/FSEApplication/DefaultFSEApplicationManager.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/FSEApplication/DefaultFSEApplicationManager.cs
index 1c1a7ae00..aa5d4a629 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/FSEApplication/DefaultFSEApplicationManager.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/FSEApplication/DefaultFSEApplicationManager.cs
@@ -26,6 +26,7 @@ using Tango.FSE.Common.Navigation;
using Tango.FSE.Common.FSEApplication;
using Tango.FSE.Common.Authentication;
using Tango.FSE.BL;
+using Tango.FSE.Common.BugReporting;
namespace Tango.FSE.UI.FSEApplication
{
@@ -359,6 +360,12 @@ namespace Tango.FSE.UI.FSEApplication
LogManager.Log($"Invoking {instance.GetType().Name}.OnApplicationReady...");
instance.OnApplicationReady(this);
}
+
+ //Check if application started after a crash.
+ if (App.IsStartedAfterCrash)
+ {
+ _notificationProvider.PushErrorReportingSnackbar(new ApplicationStartedAfterCrashException(App.StartedAfterCrashError), "Application Terminated Unexpectedly", "Tango FSE was terminated unexpectedly in the previous run.");
+ }
});
}
@@ -384,6 +391,8 @@ namespace Tango.FSE.UI.FSEApplication
try
{
+ var settings = SettingsManager.Default.GetOrCreate<FSESettings>();
+ settings.TerminatedExpectedly = true;
SettingsManager.Default.Save();
}
catch { }
@@ -448,5 +457,16 @@ namespace Tango.FSE.UI.FSEApplication
return StartupArgs.Contains("-demo");
}
}
+
+ /// <summary>
+ /// Activates the main window if it's not in focus.
+ /// </summary>
+ public void ActivateMainWindow()
+ {
+ MainWindow.Instance.Dispatcher.BeginInvoke(new Action(() =>
+ {
+ MainWindow.Instance.Activate();
+ }));
+ }
}
}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/FileAssociation/DefaultFileAssociationProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/FileAssociation/DefaultFileAssociationProvider.cs
new file mode 100644
index 000000000..9e2997e92
--- /dev/null
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/FileAssociation/DefaultFileAssociationProvider.cs
@@ -0,0 +1,136 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Core.DI;
+using Tango.FSE.Common;
+using Tango.FSE.Common.FileAssociation;
+using Tango.FSE.Common.FSEApplication;
+using Tango.FSE.Common.Threading;
+using Tango.Logging;
+using ZetaIpc.Runtime.Server;
+
+namespace Tango.FSE.UI.FileAssociation
+{
+ [TangoCreateWhenRegistered]
+ public class DefaultFileAssociationProvider : FSEExtendedObject, IFileAssociationProvider
+ {
+ private Dictionary<String, Action<FileAssociationPackage>> _handlers;
+ private IpcServer _ipcServer;
+
+ public const string FILE_ASSOCIATION_PREFIX = "-file";
+ public const int FILE_ASSOCIATION_ARGS_COUNT = 3;
+
+ public bool HasStartArgsPackage { get; private set; }
+
+ [TangoInject]
+ private IDispatcherProvider DispatcherProvider { get; set; }
+
+ [TangoInject]
+ private IFSEApplicationManager ApplicationManager { get; set; }
+
+ public DefaultFileAssociationProvider()
+ {
+ _handlers = new Dictionary<string, Action<FileAssociationPackage>>();
+ _ipcServer = new IpcServer();
+ }
+
+ public void RegisterFileAssociationHandler(string targetName, Action<FileAssociationPackage> handler)
+ {
+ _handlers.Add(targetName.ToLower(), handler);
+ }
+
+ public async void OnApplicationReady(IFSEApplicationManager applicationManager)
+ {
+ try
+ {
+ LogManager.Log("Starting file association IPC service...");
+ _ipcServer.Start(Settings.FileAssociationServicePort);
+ _ipcServer.ReceivedRequest += _ipcServer_ReceivedRequest;
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error starting file association IPC service. Another instance of the application might already be running...");
+ }
+
+ var args = applicationManager.StartupArgs;
+
+ LogManager.Log("Processing file association if any...");
+
+ if (args.Count == FILE_ASSOCIATION_ARGS_COUNT)
+ {
+ if (args[0] == FILE_ASSOCIATION_PREFIX)
+ {
+
+ //This delay is a workaround for when the invoked handler navigates to some module.
+ //The navigation system does not catches the navigation request properly... :/
+ await Task.Delay(500);
+
+ LogManager.Log($"File association package found: '{String.Join(" ", args)}'. Invoking handler...");
+
+ try
+ {
+ String targetName = args[1].ToLower();
+
+ if (_handlers.ContainsKey(targetName))
+ {
+ var package = new FileAssociationPackage()
+ {
+ TargetName = targetName,
+ File = args[2]
+ };
+
+ _handlers[targetName].Invoke(package);
+ }
+ else
+ {
+ LogManager.Log("File association handler not found.", LogCategory.Warning);
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, $"Error invoking file association handler for package '{String.Join(" ", args)}'.");
+ }
+ }
+ }
+ }
+
+ private void _ipcServer_ReceivedRequest(object sender, ReceivedRequestEventArgs e)
+ {
+ try
+ {
+ e.Handled = true;
+ LogManager.Log($"File association package received through IPC server.\n{e.Request}\nInvoking handler...");
+
+ var package = JsonConvert.DeserializeObject<FileAssociationPackage>(e.Request);
+
+ if (_handlers.ContainsKey(package.TargetName.ToLower()))
+ {
+ DispatcherProvider.Invoke(() =>
+ {
+ ApplicationManager.ActivateMainWindow();
+ _handlers[package.TargetName.ToLower()].Invoke(package);
+ });
+ }
+ else
+ {
+ LogManager.Log($"Handler not found for target '{package.TargetName}'.", LogCategory.Warning);
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, $"Error invoking file association handler.");
+ }
+ }
+
+ public void OnApplicationStarted(IFSEApplicationManager applicationManager)
+ {
+ HasStartArgsPackage =
+ applicationManager.StartupArgs.Count == FILE_ASSOCIATION_ARGS_COUNT
+ &&
+ applicationManager.StartupArgs[0] == FILE_ASSOCIATION_PREFIX;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs
index b623200d8..6673a5ae3 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/FileSystem/DefaultFileSystemProvider.cs
@@ -554,11 +554,19 @@ namespace Tango.FSE.UI.FileSystem
/// </summary>
/// <param name="localSourcePath">The local source path.</param>
/// <param name="remotePath">The remote destination path.</param>
+ /// <param name="forRemoteUpgrade">Indicates whether this upload operation is performed for a remote upgrade.</param>
/// <returns></returns>
- /// <exception cref="System.IO.FileNotFoundException">Could not locate the local file or directory to upload.</exception>
- public Task<FileSystemHandler> Upload(String localSourcePath, String remotePath)
+ /// <exception cref="FileNotFoundException">Could not locate the local file or directory to upload.</exception>
+ public Task<FileSystemHandler> Upload(String localSourcePath, String remotePath, bool forRemoteUpgrade = false)
{
- AuthenticationProvider.ThrowIfNoPermission(Permissions.FSE_PPCFileSystemWrite);
+ if (!forRemoteUpgrade)
+ {
+ AuthenticationProvider.ThrowIfNoPermission(Permissions.FSE_PPCFileSystemWrite);
+ }
+ else
+ {
+ AuthenticationProvider.ThrowIfNoPermission(Permissions.FSE_RemoteUpgradeOnline);
+ }
String operationId = String.Empty;
String destination = remotePath;
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Navigation/DefaultNavigationManager.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Navigation/DefaultNavigationManager.cs
index 9de496793..7a55b085a 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Navigation/DefaultNavigationManager.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Navigation/DefaultNavigationManager.cs
@@ -44,6 +44,7 @@ namespace Tango.FSE.UI.Navigation
private Object _currentVM;
private String _lastFullPath;
private bool _preventHistory;
+ private bool _force;
private Stack<String> _navigationHistory;
@@ -242,7 +243,7 @@ namespace Tango.FSE.UI.Navigation
{
try
{
- if (_lastFullPath == fullPath)
+ if (_lastFullPath == fullPath && !_force)
{
return true;
}
@@ -450,12 +451,15 @@ namespace Tango.FSE.UI.Navigation
/// <typeparam name="TView">The type of the view.</typeparam>
/// <typeparam name="TPass">The type of the pass.</typeparam>
/// <param name="obj">The object.</param>
- /// <param name="pushToHistory">if set to <c>true</c> [push to history].</param>
+ /// <param name="pushToHistory">Push the current view to history ?.</param>
+ /// <param name="force">Force the navigation even if we are on the same view.</param>
/// <returns></returns>
- public Task<bool> NavigateWithObject<TModule, TView, TPass>(TPass obj, bool pushToHistory = true) where TModule : IFSEModule
+ public Task<bool> NavigateWithObject<TModule, TView, TPass>(TPass obj, bool pushToHistory = true, bool force = false) where TModule : IFSEModule
{
+ _force = true;
return NavigateTo(typeof(TModule).Name + "." + typeof(TView).Name, pushToHistory, (fromVM, toVM) =>
{
+ _force = false;
if (toVM is INavigationObjectReceiver<TPass>)
{
(toVM as INavigationObjectReceiver<TPass>).OnNavigatedToWithObject(obj);
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/LogViewerPane.xaml b/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/LogViewerPane.xaml
index 0e2b67068..017091bc4 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/LogViewerPane.xaml
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/LogViewerPane.xaml
@@ -51,7 +51,7 @@
</DataTrigger>
</Style.Triggers>
</Style>
- </RowDefinition.Style>
+ </RowDefinition.Style>
</RowDefinition>
<RowDefinition Height="0" MaxHeight="{Binding ElementName=grid,Path=ActualHeight}"/>
</Grid.RowDefinitions>
@@ -166,57 +166,57 @@
<GridSplitter Grid.Row="1" Height="5" VerticalAlignment="Center" HorizontalAlignment="Stretch" />
- <Grid Grid.Row="2" Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}">
- <DockPanel Margin="10">
- <Grid DockPanel.Dock="Top" Margin="55 5 0 0" Panel.ZIndex="100">
- <TextBlock Foreground="{StaticResource FSE_PrimaryAccentBrush}" FontWeight="SemiBold">FSE LOGS</TextBlock>
- <StackPanel Margin="0 0 0 -70" HorizontalAlignment="Right" >
- <StackPanel Margin="8 0 0 0" HorizontalAlignment="Left" Orientation="Horizontal">
- <controls:ToggleIconButton ToolTip="Pause/Resume FSE logs" CheckedIcon="Play" UncheckedIcon="Pause" Width="24" Height="24" IsChecked="{Binding FSELogsPaused}" />
- <controls:IconButton Icon="CircleArrows" ToolTip="Clear FSE logs" Width="24" Height="24" Command="{Binding ClearFSELogsCommand}" />
- </StackPanel>
- <StackPanel Margin="0 8 0 0" Orientation="Horizontal">
- <ItemsControl VerticalAlignment="Center" ItemsSource="{Binding SelectedFSELogsCategories}">
- <ItemsControl.ItemsPanel>
- <ItemsPanelTemplate>
- <StackPanel Orientation="Horizontal" />
- </ItemsPanelTemplate>
- </ItemsControl.ItemsPanel>
- <ItemsControl.ItemTemplate>
- <DataTemplate>
- <StackPanel Orientation="Horizontal" Margin="10 0 0 0">
- <CheckBox FocusVisualStyle="{x:Null}" IsChecked="{Binding IsSelected,Delay=200}" VerticalAlignment="Center">
- <CheckBox.Content>
- <TextBlock Text="{Binding Data}" VerticalAlignment="Center"></TextBlock>
- </CheckBox.Content>
- </CheckBox>
- </StackPanel>
- </DataTemplate>
- </ItemsControl.ItemTemplate>
- </ItemsControl>
+ <Grid Grid.Row="2" Background="{StaticResource FSE_PrimaryBackgroundDarkBrush}" Visibility="{Binding HasFSELogsPermission,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <DockPanel Margin="10">
+ <Grid DockPanel.Dock="Top" Margin="55 5 0 0" Panel.ZIndex="100">
+ <TextBlock Foreground="{StaticResource FSE_PrimaryAccentBrush}" FontWeight="SemiBold">FSE LOGS</TextBlock>
+ <StackPanel Margin="0 0 0 -70" HorizontalAlignment="Right" >
+ <StackPanel Margin="8 0 0 0" HorizontalAlignment="Left" Orientation="Horizontal">
+ <controls:ToggleIconButton ToolTip="Pause/Resume FSE logs" CheckedIcon="Play" UncheckedIcon="Pause" Width="24" Height="24" IsChecked="{Binding FSELogsPaused}" />
+ <controls:IconButton Icon="CircleArrows" ToolTip="Clear FSE logs" Width="24" Height="24" Command="{Binding ClearFSELogsCommand}" />
+ </StackPanel>
+ <StackPanel Margin="0 8 0 0" Orientation="Horizontal">
+ <ItemsControl VerticalAlignment="Center" ItemsSource="{Binding SelectedFSELogsCategories}">
+ <ItemsControl.ItemsPanel>
+ <ItemsPanelTemplate>
+ <StackPanel Orientation="Horizontal" />
+ </ItemsPanelTemplate>
+ </ItemsControl.ItemsPanel>
+ <ItemsControl.ItemTemplate>
+ <DataTemplate>
+ <StackPanel Orientation="Horizontal" Margin="10 0 0 0">
+ <CheckBox FocusVisualStyle="{x:Null}" IsChecked="{Binding IsSelected,Delay=200}" VerticalAlignment="Center">
+ <CheckBox.Content>
+ <TextBlock Text="{Binding Data}" VerticalAlignment="Center"></TextBlock>
+ </CheckBox.Content>
+ </CheckBox>
+ </StackPanel>
+ </DataTemplate>
+ </ItemsControl.ItemTemplate>
+ </ItemsControl>
- <DockPanel Margin="20 0 0 0" VerticalAlignment="Center">
- <material:PackIcon Kind="Search" VerticalAlignment="Center" Width="18" Height="18" />
- <TextBox Margin="5 0 0 0" Style="{StaticResource FSE_Rounded_Corners_TextBox}" Background="{StaticResource FSE_PrimaryBackgroundBrush}" FontSize="{StaticResource FSE_SmallFontSize}" material:HintAssist.Hint="filter" material:TextFieldAssist.RippleOnFocusEnabled="True" Text="{Binding FSELogsFilter,UpdateSourceTrigger=PropertyChanged,Delay=1000}" Width="200"/>
- </DockPanel>
+ <DockPanel Margin="20 0 0 0" VerticalAlignment="Center">
+ <material:PackIcon Kind="Search" VerticalAlignment="Center" Width="18" Height="18" />
+ <TextBox Margin="5 0 0 0" Style="{StaticResource FSE_Rounded_Corners_TextBox}" Background="{StaticResource FSE_PrimaryBackgroundBrush}" FontSize="{StaticResource FSE_SmallFontSize}" material:HintAssist.Hint="filter" material:TextFieldAssist.RippleOnFocusEnabled="True" Text="{Binding FSELogsFilter,UpdateSourceTrigger=PropertyChanged,Delay=1000}" Width="200"/>
+ </DockPanel>
+ </StackPanel>
</StackPanel>
- </StackPanel>
- </Grid>
+ </Grid>
- <DataGrid Margin="0 5 0 0" Style="{StaticResource LogsGridStyle}" ItemsSource="{Binding FSELogs}" CellStyle="{StaticResource LogsGridCellStyle}" helpers:DataGridHelper.DoubleClickCommand="{Binding OpenFSELogItemCommand}">
- <DataGrid.Columns>
- <DataGridTemplateColumn Header="#" Width="40" CellTemplate="{StaticResource FSE_LogIcon_Cell}"/>
- <DataGridTextColumn Header="DATE TIME" Binding="{Binding TimeStamp,StringFormat='HH:mm:ss.ff'}" Width="100" />
- <DataGridTemplateColumn Header="MESSAGE" Width="1*" >
- <DataGridTemplateColumn.CellTemplate>
- <DataTemplate>
- <TextBlock Text="{Binding Message,Converter={StaticResource StringToOneLineConverter},ConverterParameter='120'}"></TextBlock>
- </DataTemplate>
- </DataGridTemplateColumn.CellTemplate>
- </DataGridTemplateColumn>
- </DataGrid.Columns>
- </DataGrid>
- </DockPanel>
+ <DataGrid Margin="0 5 0 0" Style="{StaticResource LogsGridStyle}" ItemsSource="{Binding FSELogs}" CellStyle="{StaticResource LogsGridCellStyle}" helpers:DataGridHelper.DoubleClickCommand="{Binding OpenFSELogItemCommand}">
+ <DataGrid.Columns>
+ <DataGridTemplateColumn Header="#" Width="40" CellTemplate="{StaticResource FSE_LogIcon_Cell}"/>
+ <DataGridTextColumn Header="DATE TIME" Binding="{Binding TimeStamp,StringFormat='HH:mm:ss.ff'}" Width="100" />
+ <DataGridTemplateColumn Header="MESSAGE" Width="1*" >
+ <DataGridTemplateColumn.CellTemplate>
+ <DataTemplate>
+ <TextBlock Text="{Binding Message,Converter={StaticResource StringToOneLineConverter},ConverterParameter='120'}"></TextBlock>
+ </DataTemplate>
+ </DataGridTemplateColumn.CellTemplate>
+ </DataGridTemplateColumn>
+ </DataGrid.Columns>
+ </DataGrid>
+ </DockPanel>
</Grid>
</Grid>
</UserControl>
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/LogViewerPaneVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/LogViewerPaneVM.cs
index 050b17dcc..2add8f473 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/LogViewerPaneVM.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/LogViewerPaneVM.cs
@@ -12,6 +12,7 @@ using Tango.Core.DI;
using Tango.FSE.Common;
using Tango.FSE.Common.Connection;
using Tango.FSE.Common.Dialogs;
+using Tango.FSE.Common.Helpers;
using Tango.Integration.Logging;
using Tango.Logging;
using Tango.SharedUI.Components;
@@ -232,6 +233,13 @@ namespace Tango.FSE.UI.Panes
TangoIOC.Default.Inject(this);
+ var appStartLogs = LogsHelper.GetLogSafe().EmptyAndDispose();
+
+ foreach (var log in appStartLogs)
+ {
+ FSELogs.Insert(0, log);
+ }
+
LoggingProvider.FSELogAvailable += LoggingProvider_FSELogAvailable;
LoggingProvider.ApplicationLogAvailable += LoggingProvider_ApplicationLogAvailable;
LoggingProvider.FirmwareLogAvailable += LoggingProvider_FirmwareLogAvailable;
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/MachineConnectionPaneVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/MachineConnectionPaneVM.cs
index cced594ea..dbd7819e8 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/MachineConnectionPaneVM.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Panes/MachineConnectionPaneVM.cs
@@ -173,17 +173,52 @@ namespace Tango.FSE.UI.Panes
InvokeUI(() =>
{
+ bool insert = false;
+
+ try
+ {
+ if (Settings.LastSelectedMachine != null)
+ {
+ if (machine.GetUniqueString() == Settings.LastSelectedMachine)
+ {
+ insert = true;
+ }
+ }
+ }
+ catch { }
+
if (machine is ExternalBridgeUsbClient)
{
- UsbMachines.Add(machine as ExternalBridgeUsbClient);
+ if (insert)
+ {
+ UsbMachines.Insert(0, machine as ExternalBridgeUsbClient);
+ }
+ else
+ {
+ UsbMachines.Add(machine as ExternalBridgeUsbClient);
+ }
}
else if (machine is ExternalBridgeSignalRClient)
{
- SignalRMachines.Add(machine as ExternalBridgeSignalRClient);
+ if (insert)
+ {
+ SignalRMachines.Insert(0, machine as ExternalBridgeSignalRClient);
+ }
+ else
+ {
+ SignalRMachines.Add(machine as ExternalBridgeSignalRClient);
+ }
}
else if (machine is ExternalBridgeTcpClient)
{
- TcpMachines.Add(machine as ExternalBridgeTcpClient);
+ if (insert)
+ {
+ TcpMachines.Insert(0, machine as ExternalBridgeTcpClient);
+ }
+ else
+ {
+ TcpMachines.Add(machine as ExternalBridgeTcpClient);
+ }
}
TryAutoSelectMachine();
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Properties/AssemblyInfo.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Properties/AssemblyInfo.cs
index 40af7d9f8..94653d0b5 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Properties/AssemblyInfo.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Properties/AssemblyInfo.cs
@@ -8,5 +8,5 @@ using System.Windows;
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Tango FSE")]
-[assembly: AssemblyVersion("1.0.7.0")]
+[assembly: AssemblyVersion("1.0.8.0")]
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/SQL/DefaultRemoteSqlProvider.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/SQL/DefaultRemoteSqlProvider.cs
index feac992b3..a657ad55e 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/SQL/DefaultRemoteSqlProvider.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/SQL/DefaultRemoteSqlProvider.cs
@@ -159,7 +159,7 @@ namespace Tango.FSE.UI.SQL
SqlDataReader reader = await cmd.ExecuteReaderAsync();
result.GlobalAffectedRecords = reader.RecordsAffected;
- result.GLobalDataSet = await RemoteSqlDataSet.Load(reader);
+ result.GlobalDataSet = await RemoteSqlDataSet.Load(reader);
}
}
}
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj
index 5c6885c2e..3d5fa6db1 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tango.FSE.UI.csproj
@@ -200,6 +200,9 @@
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="WindowsFormsIntegration" />
+ <Reference Include="ZetaIpc, Version=1.0.0.9, Culture=neutral, PublicKeyToken=6c27b71344e0b736, processorArchitecture=MSIL">
+ <HintPath>..\..\packages\ZetaIpc.1.0.0.9\lib\netstandard2.0\ZetaIpc.dll</HintPath>
+ </Reference>
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
@@ -271,6 +274,7 @@
<Compile Include="Dialogs\MachineConnectionSignalRViewVM.cs" />
<Compile Include="Dialogs\MachineConnectionWifiViewVM.cs" />
<Compile Include="Events\DefaultEventsProvider.cs" />
+ <Compile Include="FileAssociation\DefaultFileAssociationProvider.cs" />
<Compile Include="FileSystem\DefaultFileSystemProvider.cs" />
<Compile Include="Firmware\DefaultFirmwareStorageProvider.cs" />
<Compile Include="InternalModule.cs" />
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tiles/RemoteJob/RemoteJobTile.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tiles/RemoteJob/RemoteJobTile.cs
index cb99ef6ca..b0a563ebd 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/Tiles/RemoteJob/RemoteJobTile.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/Tiles/RemoteJob/RemoteJobTile.cs
@@ -58,6 +58,7 @@ namespace Tango.FSE.UI.Tiles.RemoteJob
private void InitDemoJob()
{
+ IsRunning = false;
Job = new Job();
Job.NumberOfUnits = 1;
Job.Name = "N/A";
@@ -88,6 +89,12 @@ namespace Tango.FSE.UI.Tiles.RemoteJob
RemoteJobProvider.RemoteJobStarted += RemoteJobProvider_RemoteJobStarted;
RemoteJobProvider.RemoteJobStopped += RemoteJobProvider_RemoteJobStopped;
+ MachineProvider.MachineConnected += MachineProvider_MachineConnected;
+ }
+
+ private void MachineProvider_MachineConnected(object sender, Common.Connection.MachineConnectedEventArgs e)
+ {
+ InitDemoJob();
}
private void RemoteJobProvider_RemoteJobStopped(object sender, Common.RemoteJob.RemoteJobStoppedEventArgs e)
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs
index 13520ec7e..25d0b45c9 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModelLocator.cs
@@ -64,6 +64,8 @@ using Tango.FSE.Common.DemoMode;
using Tango.FSE.UI.DemoMode;
using Tango.FSE.Common.SQL;
using Tango.FSE.UI.SQL;
+using Tango.FSE.Common.FileAssociation;
+using Tango.FSE.UI.FileAssociation;
namespace Tango.FSE.UI
{
@@ -101,6 +103,7 @@ namespace Tango.FSE.UI
TangoIOC.Default.Unregister<IWindowsManager>();
TangoIOC.Default.Unregister<IDemoModeManager>();
TangoIOC.Default.Unregister<IRemoteSqlProvider>();
+ TangoIOC.Default.Unregister<IFileAssociationProvider>();
//TangoIOC.Default.Unregister<ExternalBridgeScanner>();
//TangoIOC.Default.Unregister<IDiagnosticsFrameProvider>();
//TangoIOC.Default.Unregister<IEventLogger>();
@@ -138,6 +141,7 @@ namespace Tango.FSE.UI
TangoIOC.Default.Register<IWindowsManager, DefaultWindowsManager>();
TangoIOC.Default.Register<IDemoModeManager, DefaultDemoModeManager>();
TangoIOC.Default.Register<IRemoteSqlProvider, DefaultRemoteSqlProvider>();
+ TangoIOC.Default.Register<IFileAssociationProvider, DefaultFileAssociationProvider>();
TangoIOC.Default.Register<MainWindowVM>();
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs
index 5c4f1b11a..9a5433f82 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/ViewModels/LoginViewVM.cs
@@ -232,6 +232,14 @@ namespace Tango.FSE.UI.ViewModels
{
this.SetFocus(() => Password);
}
+
+ if (RememberMe)
+ {
+ if (FileAssociationProvider.HasStartArgsPackage)
+ {
+ Login();
+ }
+ }
}
/// <summary>
diff --git a/Software/Visual_Studio/FSE/Tango.FSE.UI/packages.config b/Software/Visual_Studio/FSE/Tango.FSE.UI/packages.config
index d0abb0ebf..4fda0a885 100644
--- a/Software/Visual_Studio/FSE/Tango.FSE.UI/packages.config
+++ b/Software/Visual_Studio/FSE/Tango.FSE.UI/packages.config
@@ -68,4 +68,5 @@
<package id="System.Xml.XPath.XDocument" version="4.3.0" targetFramework="net461" />
<package id="WindowsAPICodePack-Core" version="1.1.1" targetFramework="net461" />
<package id="WindowsAPICodePack-Shell" version="1.1.1" targetFramework="net461" />
+ <package id="ZetaIpc" version="1.0.0.9" targetFramework="net461" />
</packages> \ No newline at end of file
diff --git a/Software/Visual_Studio/Installers/Sandcastle/SHFBInstaller_v2020.3.6.0.zip b/Software/Visual_Studio/Installers/Sandcastle/SHFBInstaller_v2020.3.6.0.zip
new file mode 100644
index 000000000..c8f91b5e1
--- /dev/null
+++ b/Software/Visual_Studio/Installers/Sandcastle/SHFBInstaller_v2020.3.6.0.zip
Binary files differ
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/Views/MainView.xaml
index e2d65d7a3..40e282712 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/Views/MainView.xaml
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ActionLogs/Views/MainView.xaml
@@ -4,14 +4,14 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls"
- xmlns:local="clr-namespace:Tango.MachineStudio.ActionLogs.Views"
+ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:sharedConverters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI"
xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI"
xmlns:vm="clr-namespace:Tango.MachineStudio.ActionLogs.ViewModels"
xmlns:global="clr-namespace:Tango.MachineStudio.ActionLogs"
- xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:wpf="clr-namespace:MaterialDesignThemes.Wpf;assembly=MaterialDesignThemes.Wpf"
xmlns:diff="clr-namespace:Tango.BL.ValueObjects;assembly=Tango.BL"
+ xmlns:local="clr-namespace:Tango.MachineStudio.ActionLogs.Views"
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}">
<UserControl.Resources>
@@ -60,7 +60,7 @@
</StackPanel>
<DockPanel Margin="50 0 0 0" >
<TextBlock DockPanel.Dock="Top" Text="Action Log Type:" VerticalAlignment="Center" FontSize="10"></TextBlock>
- <ToggleButton Width="200" Margin="0 5 0 0" x:Name="selectActionsButton">
+ <ToggleButton Width="200" Margin="0 5 0 0" x:Name="selectActionsButton" >
<ToggleButton.Template>
<ControlTemplate>
<Grid>
@@ -75,21 +75,16 @@
</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 SelectedActionLogTypes}" 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,Converter={StaticResource EnumToDescriptionConverter}}"></TextBlock>
- </CheckBox>
- </DockPanel>
- </DataTemplate>
- </ItemsControl.ItemTemplate>
- </ItemsControl>
- </ScrollViewer>
+ <Popup StaysOpen="False" IsOpen="{Binding RelativeSource={RelativeSource AncestorType=ToggleButton},Path=IsChecked }" Style="{x:Null}">
+ <Border Padding="5" MaxHeight="600" Background="{DynamicResource ComboBox.Floating.Background}" BorderBrush="{StaticResource AutoCompleteTextBox.Popup.BorderBrush}" MinWidth="{Binding RelativeSource={RelativeSource AncestorType=ToggleButton},Path=ActualWidth}">
+ <controls:AllSelectedCheckboxList Style="{StaticResource AllSelectedCheckBoxListStyle}" MaxHeight="600" ItemsSource="{Binding SelectedActionLogTypes}" Foreground="{StaticResource MainWindow.Foreground}" Background="{DynamicResource ComboBox.Floating.Background}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" SelectionMode="Multiple" AllSelected="True" >
+ <controls:AllSelectedCheckboxList.ItemTemplate>
+ <DataTemplate >
+ <TextBlock Margin="5 0 0 0" VerticalAlignment="Center" Text="{Binding Data,Converter={StaticResource EnumToDescriptionConverter}}"/>
+
+ </DataTemplate>
+ </controls:AllSelectedCheckboxList.ItemTemplate>
+ </controls:AllSelectedCheckboxList>
</Border>
</Popup>
</Grid>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Tango.MachineStudio.ColorCapture.csproj b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Tango.MachineStudio.ColorCapture.csproj
index 8f37a9c2d..4e6feceb5 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Tango.MachineStudio.ColorCapture.csproj
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorCapture/Tango.MachineStudio.ColorCapture.csproj
@@ -18,7 +18,7 @@
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
- <OutputPath>..\..\..\Build\Machine Studio\Debug\</OutputPath>
+ <OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
@@ -26,7 +26,7 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
- <OutputPath>..\..\..\Build\Machine Studio\Release\</OutputPath>
+ <OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/JobView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/JobView.xaml
index 5b29fd432..073ba827f 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/JobView.xaml
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/JobView.xaml
@@ -756,7 +756,7 @@
<StackPanel>
<TextBlock>MEDIA</TextBlock>
<StackPanel Orientation="Horizontal" DockPanel.Dock="Left">
- <controls:SearchComboBox Width="250" ItemsSource="{Binding Rmls}" SelectedItem="{Binding SelectedRML}" HorizontalContentAlignment="Stretch" SearchParam="Name">
+ <controls:SearchComboBox Width="250" ItemsSource="{Binding Rmls}" SelectedItem="{Binding SelectedRML}" HorizontalContentAlignment="Stretch" SearchProperty="Name">
<ComboBox.ItemTemplate>
<DataTemplate>
<DockPanel>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/MachineJobSelectionView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/MachineJobSelectionView.xaml
index bf626f462..1bbcfb8fe 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/MachineJobSelectionView.xaml
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Views/MachineJobSelectionView.xaml
@@ -190,7 +190,7 @@
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
- <DataGridTemplateColumn Header="CREATED BY" Width="100" CanUserSort="True" SortMemberPath="User">
+ <DataGridTemplateColumn Header="CREATED BY" Width="100" CanUserSort="True" SortMemberPath="User.Contact.FirstName">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding User.Contact.FirstName}" VerticalAlignment="Center" FontSize="14"></TextBlock>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.HardwareDesigner/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.HardwareDesigner/Views/MainView.xaml
index 1c00397aa..9ee2ffee7 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.HardwareDesigner/Views/MainView.xaml
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.HardwareDesigner/Views/MainView.xaml
@@ -9,6 +9,7 @@
xmlns:editors="clr-namespace:Tango.SharedUI.Editors;assembly=Tango.SharedUI"
xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI"
xmlns:entities="clr-namespace:Tango.BL.Entities;assembly=Tango.BL"
+ xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI"
xmlns:local="clr-namespace:Tango.MachineStudio.HardwareDesigner.Views"
xmlns:vm="clr-namespace:Tango.MachineStudio.HardwareDesigner.ViewModels"
xmlns:observables="clr-namespace:Tango.BL.Entities;assembly=Tango.BL"
@@ -57,14 +58,14 @@
<TextBlock FontSize="30" FontStyle="Italic" VerticalAlignment="Center" Margin="50 10 10 0" Foreground="Silver" FontWeight="Bold">HARDWARE DESIGNER</TextBlock>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="10 10 0 0">
<materialDesign:PackIcon Kind="Pencil" Width="32" Height="32" Foreground="Silver" />
- <ComboBox IsEnabled="{Binding IsFree}" ItemsSource="{Binding HardwareVersions}" SelectedItem="{Binding SelectedVersion}" Width="300" FontSize="16" FontWeight="Bold" Margin="5 0 0 0" materialDesign:HintAssist.Hint="Hardware Version">
+ <controls:SearchComboBox IsEnabled="{Binding IsFree}" ItemsSource="{Binding HardwareVersions}" SelectedItem="{Binding SelectedVersion}" Width="300" SearchProperty="FullName" FontSize="16" FontWeight="Bold" Margin="5 0 0 0" materialDesign:HintAssist.Hint="Hardware Version">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock><Run Text="{Binding Name}"></Run> <Run></Run> <Run Foreground="{StaticResource MainWindow.Foreground}" FontSize="14">v</Run><Run Foreground="{StaticResource MainWindow.Foreground}" FontSize="14" Text="{Binding Version}"></Run></TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
- </ComboBox>
-
+ </controls:SearchComboBox>
+
</StackPanel>
<Button Margin="100 10 0 0" Cursor="Hand" Height="40" FontSize="12" ToolTip="Open Comparison Wizard" Command="{Binding OpenComparisonWizardCommand}">
<StackPanel Orientation="Horizontal">
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/MainViewVM.cs
index 229d62df7..cbb171cd6 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/MainViewVM.cs
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/ViewModels/MainViewVM.cs
@@ -314,8 +314,7 @@ namespace Tango.MachineStudio.RML.ViewModels
{
Rml r = rml as Rml;
return String.IsNullOrWhiteSpace(RMLFilter)
- || r.Name.ToLower().Contains(RMLFilter.ToLower()) //Rml name
- || (r.MediaMaterial != null && r.MediaMaterial.Name.ToLower().Contains(RMLFilter.ToLower()));
+ || r.Name.ToLower().Contains(RMLFilter.ToLower());
};
}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlsView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlsView.xaml
index 18af6bed5..7c7194554 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlsView.xaml
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.RML/Views/RmlsView.xaml
@@ -24,7 +24,7 @@
<Image Source="../Images/threads.png" Width="300" Margin="10" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0 0 10 30">
<materialDesign:PackIcon Kind="Magnify" Width="26" Height="26"/>
- <TextBox Width="300" materialDesign:HintAssist.Hint="Search name, material,..." Text="{Binding RMLFilter,UpdateSourceTrigger=PropertyChanged}"></TextBox>
+ <TextBox Width="300" materialDesign:HintAssist.Hint="Search by name" Text="{Binding RMLFilter,UpdateSourceTrigger=PropertyChanged,Delay=500}"></TextBox>
</StackPanel>
</Grid>
<Grid DockPanel.Dock="Bottom">
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 23b7c594c..4ce0ea87d 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
@@ -78,7 +78,6 @@
<ItemGroup>
<Compile Include="Converters\CollectionConverter .cs" />
<Compile Include="Converters\DateTimeToStringFormatConverter.cs" />
- <Compile Include="Converters\HeadCleaningConverter.cs" />
<Compile Include="Converters\JobLengthConverter.cs" />
<Compile Include="Converters\LiquidQuantityToFormatStringConverter.cs" />
<Compile Include="Converters\LiquidTypeToColorConverter.cs" />
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
index 0ecb12ba7..ae1592d8d 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/JobRunsViewVM.cs
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/JobRunsViewVM.cs
@@ -23,9 +23,21 @@ using Tango.BL.ValueObjects;
using System.Diagnostics;
using Microsoft.Win32;
using Tango.CSV;
+using System.ComponentModel;
namespace Tango.MachineStudio.Statistics.ViewModels
{
+ public enum HeadCleaningSelectionEnum
+ {
+ [Description("Exclude")]
+ Exclude = 0,
+ [Description("Include")]
+ Include = 1,
+ [Description("Only")]
+ Only = 2
+ };
+
+
public class JobRunsViewVM : ViewModel
{
private INotificationProvider _notification;
@@ -33,6 +45,8 @@ namespace Tango.MachineStudio.Statistics.ViewModels
private List<User> _allUsers;
private List<RmlModel> _rmlsModels;
+
+
#region Properties
private ObservableCollection<JobRunModel> _jobRuns;
@@ -175,14 +189,14 @@ namespace Tango.MachineStudio.Statistics.ViewModels
}
}
- private SelectedObjectCollection<bool> _isHeadCleaningSelection;
+ private HeadCleaningSelectionEnum _headCleaningSelected;
- public SelectedObjectCollection<bool> IsHeadCleaningSelection
+ public HeadCleaningSelectionEnum HeadCleaningSelected
{
- get { return _isHeadCleaningSelection; }
+ get { return _headCleaningSelected; }
set
{
- _isHeadCleaningSelection = value;
+ _headCleaningSelected = value;
RaisePropertyChangedAuto();
}
}
@@ -270,17 +284,8 @@ namespace Tango.MachineStudio.Statistics.ViewModels
IsGradientSelection.SelectionChanged -= (x, y) => RaisePropertyChanged(nameof(IsGradientSelection));
IsGradientSelection.SelectionChanged += (x, y) => RaisePropertyChanged(nameof(IsGradientSelection));
- IsHeadCleaningSelection = new SelectedObjectCollection<bool>(new ObservableCollection<bool>()
- {
- true,
- false
- }, new ObservableCollection<bool>()
- {
- true,
- false
- });
- IsHeadCleaningSelection.SelectionChanged -= (x, y) => RaisePropertyChanged(nameof(IsHeadCleaningSelection));
- IsHeadCleaningSelection.SelectionChanged += (x, y) => RaisePropertyChanged(nameof(IsHeadCleaningSelection));
+ HeadCleaningSelected = HeadCleaningSelectionEnum.Exclude;
+
JobsProvider = new SuggestionProvider((filter) =>
{
try
@@ -336,8 +341,9 @@ namespace Tango.MachineStudio.Statistics.ViewModels
IsFree = true;
}
}
+
}
-
+
/// <summary>
/// Loads the job runs by filters.
/// </summary>
@@ -407,10 +413,11 @@ namespace Tango.MachineStudio.Statistics.ViewModels
{
db_JobRuns = db_JobRuns.Where(x => isGradientArr.Contains(x.IsGradient));
}
- bool[] isHeadCleaningArr = IsHeadCleaningSelection.SynchedSource.Select(x => (bool)x).ToArray();
- if(isHeadCleaningArr.Length > 0)
+
+ if(HeadCleaningSelected != HeadCleaningSelectionEnum.Include)
{
- db_JobRuns = db_JobRuns.Where(x => isHeadCleaningArr.Contains(x.IsHeadCleaning));
+ bool isHeadCleaning = HeadCleaningSelected == HeadCleaningSelectionEnum.Only;
+ db_JobRuns = db_JobRuns.Where(x => isHeadCleaning == x.IsHeadCleaning);
}
List<String> rmlGuids = SelectedThreads.SynchedSource.Select(y => y.Guid).ToList();
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
index 9e4a9603e..8724fcc2b 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/JobRunsView.xaml
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Views/JobRunsView.xaml
@@ -13,8 +13,10 @@
xmlns:tooltips="clr-namespace:Tango.MachineStudio.Statistics.Tooltips"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:enumerations="clr-namespace:Tango.BL.Enumerations;assembly=Tango.BL"
+ xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI"
xmlns:local="clr-namespace:Tango.MachineStudio.Statistics.Views"
xmlns:model="clr-namespace:Tango.MachineStudio.Statistics.Models"
+ xmlns:vs="clr-namespace:Tango.MachineStudio.Statistics.ViewModels"
xmlns:wellknowntypes="clr-namespace:Google.Protobuf.WellKnownTypes;assembly=Google.Protobuf"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="1800" Foreground="{StaticResource JobFieldForeground}">
@@ -33,7 +35,6 @@
<localConverters:NanoLiterToLiterFormatConverter x:Key="NanoLiterToLiterFormatConverter"/>
<localConverters:LiquidQuantityToFormatStringConverter x:Key="LiquidQuantityToFormatStringConverter"/>
<localConverters:TooltipLiquidQuantityFormatConverter x:Key="TooltipLiquidQuantityFormatConverter"/>
- <localConverters:HeadCleaningConverter x:Key="HeadCleaningConverter"/>
<ResourceDictionary x:Key="SelectAllTextBoxResource">
<Style TargetType="TextBox">
@@ -42,6 +43,12 @@
</Style>
</ResourceDictionary>
+ <ObjectDataProvider x:Key="HeadCleaning" MethodName="GetValues" ObjectType="{x:Type sys:Enum}">
+ <ObjectDataProvider.MethodParameters>
+ <x:Type TypeName="vs:HeadCleaningSelectionEnum"/>
+ </ObjectDataProvider.MethodParameters>
+ </ObjectDataProvider>
+
<Style TargetType="{x:Type TextBlock}" x:Key="WrapText">
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
@@ -55,7 +62,7 @@
<Setter Property="Background" Value="Transparent"/>
<Setter Property="LegendLocation" Value="None"/>
</Style>
-
+
<DataTemplate x:Key="PopUpDataTemplate">
<CheckBox VerticalAlignment="Center" FontSize="11" DockPanel.Dock="Left" IsChecked="{Binding IsSelected}">
<CheckBox.Content>
@@ -64,14 +71,6 @@
</CheckBox>
</DataTemplate>
- <DataTemplate x:Key="PopUpSNDataTemplate">
- <CheckBox VerticalAlignment="Center" FontSize="11" DockPanel.Dock="Left" IsChecked="{Binding IsSelected}" >
- <CheckBox.Content>
- <TextBlock Margin="5 0 0 0" VerticalAlignment="Center" Text="{Binding Data.SerialNumber}" ToolTip="{Binding Data.SerialNumber}" FontFamily="{StaticResource FontName}"></TextBlock>
- </CheckBox.Content>
- </CheckBox>
- </DataTemplate>
-
<DataTemplate x:Key="PopupBoolDataTemplate">
<CheckBox VerticalAlignment="Center" FontSize="11" DockPanel.Dock="Left" IsChecked="{Binding IsSelected}">
<CheckBox.Content>
@@ -80,22 +79,6 @@
</CheckBox>
</DataTemplate>
- <DataTemplate x:Key="PopupThreadDataTemplate">
- <CheckBox VerticalAlignment="Center" FontSize="11" DockPanel.Dock="Left" IsChecked="{Binding IsSelected}" >
- <CheckBox.Content>
- <TextBlock Margin="5 0 5 0" VerticalAlignment="Center" Text="{Binding Data.Name}" ToolTip="{Binding Data.Name}" FontFamily="{StaticResource FontName}" FontSize="11"></TextBlock>
- </CheckBox.Content>
- </CheckBox>
- </DataTemplate>
-
- <DataTemplate x:Key="PopupIsHeadHeatingDataTemplate">
- <CheckBox VerticalAlignment="Center" FontSize="11" DockPanel.Dock="Left" IsChecked="{Binding IsSelected}">
- <CheckBox.Content>
- <TextBlock Margin="5 0 0 0" VerticalAlignment="Center" Text="{Binding Data, Converter={StaticResource HeadCleaningConverter}}"/>
- </CheckBox.Content>
- </CheckBox>
- </DataTemplate>
-
<Style x:Key="{x:Type ToolTip}" TargetType="{x:Type ToolTip}" BasedOn="{StaticResource MaterialDesignToolTip}">
<Setter Property="Background" Value="{StaticResource Logging.Background}" />
@@ -158,13 +141,18 @@
</DockPanel>
</Border>
<Popup AllowsTransparency="True" StaysOpen="False" IsOpen="{Binding RelativeSource={RelativeSource AncestorType=ToggleButton},Path=IsChecked }">
- <Border Padding="3" CornerRadius="0 0 3 3" MinWidth="{Binding RelativeSource={RelativeSource AncestorType=ToggleButton},Path=Width}" Margin="5" Background="{StaticResource TransparentBackgroundBrush200}" BorderBrush="{StaticResource AutoCompleteTextBox.Popup.BorderBrush}" >
+ <Border Padding="3" CornerRadius="0 0 3 3" MinWidth="{Binding RelativeSource={RelativeSource AncestorType=ToggleButton},Path=Width}" Margin="5" BorderBrush="{StaticResource AutoCompleteTextBox.Popup.BorderBrush}" >
<Border.Effect>
<DropShadowEffect Opacity="0.2" />
</Border.Effect>
- <ScrollViewer MaxHeight="600" Background="{StaticResource TransparentBackgroundBrush}" >
- <ItemsControl ItemsSource="{Binding SelectedMachines}" Foreground="{StaticResource MainWindow.Foreground}" ItemTemplate="{StaticResource PopUpSNDataTemplate}"/>
- </ScrollViewer>
+ <controls:AllSelectedCheckboxList Style="{StaticResource AllSelectedCheckBoxListStyle}" MaxHeight="600" ItemsSource="{Binding SelectedMachines}" Background="{StaticResource ComboBox.Floating.Background}" Foreground="{StaticResource MainWindow.Foreground}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" SelectionMode="Multiple" AllSelected="True" >
+ <controls:AllSelectedCheckboxList.ItemTemplate>
+ <DataTemplate >
+ <TextBlock Margin="5 0 0 0" VerticalAlignment="Center" Text="{Binding Data.SerialNumber}" ToolTip="{Binding Data.SerialNumber}" FontFamily="{StaticResource FontName}" Background="{DynamicResource TransparentBackgroundBrush}" FontSize="11"></TextBlock>
+
+ </DataTemplate>
+ </controls:AllSelectedCheckboxList.ItemTemplate>
+ </controls:AllSelectedCheckboxList>
</Border>
</Popup>
</Grid>
@@ -342,10 +330,13 @@
<Border.Effect>
<DropShadowEffect Opacity="0.2" />
</Border.Effect>
- <ScrollViewer MaxHeight="600" Background="{StaticResource TransparentBackgroundBrush200}">
- <ItemsControl ItemsSource="{Binding SelectedThreads}" Foreground="{StaticResource MainWindow.Foreground}" ItemTemplate="{StaticResource PopupThreadDataTemplate}"/>
-
- </ScrollViewer>
+ <controls:AllSelectedCheckboxList Style="{StaticResource AllSelectedCheckBoxListStyle}" MaxHeight="600" ItemsSource="{Binding SelectedThreads}" Background="{StaticResource ComboBox.Floating.Background}" Foreground="{StaticResource MainWindow.Foreground}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" SelectionMode="Multiple" AllSelected="True" FontSize="11">
+ <controls:AllSelectedCheckboxList.ItemTemplate>
+ <DataTemplate >
+ <TextBlock Margin="5 0 0 0" VerticalAlignment="Center" Text="{Binding Data.Name}" ToolTip="{Binding Data.Name}" FontFamily="{StaticResource FontName}"></TextBlock>
+ </DataTemplate>
+ </controls:AllSelectedCheckboxList.ItemTemplate>
+ </controls:AllSelectedCheckboxList>
</Border>
</Popup>
</Grid>
@@ -364,18 +355,8 @@
<Button x:Name="IsHeadCleaningButton" Width="18" Padding="0" Height="16" DockPanel.Dock="Right" BorderBrush="{x:Null}" HorizontalAlignment="Left" Click="IsHeadCleaningButton_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}" FontSize="11" Margin="5 0 2 0">
- <TextBlock.Style>
- <Style TargetType="{x:Type TextBlock}">
- <Setter Property="Text" Value="{Binding IsHeadCleaningSelection.SynchedSource, Converter={StaticResource CollectionConverter}, ConverterParameter='Exclude, Only'}">
- </Setter>
- <Style.Triggers>
- <DataTrigger Binding="{Binding IsHeadCleaningSelection.SynchedSource.Count}" Value="2">
- <Setter Property="Text" Value="Include"/>
- </DataTrigger>
- </Style.Triggers>
- </Style>
- </TextBlock.Style>
+ <TextBlock VerticalAlignment="Center" Foreground="{StaticResource MainWindow.Foreground}" FontSize="11" Margin="5 0 2 0" Text="{Binding HeadCleaningSelected, Converter={StaticResource EnumToDescriptionConverter}}">
+
</TextBlock>
</DockPanel>
</Border>
@@ -384,8 +365,17 @@
<Border.Effect>
<DropShadowEffect Opacity="0.2" />
</Border.Effect>
- <ItemsControl ItemsSource="{Binding IsHeadCleaningSelection}" Foreground="{StaticResource MainWindow.Foreground}" ItemTemplate="{StaticResource PopupIsHeadHeatingDataTemplate}"/>
-
+ <ListBox x:Name="HeadCleaningListBoxItem" ItemsSource="{Binding Source={StaticResource HeadCleaning}}" Foreground="{StaticResource MainWindow.Foreground}" SelectedItem="{Binding HeadCleaningSelected, Mode=TwoWay}" SelectionMode="Single" >
+ <ListBox.ItemTemplate>
+ <DataTemplate>
+ <CheckBox x:Name="HeadCleaningCheckBox" Selector.IsSelected="True" VerticalAlignment="Center" FontSize="11" DockPanel.Dock="Left" IsChecked="{Binding IsSelected, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}, UpdateSourceTrigger=PropertyChanged}" Click="CheckBox_PreventUndoCheck">
+ <CheckBox.Content>
+ <TextBlock Margin="5 0 0 0" VerticalAlignment="Center" Text="{Binding Converter={StaticResource EnumToDescriptionConverter}}"/>
+ </CheckBox.Content>
+ </CheckBox>
+ </DataTemplate>
+ </ListBox.ItemTemplate>
+ </ListBox>
</Border>
</Popup>
</Grid>
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
index 9bfed23e3..226478a7d 100644
--- 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
@@ -28,6 +28,8 @@ namespace Tango.MachineStudio.Statistics.Views
InitializeComponent();
_lastSelectedGridItemIndex = -1;
}
+
+
private void Button_Click(object sender, RoutedEventArgs e)
{
selectMachineButton.IsChecked = true;
@@ -127,5 +129,20 @@ namespace Tango.MachineStudio.Statistics.Views
}
}
}
+
+ private void CheckBox_PreventUndoCheck(object sender, RoutedEventArgs e)
+ {
+ if( sender is CheckBox)
+ {
+ CheckBox cb = sender as CheckBox;
+ if (cb.IsChecked == false)
+ {
+ cb.IsChecked = true;
+ e.Handled = true;
+ return;
+ }
+ }
+ e.Handled = false;
+ }
}
}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/HeadCleaningConverter.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Converters/RoleEnumToVisibleConverter.cs
index 478a1deba..350257fdd 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/Converters/HeadCleaningConverter.cs
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Converters/RoleEnumToVisibleConverter.cs
@@ -4,15 +4,24 @@ using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using System.Windows;
using System.Windows.Data;
+using Tango.BL.Enumerations;
-namespace Tango.MachineStudio.Statistics.Converters
+namespace Tango.MachineStudio.UsersAndRoles.Converters
{
- public class HeadCleaningConverter : IValueConverter
+ public class RoleEnumToVisibleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
- return (bool)value ? "Only" : "Exclude";
+ if(value.GetType().IsEnum && Enum.IsDefined(typeof(Roles), value))
+ {
+ Roles roleEnum = (Roles)value;
+ if (roleEnum.ToString().StartsWith("FSE"))
+ return Visibility.Collapsed;
+ }
+
+ return Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Tango.MachineStudio.UsersAndRoles.csproj b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Tango.MachineStudio.UsersAndRoles.csproj
index 035cb2b9d..687544c1b 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Tango.MachineStudio.UsersAndRoles.csproj
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Tango.MachineStudio.UsersAndRoles.csproj
@@ -75,6 +75,7 @@
<Compile Include="..\..\..\Versioning\GlobalVersionInfo.cs">
<Link>GlobalVersionInfo.cs</Link>
</Compile>
+ <Compile Include="Converters\RoleEnumToVisibleConverter.cs" />
<Compile Include="Navigation\UsersAndRolesNavigationManager.cs" />
<Compile Include="Navigation\UsersAndRolesNavigationView.cs" />
<Compile Include="Providers\PlaceAddress.cs" />
@@ -226,10 +227,11 @@
<ItemGroup>
<Resource Include="Images\login.png" />
</ItemGroup>
+ <ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
<VisualStudio>
- <UserProperties BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UseGlobalSettings="False" BuildVersion_StartDate="2000/1/1" />
+ <UserProperties BuildVersion_StartDate="2000/1/1" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" />
</VisualStudio>
</ProjectExtensions>
</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Views/UserManagementView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Views/UserManagementView.xaml
index 3964abfc8..2a8621e5c 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Views/UserManagementView.xaml
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.UsersAndRoles/Views/UserManagementView.xaml
@@ -14,6 +14,7 @@
xmlns:entities="clr-namespace:Tango.BL.Entities;assembly=Tango.BL"
xmlns:local="clr-namespace:Tango.MachineStudio.UsersAndRoles.Views"
xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI"
+ xmlns:localconverters="clr-namespace:Tango.MachineStudio.UsersAndRoles.Converters"
mc:Ignorable="d"
d:DesignHeight="1080" d:DesignWidth="1920" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}">
@@ -21,6 +22,7 @@
<providers:PlacesProvider x:Key="PlacesProvider" />
<converters:BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter"></converters:BooleanToVisibilityConverter>
<converters:BooleanToVisibilityInverseConverter x:Key="BooleanToVisibilityInverseConverter"></converters:BooleanToVisibilityInverseConverter>
+ <localconverters:RoleEnumToVisibleConverter x:Key="RoleEnumToVisibleConverter"/>
</UserControl.Resources>
<Grid>
@@ -103,7 +105,7 @@
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type entities:Role}">
- <Grid>
+ <Grid Visibility="{Binding RoleEnum, Converter={StaticResource RoleEnumToVisibleConverter}}">
<Grid.ToolTip>
<StackPanel Background="Transparent">
<TextBlock Text="{Binding Description}" FontSize="10" Margin="0 0 0 10"></TextBlock>
@@ -175,7 +177,7 @@
<ListBox ItemsSource="{Binding Roles}" ItemContainerStyle="{StaticResource basicListBoxItem}" HorizontalContentAlignment="Stretch" Background="Transparent">
<ListBox.ItemTemplate>
<DataTemplate>
- <Grid Background="Transparent" IsHitTestVisible="True" Style="{StaticResource draggableGrid}" dragAndDrop:DragAndDropService.DraggableBorderBrush="{StaticResource AccentColorBrush}" dragAndDrop:DragAndDropService.Draggable="True" dragAndDrop:DragAndDropService.DraggingSurface="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DraggingSurface}">
+ <Grid Background="Transparent" IsHitTestVisible="True" Style="{StaticResource draggableGrid}" dragAndDrop:DragAndDropService.DraggableBorderBrush="{StaticResource AccentColorBrush}" dragAndDrop:DragAndDropService.Draggable="True" dragAndDrop:DragAndDropService.DraggingSurface="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DraggingSurface}" Visibility="{Binding RoleEnum, Converter={StaticResource RoleEnumToVisibleConverter}}">
<Grid.ToolTip>
<StackPanel Background="Transparent">
<TextBlock Text="{Binding Description}" FontSize="10" Margin="0 0 0 10"></TextBlock>
diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Resources/MaterialDesign.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Resources/MaterialDesign.xaml
index c8e216191..007712d87 100644
--- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Resources/MaterialDesign.xaml
+++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Resources/MaterialDesign.xaml
@@ -772,16 +772,77 @@
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
- <ControlTemplate TargetType="{x:Type ComboBox}" >
+ <ControlTemplate TargetType="{x:Type controls:SearchComboBox}">
<Grid x:Name="templateRoot" Background="Transparent" SnapsToDevicePixels="True">
<Grid x:Name="InnerRoot">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="0" MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" />
</Grid.ColumnDefinitions>
- <ToggleButton x:Name="SearchToggleButton" Grid.ColumnSpan="2" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}"
- BorderThickness="{TemplateBinding BorderThickness}" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
- Style="{StaticResource MaterialDesignComboBoxToggleButton}"/>
+ <ToggleButton x:Name="SearchToggleButton" Grid.ColumnSpan="2" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" IsChecked="{Binding IsOpened, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Style="{x:Null}">
+ <ToggleButton.Template>
+ <ControlTemplate TargetType="ToggleButton">
+ <Grid>
+ <Border x:Name="ToggleTemplateRoot"
+ Background="{TemplateBinding Background}"
+ BorderBrush="{TemplateBinding BorderBrush}"
+ BorderThickness="{TemplateBinding BorderThickness}">
+ <Border x:Name="splitBorder"
+ Margin="0"
+ HorizontalAlignment="Right"
+ VerticalAlignment="Center"
+ BorderBrush="Transparent"
+ BorderThickness="0">
+ <Path x:Name="arrow"
+ Width="8" Height="8"
+ Margin="0"
+ Stretch="Uniform"
+ HorizontalAlignment="Right"
+ VerticalAlignment="Center"
+ Data="M7,10L12,15L17,10H7Z"
+ Fill="{TemplateBinding BorderBrush}" />
+ </Border>
+ </Border>
+ </Grid>
+ <ControlTemplate.Triggers>
+ <MultiDataTrigger>
+ <MultiDataTrigger.Conditions>
+ <Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}" Value="true" />
+ <Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="false" />
+ </MultiDataTrigger.Conditions>
+ </MultiDataTrigger>
+ <MultiDataTrigger>
+ <MultiDataTrigger.Conditions>
+ <Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}" Value="true" />
+ <Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="true" />
+ </MultiDataTrigger.Conditions>
+ <Setter Property="BorderBrush" Value="{DynamicResource PrimaryHueMidBrush}" />
+ </MultiDataTrigger>
+ <Trigger Property="IsPressed" Value="true">
+ <Setter TargetName="arrow" Property="Fill" Value="{DynamicResource PrimaryHueDarkBrush}" />
+ </Trigger>
+ <Trigger Property="IsEnabled" Value="false">
+ <Setter TargetName="arrow" Property="Fill" Value="{DynamicResource MaterialDesignCheckBoxDisabled}" />
+ </Trigger>
+ <MultiDataTrigger>
+ <MultiDataTrigger.Conditions>
+ <Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}" Value="false" />
+ <Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="false" />
+ </MultiDataTrigger.Conditions>
+ <Setter TargetName="ToggleTemplateRoot" Property="BorderBrush" Value="Transparent"/>
+ </MultiDataTrigger>
+ <MultiDataTrigger>
+ <MultiDataTrigger.Conditions>
+ <Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}" Value="false" />
+ <Condition Binding="{Binding IsEditable, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="true" />
+ </MultiDataTrigger.Conditions>
+ <Setter TargetName="ToggleTemplateRoot" Property="BorderBrush" Value="Transparent"/>
+ <Setter TargetName="splitBorder" Property="BorderBrush" Value="{DynamicResource MaterialDesignCheckBoxDisabled}" />
+ </MultiDataTrigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </ToggleButton.Template>
+ </ToggleButton>
<Grid HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" UseLayoutRounding="{TemplateBinding UseLayoutRounding}">
<Grid x:Name="InputRoot" HorizontalAlignment="Left">
<ContentPresenter x:Name="contentPresenter" Content="{TemplateBinding SelectionBoxItem}" ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" IsHitTestVisible="False" />
@@ -798,35 +859,25 @@
</Grid>
</Grid>
<Line x:Name="DashedLine" Grid.ColumnSpan="2" VerticalAlignment="Bottom" Visibility="{Binding Path=IsEnabled, RelativeSource={RelativeSource Self}, Converter={StaticResource InverseBoolToVisConverter}}" StrokeThickness="1.25" StrokeDashArray="1,2.5" StrokeDashCap="Round" X1="0" X2="{Binding ActualWidth, ElementName=SearchToggleButton}" Y1="0" Y2="0" Stroke="{TemplateBinding BorderBrush}" Opacity="0.56" />
- <materialDesign:Underline x:Name="Underline" Grid.ColumnSpan="2" IsActive="{Binding ElementName=PART_EditableTextBox, Path=IsKeyboardFocused}"
- Visibility="{Binding Path=(materialDesign:TextFieldAssist.DecorationVisibility), RelativeSource={RelativeSource TemplatedParent}}"/>
+ <materialDesign:Underline x:Name="Underline" Grid.ColumnSpan="2" IsActive="{Binding ElementName=PART_EditableTextBox, Path=IsKeyboardFocused}" Visibility="{Binding Path=(materialDesign:TextFieldAssist.DecorationVisibility), RelativeSource={RelativeSource TemplatedParent}}"/>
- <controls:PopupWithKeyboardFocus x:Name="PART_Popup" AllowsTransparency="true" Focusable="False" HorizontalOffset="-11.5"
- Tag="{Binding RelativeSource={RelativeSource AncestorType=controls:SearchComboBox}}" IsOpen="{Binding ElementName=SearchToggleButton,Path=IsChecked}" PlacementTarget="{Binding ElementName=templateRoot}"
- SnapsToDevicePixels="True" UseLayoutRounding="True" Placement="Custom" PopupAnimation="Fade" VerticalOffset="-10" DefaultVerticalOffset="5"
- DownVerticalOffset="{Binding ElementName=templateRoot, Path=ActualHeight}" UpVerticalOffset="15" ClassicMode="{Binding Path=(materialDesign:ComboBoxAssist.ClassicMode), RelativeSource={RelativeSource TemplatedParent}}"
- UpContentTemplate="{StaticResource PopupContentUpTemplate}" DownContentTemplate="{StaticResource TransparentPopupContentDownTemplate}" ClassicContentTemplate="{StaticResource PopupContentClassicTemplate}">
+ <materialDesign:ComboBoxPopup x:Name="PART_Popup" AllowsTransparency="true" HorizontalOffset="0" Tag="{Binding RelativeSource={RelativeSource AncestorType=controls:SearchComboBox}}" IsOpen="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=IsOpened, Mode=TwoWay}" PlacementTarget="{Binding ElementName=templateRoot}" SnapsToDevicePixels="True" UseLayoutRounding="True" Placement="Bottom" PopupAnimation="Fade" VerticalOffset="-10" DefaultVerticalOffset="5"
+ MinWidth="{Binding ElementName=SearchToggleButton,Path=ActualWidth}" DownVerticalOffset="{Binding ElementName=templateRoot, Path=ActualHeight}" UpVerticalOffset="15" ClassicMode="{Binding Path=(materialDesign:ComboBoxAssist.ClassicMode), RelativeSource={RelativeSource TemplatedParent}}"
+ MaxHeight="{TemplateBinding MaxDropDownHeight}" UpContentTemplate="{StaticResource PopupContentUpTemplate}" DownContentTemplate="{StaticResource TransparentPopupContentDownTemplate}" ClassicContentTemplate="{StaticResource PopupContentClassicTemplate}" StaysOpen="False" Margin="10 0 0 0">
<ContentControl>
<Border Opacity="1" Background="{DynamicResource ComboBox.Floating.Background}" Padding="1" BorderThickness="0" BorderBrush="{TemplateBinding BorderBrush}" MaxHeight="{TemplateBinding MaxDropDownHeight}" >
- <Grid >
- <Grid.RowDefinitions>
- <RowDefinition Height="30"/>
- <RowDefinition Height="1*"/>
- </Grid.RowDefinitions>
- <TextBox x:Name="Search" Grid.Row="0" HorizontalAlignment="Stretch" Text="{Binding RelativeSource={RelativeSource AncestorType=controls:SearchComboBox}, Path=SearchText}" Background="{DynamicResource ComboBox.Floating.Background}" IsReadOnly="False" FontSize="14" TextAlignment="Left" VerticalAlignment="Center" VerticalContentAlignment="Center" BorderThickness="0 0 0 2" Margin=" 1 0 1 0">
+ <DockPanel>
+ <TextBox x:Name="Search" DockPanel.Dock="Top" Margin="10" Padding="0 5" HorizontalAlignment="Stretch" Text="{Binding RelativeSource={RelativeSource AncestorType=controls:SearchComboBox}, Path=SearchFilter, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Background="{DynamicResource ComboBox.Floating.Background}" IsReadOnly="False" FontSize="14" TextAlignment="Left" VerticalAlignment="Center" VerticalContentAlignment="Center" BorderThickness="0 0 0 2" >
<TextBox.Style>
<Style TargetType="TextBox"/>
</TextBox.Style>
</TextBox>
- <ScrollViewer Grid.Row="1" Background="{DynamicResource ComboBox.Floating.Background}" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Hidden">
+ <ListBox x:Name="list" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=controls:SearchComboBox}, Path = ListItemsSource}" ItemTemplate="{TemplateBinding ItemTemplate}"/>
- <ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained"/>
-
- </ScrollViewer>
- </Grid>
+ </DockPanel>
</Border>
</ContentControl>
- </controls:PopupWithKeyboardFocus>
+ </materialDesign:ComboBoxPopup>
</Grid>
</Grid>
<ControlTemplate.Triggers>
@@ -926,6 +977,52 @@
</Setter>
</Style>
+ <Style x:Key="CheckBoxListBoxItem" TargetType="{x:Type ListBoxItem}">
+ <Setter Property="SnapsToDevicePixels" Value="true" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="ListBoxItem">
+ <CheckBox Margin="5,2" IsChecked="{TemplateBinding IsSelected}" x:Name="CheckBoxItem"
+ Command="{Binding RelativeSource={RelativeSource AncestorType=controls:AllSelectedCheckboxList}, Path=ClickCheckBoxCommand}" CommandParameter="{Binding RelativeSource={RelativeSource TemplatedParent}}">
+ <ContentPresenter />
+ </CheckBox>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style x:Key="AllSelectedCheckBoxListStyle" TargetType="{x:Type controls:AllSelectedCheckboxList}" BasedOn="{StaticResource MaterialDesignListBox}">
+ <!--<Setter Property="OverridesDefaultStyle" Value="true" />-->
+ <Setter Property="SnapsToDevicePixels" Value="true" />
+ <Setter Property="SelectionMode" Value="Multiple"/>
+ <Setter Property="ItemContainerStyle" Value="{StaticResource CheckBoxListBoxItem}"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type controls:AllSelectedCheckboxList}">
+ <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">
+ <DockPanel>
+ <CheckBox x:Name="SelectAllCheckBox" DockPanel.Dock="Top" VerticalAlignment="Center" IsChecked="{Binding AllSelected, Mode=TwoWay,RelativeSource={RelativeSource AncestorType=controls:AllSelectedCheckboxList}}" Margin="5">
+ <TextBlock Margin="5 0 0 0" VerticalAlignment="Center" Text="SelectAll"></TextBlock>
+ </CheckBox>
+ <ScrollViewer DockPanel.Dock="Bottom" Focusable="false" Padding="{TemplateBinding Padding}">
+ <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
+ </ScrollViewer>
+ </DockPanel>
+ </Border>
+ <ControlTemplate.Triggers>
+ <MultiTrigger>
+ <MultiTrigger.Conditions>
+ <Condition Property="IsGrouping" Value="true"/>
+ <Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="false"/>
+ </MultiTrigger.Conditions>
+ <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
+ </MultiTrigger>
+ </ControlTemplate.Triggers>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
<Style TargetType="Window">
<Setter Property="FontFamily" Value="{StaticResource flexo}"></Setter>
</Style>
diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml.cs
index 2ea0ebd38..7eab5066a 100644
--- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml.cs
+++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml.cs
@@ -25,6 +25,8 @@ using Tango.Core;
using Tango.BL;
using Tango.Integration.Operation;
using System.Net;
+using System.Globalization;
+using System.Windows.Markup;
namespace Tango.MachineStudio.UI
{
@@ -40,6 +42,18 @@ namespace Tango.MachineStudio.UI
protected override void OnStartup(StartupEventArgs e)
{
+ //Set culture info.
+ var enUSCulture = new CultureInfo("en-US");
+
+ Thread.CurrentThread.CurrentCulture = enUSCulture;
+ Thread.CurrentThread.CurrentUICulture = enUSCulture;
+ CultureInfo.DefaultThreadCurrentCulture = enUSCulture;
+ CultureInfo.DefaultThreadCurrentUICulture = enUSCulture;
+
+ FrameworkElement.LanguageProperty.OverrideMetadata(
+ typeof(FrameworkElement),
+ new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));
+
StartupArgs = e.Args;
#if DEBUG
@@ -88,6 +102,17 @@ namespace Tango.MachineStudio.UI
ApplyEFCacheSettings();
WebRequest.DefaultWebProxy = null;
+
+ GetLastApplicationCrashFromWindows();
+ }
+
+ private async void GetLastApplicationCrashFromWindows()
+ {
+ var logItem = await exceptionTrapper.GetLastApplicationCrashEventLog();
+ if (logItem != null)
+ {
+ LogManager.Log(logItem);
+ }
}
private void ApplyEFCacheSettings()
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Images/remote_connections.png b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Images/remote_connections.png
new file mode 100644
index 000000000..d9d4a1d45
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Images/remote_connections.png
Binary files differ
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Tango.PPC.Technician.csproj b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Tango.PPC.Technician.csproj
index e8eec7b2f..7f36b7b17 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Tango.PPC.Technician.csproj
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Tango.PPC.Technician.csproj
@@ -106,11 +106,15 @@
<Compile Include="ViewModels\LoggingViewVM.cs" />
<Compile Include="ViewModels\MainViewVM.cs" />
<Compile Include="ViewModels\PackagesViewVM.cs" />
+ <Compile Include="ViewModels\RemoteConnectionsViewVM.cs" />
<Compile Include="ViewModels\UpdatesViewVM.cs" />
<Compile Include="ViewModels\SystemViewVM.cs" />
<Compile Include="Views\CatalogView.xaml.cs">
<DependentUpon>CatalogView.xaml</DependentUpon>
</Compile>
+ <Compile Include="Views\RemoteConnectionsView.xaml.cs">
+ <DependentUpon>RemoteConnectionsView.xaml</DependentUpon>
+ </Compile>
<Compile Include="Views\UpdatesView.xaml.cs">
<DependentUpon>UpdatesView.xaml</DependentUpon>
</Compile>
@@ -219,6 +223,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
+ <Page Include="Views\RemoteConnectionsView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
<Page Include="Views\UpdatesView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@@ -272,5 +280,8 @@
<ItemGroup>
<Resource Include="Images\browser.png" />
</ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\remote_connections.png" />
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModelLocator.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModelLocator.cs
index d50df6a01..9a8b63c91 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModelLocator.cs
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModelLocator.cs
@@ -22,6 +22,7 @@ namespace Tango.PPC.Technician
TangoIOC.Default.Register<SystemViewVM>();
TangoIOC.Default.Register<PackagesViewVM>();
TangoIOC.Default.Register<UpdatesViewVM>();
+ TangoIOC.Default.Register<RemoteConnectionsViewVM>();
}
/// <summary>
@@ -100,5 +101,16 @@ namespace Tango.PPC.Technician
return TangoIOC.Default.GetInstance<UpdatesViewVM>();
}
}
+
+ /// <summary>
+ /// Gets the remote connections view vm.
+ /// </summary>
+ public static RemoteConnectionsViewVM RemoteConnectionsViewVM
+ {
+ get
+ {
+ return TangoIOC.Default.GetInstance<RemoteConnectionsViewVM>();
+ }
+ }
}
}
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/LoggingViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/LoggingViewVM.cs
index a0110b18a..2aee7f561 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/LoggingViewVM.cs
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/LoggingViewVM.cs
@@ -12,6 +12,7 @@ using Tango.Integration.Logging;
using Tango.Integration.Operation;
using Tango.Logging;
using Tango.PPC.Common;
+using Tango.PPC.Common.Helpers;
using Tango.PPC.Technician.Dialogs;
namespace Tango.PPC.Technician.ViewModels
@@ -86,6 +87,13 @@ namespace Tango.PPC.Technician.ViewModels
paused_logs = new List<LogItemBase>();
paused_embedded_logs = new List<LogItemBase>();
+ var appStartLogs = LogsHelper.GetLogSafe().EmptyAndDispose();
+
+ foreach (var log in appStartLogs)
+ {
+ ApplicationLogs.Insert(0, log);
+ }
+
LogManager.NewLog += LogManager_NewLog;
MachineOperator.EmbeddedLogManager.NewLog += EmbeddedLogManager_NewLog;
ClearCommand = new RelayCommand(ClearLogs);
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/RemoteConnectionsViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/RemoteConnectionsViewVM.cs
new file mode 100644
index 000000000..2d8857329
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/RemoteConnectionsViewVM.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Core.Commands;
+using Tango.Integration.ExternalBridge;
+using Tango.PPC.Common;
+
+namespace Tango.PPC.Technician.ViewModels
+{
+ public class RemoteConnectionsViewVM : PPCViewModel
+ {
+ public RelayCommand DisconnectCommand { get; set; }
+
+ private ExternalBridgeReceiver _selectedReceiver;
+ public ExternalBridgeReceiver SelectedReceiver
+ {
+ get { return _selectedReceiver; }
+ set
+ {
+ if (value != null)
+ {
+ _selectedReceiver = value;
+ InvalidateRelayCommands();
+ }
+ }
+ }
+
+ public RemoteConnectionsViewVM()
+ {
+ DisconnectCommand = new RelayCommand(DisconnectReceiver, () => SelectedReceiver != null);
+ }
+
+ private async void DisconnectReceiver()
+ {
+ if (SelectedReceiver != null)
+ {
+ try
+ {
+ await Task.Factory.StartNew(() =>
+ {
+ SelectedReceiver.Disconnect().Wait();
+ });
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error disconnecting the specified receiver.");
+ }
+ finally
+ {
+ _selectedReceiver = null;
+ RaisePropertyChanged(nameof(SelectedReceiver));
+ InvalidateRelayCommands();
+ }
+ }
+ }
+
+ public override void OnApplicationStarted()
+ {
+
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/CatalogView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/CatalogView.xaml
index 8f4bc9f0b..f954e461f 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/CatalogView.xaml
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/CatalogView.xaml
@@ -105,6 +105,18 @@
</StackPanel>
</touch:TouchButton>
+ <touch:TouchButton Command="{Binding NavigationCommand}" CommandParameter="RemoteConnectionsView" Style="{StaticResource ButtonMenu}">
+ <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
+ <Image Source="../Images/remote_connections.png" Width="80" Height="80" />
+ <StackPanel Margin="10 0 0 0">
+ <TextBlock FontSize="{StaticResource TangoButtonFontSize}">Remote Connections</TextBlock>
+ <TextBlock Foreground="{StaticResource TangoGrayTextBrush}" TextWrapping="Wrap" Width="580">
+ View the current status of remote connections to this machine.
+ </TextBlock>
+ </StackPanel>
+ </StackPanel>
+ </touch:TouchButton>
+
<touch:TouchButton Command="{Binding BrowserCommand}" Style="{StaticResource ButtonMenu}">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<Image Source="../Images/browser.png" RenderOptions.BitmapScalingMode="Fant" Width="80" Height="80" />
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/MainView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/MainView.xaml
index d669de187..d4235341c 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/MainView.xaml
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/MainView.xaml
@@ -19,6 +19,7 @@
<local:SystemView/>
<local:PackagesView/>
<local:UpdatesView/>
+ <local:RemoteConnectionsView/>
</controls:NavigationControl>
</Grid>
</UserControl>
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/RemoteConnectionsView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/RemoteConnectionsView.xaml
new file mode 100644
index 000000000..af93a56e5
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/RemoteConnectionsView.xaml
@@ -0,0 +1,88 @@
+<UserControl x:Class="Tango.PPC.Technician.Views.RemoteConnectionsView"
+ 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.PPC.Technician.ViewModels"
+ xmlns:touch="clr-namespace:Tango.Touch.Controls;assembly=Tango.Touch"
+ xmlns:global="clr-namespace:Tango.PPC.Technician"
+ xmlns:local="clr-namespace:Tango.PPC.Technician.Views"
+ mc:Ignorable="d"
+ d:DesignHeight="1280" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=vm:RemoteConnectionsViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.RemoteConnectionsViewVM}">
+ <Grid Background="{StaticResource TangoMidBackgroundBrush}">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="1*"/>
+ </Grid.RowDefinitions>
+
+ <Border Padding="20" Background="{StaticResource TangoPrimaryBackgroundBrush}" BorderThickness="0 0 0 1" BorderBrush="{StaticResource TangoDividerBrush}">
+ <Border.Effect>
+ <DropShadowEffect Color="Silver" ShadowDepth="0" BlurRadius="20" Opacity="1" />
+ </Border.Effect>
+ <TextBlock VerticalAlignment="Center" FontSize="{StaticResource TangoHeaderFontSize}" FontWeight="SemiBold">Remote Connections</TextBlock>
+ </Border>
+
+ <Grid Grid.Row="1">
+ <Grid Margin="20">
+ <DockPanel>
+ <touch:TouchButton Command="{Binding DisconnectCommand}" DockPanel.Dock="Bottom" HorizontalAlignment="Right" Style="{StaticResource TangoHollowButton}" Height="60" Width="250" Margin="0 20 0 0">DISCONNECT</touch:TouchButton>
+ <touch:TouchSimpleDataGrid IsSynchronizedWithCurrentItem="True" SelectedItem="{Binding SelectedReceiver,Mode=TwoWay}" Background="{StaticResource TangoPrimaryBackgroundBrush}" AutoGenerateColumns="False" SelectionMode="Single" SelectionUnit="FullRow" BorderThickness="1" BorderBrush="{StaticResource TangoDarkForegroundBrush}" HeadersVisibility="Column" CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" CanUserResizeRows="False" CanUserResizeColumns="False" CanUserSortColumns="False" IsReadOnly="True" ItemsSource="{Binding ExternalBridgeService.ActiveReceivers}" VerticalGridLinesBrush="{x:Null}" HorizontalGridLinesBrush="{StaticResource TangoGrayBrush}" RowHeight="50" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Disabled">
+ <DataGrid.Resources>
+ <Style BasedOn="{StaticResource {x:Type DataGridColumnHeader}}" TargetType="{x:Type DataGridColumnHeader}">
+ <Setter Property="Background" Value="{StaticResource TangoDarkForegroundBrush}" />
+ <Setter Property="Foreground" Value="{StaticResource TangoLightForegroundBrush}" />
+ <Setter Property="Padding" Value="5"></Setter>
+ </Style>
+ </DataGrid.Resources>
+ <DataGrid.RowStyle>
+ <Style TargetType="DataGridRow" BasedOn="{StaticResource {x:Type DataGridRow}}">
+ <Style.Triggers>
+ <Trigger Property="IsSelected" Value="True">
+ <Setter Property="Background" Value="Transparent"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource TangoPrimaryAccentBrush}" />
+ </Trigger>
+ <Trigger Property="IsFocused" Value="True">
+ <Setter Property="Background" Value="Transparent"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource TangoPrimaryAccentBrush}" />
+ </Trigger>
+ </Style.Triggers>
+ </Style>
+ </DataGrid.RowStyle>
+ <DataGrid.CellStyle>
+ <Style TargetType="{x:Type DataGridCell}">
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type DataGridCell}">
+ <Grid Background="{TemplateBinding Background}">
+ <ContentPresenter VerticalAlignment="Center" />
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ <Style.Triggers>
+ <Trigger Property="IsSelected" Value="True">
+ <Setter Property="Background" Value="Transparent"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource TangoPrimaryAccentBrush}" />
+ </Trigger>
+ </Style.Triggers>
+ </Style>
+ </DataGrid.CellStyle>
+ <DataGrid.Columns>
+ <DataGridTemplateColumn Header="" Width="50">
+ <DataGridTemplateColumn.CellTemplate>
+ <DataTemplate>
+ <touch:TouchIcon Width="16" Icon="Bridge" />
+ </DataTemplate>
+ </DataGridTemplateColumn.CellTemplate>
+ </DataGridTemplateColumn>
+ <DataGridTextColumn Header="App ID" Width="130" Binding="{Binding LoginInfo.AppID}" />
+ <DataGridTextColumn Header="User" Width="180" Binding="{Binding LoginInfo.UserName}" />
+ <DataGridTextColumn Header="Host Name" Width="180" Binding="{Binding LoginInfo.HostName}" />
+ <DataGridTextColumn Header="Safety Level Permissions" Width="1*" Binding="{Binding LoginInfo.RequireSafetyLevelOperations,Converter={StaticResource BooleanToYesNoConverter}}" />
+ </DataGrid.Columns>
+ </touch:TouchSimpleDataGrid>
+ </DockPanel>
+ </Grid>
+ </Grid>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/RemoteConnectionsView.xaml.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/RemoteConnectionsView.xaml.cs
new file mode 100644
index 000000000..5d8e32444
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/RemoteConnectionsView.xaml.cs
@@ -0,0 +1,28 @@
+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.PPC.Technician.Views
+{
+ /// <summary>
+ /// Interaction logic for RemoteConnectionsView.xaml
+ /// </summary>
+ public partial class RemoteConnectionsView : UserControl
+ {
+ public RemoteConnectionsView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Helpers/LogsHelper.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Helpers/LogsHelper.cs
new file mode 100644
index 000000000..b7ab2d5b8
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Helpers/LogsHelper.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Logging;
+
+namespace Tango.PPC.Common.Helpers
+{
+ public static class LogsHelper
+ {
+ private static LogSafe _logSafe;
+
+ public static void SetLogSafe(LogSafe logSafe)
+ {
+ _logSafe = logSafe;
+ }
+
+ public static LogSafe GetLogSafe()
+ {
+ return _logSafe;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Insights/DefaultInsightsService.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Insights/DefaultInsightsService.cs
new file mode 100644
index 000000000..e5148cfe5
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Insights/DefaultInsightsService.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Core;
+using Tango.Core.DI;
+using Tango.Insights;
+using Tango.PPC.Common.Application;
+using Tango.PPC.Common.Connection;
+
+namespace Tango.PPC.Common.Insights
+{
+ [TangoCreateWhenRegistered]
+ public class DefaultInsightsService : ExtendedObject, IInsightsService
+ {
+ private InsightsListener _listener;
+ public bool Enabled { get; set; }
+
+ private IMachineProvider MachineProvider { get; set; }
+
+ public DefaultInsightsService(IMachineProvider machineProvider, IPPCApplicationManager applicationManager)
+ {
+ MachineProvider = machineProvider;
+
+ applicationManager.ApplicationStarted += ApplicationManager_ApplicationStarted;
+ }
+
+ private void ApplicationManager_ApplicationStarted(object sender, EventArgs e)
+ {
+ Task.Factory.StartNew(() =>
+ {
+ try
+ {
+ _listener = new InsightsListener(MachineProvider.MachineOperator);
+ _listener.Start();
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error initializing insights listener.");
+ }
+ });
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Insights/IInsightsService.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Insights/IInsightsService.cs
new file mode 100644
index 000000000..d7c5497d6
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Insights/IInsightsService.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.PPC.Common.Insights
+{
+ public interface IInsightsService: IPPCService
+ {
+
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PPCPublisher.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PPCPublisher.cs
index 2fc2ca507..a28cc747a 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PPCPublisher.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PPCPublisher.cs
@@ -59,14 +59,11 @@ namespace Tango.PPC.Common.Publish
/// Gets the latest version.
/// </summary>
/// <returns></returns>
- public async Task<String> GetRemoteVersion(String machineVersionGuid)
+ public async Task<LatestVersionResponse> GetRemoteVersion(String machineVersionGuid)
{
_client.Environment = Options.Environment;
- var response = await _client.GetLatestVersion(new LatestVersionRequest()
- {
- MachineVersionGuid = machineVersionGuid,
- });
- return response.Version;
+ var response = await _client.GetLatestVersion(new LatestVersionRequest() { MachineVersionGuid = machineVersionGuid } );
+ return response;
}
/// <summary>
@@ -163,8 +160,12 @@ namespace Tango.PPC.Common.Publish
OnPublishProgress(0, 100, $"Fetching remote version from {Options.Environment.ToAddress()}...");
- String remote_version = GetRemoteVersion(Options.MachineVersionGuid).Result;
+ var r = GetRemoteVersion(Options.MachineVersionGuid).Result;
+ String remote_version = r.Version;
+ String remote_firmware_version = r.FirmwareVersion;
+
String local_version = GetLocalVersion();
+ String local_firmware_version = GetLocalFirmwareVersion(Options.TfpPath);
OnPublishProgress(0, 100, $"Remote version: {remote_version}");
OnPublishProgress(0, 100, $"Local version: {local_version}");
@@ -174,6 +175,11 @@ namespace Tango.PPC.Common.Publish
throw new InvalidOperationException($"The local version '{local_version}' is not greater than the remote version '{remote_version}'.");
}
+ if (Version.Parse(local_firmware_version) <= Version.Parse(remote_firmware_version))
+ {
+ throw new InvalidOperationException($"The local firmware version '{local_firmware_version}' is not greater than the remote version '{remote_firmware_version}'.");
+ }
+
OnPublishProgress(0, 100, $"Requesting version upload...");
var response = _client.UploadVersion(new UploadVersionRequest()
@@ -233,7 +239,7 @@ namespace Tango.PPC.Common.Publish
Token = response.Token,
}).Wait();
- remote_version = GetRemoteVersion(Options.MachineVersionGuid).Result;
+ remote_version = GetRemoteVersion(Options.MachineVersionGuid).Result.Version;
local_version = GetLocalVersion();
OnPublishProgress(0, 0, $"Remote version: {remote_version}");
@@ -413,6 +419,16 @@ namespace Tango.PPC.Common.Publish
}
/// <summary>
+ /// Gets the MCU version from the specified TFP file.
+ /// </summary>
+ /// <param name="tfpFile">The TFP file.</param>
+ /// <returns></returns>
+ public String GetLocalFirmwareVersion(String tfpFile)
+ {
+ return GetVersionInfoFromTFP(tfpFile).GetMcuVersion().ToString();
+ }
+
+ /// <summary>
/// Raises the publish progress event.
/// </summary>
/// <param name="progress">The progress.</param>
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishOptions.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishOptions.cs
index 4c40acb44..9b8613cfb 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishOptions.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishOptions.cs
@@ -17,6 +17,7 @@ namespace Tango.PPC.Common.Publish
public event EventHandler BuidConfigChanged;
public event EventHandler BasicInfoChanged;
public event EventHandler MachineVersionGuidChanged;
+ public event EventHandler TfpPathChanged;
private String basePath;
[Option("path", HelpText = "Specifies the application base path.", Required = false)]
@@ -79,7 +80,7 @@ namespace Tango.PPC.Common.Publish
public String TfpPath
{
get { return _tfpPath; }
- set { _tfpPath = value; RaisePropertyChangedAuto(); }
+ set { _tfpPath = value; RaisePropertyChangedAuto(); TfpPathChanged?.Invoke(this, new EventArgs()); }
}
private String _installerProject;
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Resources/Merged.xaml b/Software/Visual_Studio/PPC/Tango.PPC.Common/Resources/Merged.xaml
index 7398c898f..955a584c2 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Resources/Merged.xaml
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Resources/Merged.xaml
@@ -54,6 +54,7 @@
<converters:DateTimeUTCToShortDateTimeConverter x:Key="DateTimeUTCToShortDateTimeConverter" />
<converters:TimeSpanToMinutesConverter x:Key="TimeSpanToMinutesConverter" />
<converters:TimeSpanToSecondsConverter x:Key="TimeSpanToSecondsConverter" />
+ <converters:BooleanToYesNoConverter x:Key="BooleanToYesNoConverter" />
<Style TargetType="FrameworkElement">
<Setter Property="TextElement.FontFamily" Value="{StaticResource TangoFlexoFontFamily}"></Setter>
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj b/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj
index 32f3b865b..08e49621c 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj
@@ -160,8 +160,11 @@
<Compile Include="FileSystem\FileSystemOperationMode.cs" />
<Compile Include="FileSystem\IFileSystemService.cs" />
<Compile Include="Helpers\KeyboardHelper.cs" />
+ <Compile Include="Helpers\LogsHelper.cs" />
<Compile Include="HotSpot\DefaultHotSpotProvider.cs" />
<Compile Include="HotSpot\IHotSpotProvider.cs" />
+ <Compile Include="Insights\DefaultInsightsService.cs" />
+ <Compile Include="Insights\IInsightsService.cs" />
<Compile Include="IPPCView.cs" />
<Compile Include="IPPCService.cs" />
<Compile Include="MachineSetup\IMachineSetupManager.cs" />
@@ -388,6 +391,10 @@
<Project>{c6ebbbbe-2123-44dc-aef7-a0d47d736ac0}</Project>
<Name>Tango.FileSystem</Name>
</ProjectReference>
+ <ProjectReference Include="..\..\Tango.Insights\Tango.Insights.csproj">
+ <Project>{4a55c185-3f8d-41b0-8815-c15f6213a14a}</Project>
+ <Name>Tango.Insights</Name>
+ </ProjectReference>
<ProjectReference Include="..\..\Tango.Integration\Tango.Integration.csproj">
<Project>{4206ac58-3b57-4699-8835-90bf6db01a61}</Project>
<Name>Tango.Integration</Name>
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/LatestVersionResponse.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/LatestVersionResponse.cs
index d2ed08f7d..eb5ef7f5a 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/LatestVersionResponse.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/LatestVersionResponse.cs
@@ -11,5 +11,6 @@ namespace Tango.PPC.Common.Web
public class LatestVersionResponse : WebResponseMessage
{
public String Version { get; set; }
+ public String FirmwareVersion { get; set; }
}
}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Publisher.UI/MainWindow.xaml b/Software/Visual_Studio/PPC/Tango.PPC.Publisher.UI/MainWindow.xaml
index f74194222..1d60a70be 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Publisher.UI/MainWindow.xaml
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Publisher.UI/MainWindow.xaml
@@ -67,15 +67,17 @@
<TextBlock Margin="0 20 0 0">
<TextBlock>
- <Run>Remote Version:</Run>
- <Run Text="{Binding RemoteVersion}"></Run>
+ <Run>Remote Versions:</Run>
+ <Run Text="{Binding RemoteVersion}"></Run>,
+ <Run Text="{Binding RemoteFirmwareVersion}"></Run>
</TextBlock>
</TextBlock>
<TextBlock Margin="0 20 0 0">
<TextBlock>
- <Run>Local Version:</Run>
- <Run Text="{Binding LocalVersion}"></Run>
+ <Run>Local Versions:</Run>
+ <Run Text="{Binding LocalVersion}"></Run>,
+ <Run Text="{Binding LocalFirmwareVersion}"></Run>
</TextBlock>
</TextBlock>
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Publisher.UI/MainWindowVM.cs b/Software/Visual_Studio/PPC/Tango.PPC.Publisher.UI/MainWindowVM.cs
index 98b35ed3f..d935c44d2 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Publisher.UI/MainWindowVM.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Publisher.UI/MainWindowVM.cs
@@ -67,6 +67,13 @@ namespace Tango.PPC.Publisher.UI
set { _localVersion = value; RaisePropertyChangedAuto(); }
}
+ private String _localFirmwareVersion;
+ public String LocalFirmwareVersion
+ {
+ get { return _localFirmwareVersion; }
+ set { _localFirmwareVersion = value; RaisePropertyChangedAuto(); }
+ }
+
private String _remoteVersion;
public String RemoteVersion
{
@@ -74,6 +81,13 @@ namespace Tango.PPC.Publisher.UI
set { _remoteVersion = value; RaisePropertyChangedAuto(); }
}
+ private String _remoteFirmwareVersion;
+ public String RemoteFirmwareVersion
+ {
+ get { return _remoteFirmwareVersion; }
+ set { _remoteFirmwareVersion = value; RaisePropertyChangedAuto(); }
+ }
+
private ICollectionView _provisionSequenceItemsView;
public ICollectionView ProvisionSequenceItemsView
{
@@ -127,6 +141,7 @@ namespace Tango.PPC.Publisher.UI
Options.BasicInfoChanged += (_, __) => InvalidateRelayCommands();
Options.EnvironmentChanged += async (_, __) => await OnEnvironmentChanged();
Options.BuidConfigChanged += async (_, __) => await UpdateVersions();
+ Options.TfpPathChanged += async (_, __) => await UpdateVersions();
Init();
}
@@ -165,9 +180,18 @@ namespace Tango.PPC.Publisher.UI
{
IsFree = false;
LocalVersion = _publisher.GetLocalVersion();
+
+ try
+ {
+ LocalFirmwareVersion = _publisher.GetLocalFirmwareVersion(Options.TfpPath);
+ }
+ catch {}
+
if (SelectedMachineVersion != null)
{
- RemoteVersion = await _publisher.GetRemoteVersion(SelectedMachineVersion.Guid);
+ var latestVersion = await _publisher.GetRemoteVersion(SelectedMachineVersion.Guid);
+ RemoteVersion = latestVersion.Version;
+ RemoteFirmwareVersion = latestVersion.FirmwareVersion;
}
InvalidateRelayCommands();
IsFree = true;
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Shared/SQL/RemoteSqlColumn.cs b/Software/Visual_Studio/PPC/Tango.PPC.Shared/SQL/RemoteSqlColumn.cs
index 328dbb492..54431bdbe 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Shared/SQL/RemoteSqlColumn.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Shared/SQL/RemoteSqlColumn.cs
@@ -6,19 +6,47 @@ using System.Threading.Tasks;
namespace Tango.PPC.Shared.SQL
{
+ /// <summary>
+ /// Represents a <see cref="RemoteSqlDataSet"/> column.
+ /// </summary>
public class RemoteSqlColumn
{
+ /// <summary>
+ /// Gets or sets the column name.
+ /// </summary>
public String Name { get; set; }
+
+ /// <summary>
+ /// Gets or sets the column index.
+ /// </summary>
public int Index { get; set; }
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RemoteSqlColumn"/> class.
+ /// </summary>
public RemoteSqlColumn()
{
}
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RemoteSqlColumn"/> class.
+ /// </summary>
+ /// <param name="name">The column name.</param>
public RemoteSqlColumn(String name)
{
Name = name;
}
+
+ /// <summary>
+ /// Returns a <see cref="System.String" /> that represents this instance.
+ /// </summary>
+ /// <returns>
+ /// A <see cref="System.String" /> that represents this instance.
+ /// </returns>
+ public override string ToString()
+ {
+ return Name;
+ }
}
}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Shared/SQL/RemoteSqlColumnCollection.cs b/Software/Visual_Studio/PPC/Tango.PPC.Shared/SQL/RemoteSqlColumnCollection.cs
index 5358e047b..dfda6c3b7 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Shared/SQL/RemoteSqlColumnCollection.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Shared/SQL/RemoteSqlColumnCollection.cs
@@ -7,15 +7,27 @@ using System.Threading.Tasks;
namespace Tango.PPC.Shared.SQL
{
+ /// <summary>
+ /// Represents a <see cref="RemoteSqlDataSet"/> columns collection.
+ /// </summary>
+ /// <seealso cref="System.Collections.ObjectModel.Collection{Tango.PPC.Shared.SQL.RemoteSqlColumn}" />
public class RemoteSqlColumnCollection : Collection<RemoteSqlColumn>
{
private Dictionary<String, RemoteSqlColumn> _dictionary;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RemoteSqlColumnCollection"/> class.
+ /// </summary>
public RemoteSqlColumnCollection()
{
_dictionary = new Dictionary<string, RemoteSqlColumn>();
}
+ /// <summary>
+ /// Inserts an element into the <see cref="T:System.Collections.ObjectModel.Collection`1" /> at the specified index.
+ /// </summary>
+ /// <param name="index">The zero-based index at which <paramref name="item" /> should be inserted.</param>
+ /// <param name="item">The object to insert. The value can be null for reference types.</param>
protected override void InsertItem(int index, RemoteSqlColumn item)
{
item.Index = Count;
@@ -23,22 +35,41 @@ namespace Tango.PPC.Shared.SQL
base.InsertItem(index, item);
}
+ /// <summary>
+ /// Removes the element at the specified index of the <see cref="T:System.Collections.ObjectModel.Collection`1" />.
+ /// </summary>
+ /// <param name="index">The zero-based index of the element to remove.</param>
+ /// <exception cref="NotSupportedException"></exception>
protected override void RemoveItem(int index)
{
throw new NotSupportedException();
}
+ /// <summary>
+ /// Removes all elements from the <see cref="T:System.Collections.ObjectModel.Collection`1" />.
+ /// </summary>
protected override void ClearItems()
{
_dictionary.Clear();
base.ClearItems();
}
+ /// <summary>
+ /// Replaces the element at the specified index.
+ /// </summary>
+ /// <param name="index">The zero-based index of the element to replace.</param>
+ /// <param name="item">The new value for the element at the specified index. The value can be null for reference types.</param>
+ /// <exception cref="NotSupportedException"></exception>
protected override void SetItem(int index, RemoteSqlColumn item)
{
throw new NotSupportedException();
}
+ /// <summary>
+ /// Gets the column index by column name.
+ /// </summary>
+ /// <param name="columnName">Column name.</param>
+ /// <returns></returns>
public int GetIndexOf(String columnName)
{
return _dictionary[columnName].Index;
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Shared/SQL/RemoteSqlDataSet.cs b/Software/Visual_Studio/PPC/Tango.PPC.Shared/SQL/RemoteSqlDataSet.cs
index 089908e5a..72b8d2eb2 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Shared/SQL/RemoteSqlDataSet.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Shared/SQL/RemoteSqlDataSet.cs
@@ -9,17 +9,37 @@ using System.Threading.Tasks;
namespace Tango.PPC.Shared.SQL
{
+ /// <summary>
+ /// Represents remote database query result composed of rows and columns.
+ /// </summary>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to set the connected machine's demo state and query for the connected machine's jobs.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/Sql/Program.cs" title="Remote SQL" region="Example" />
+ /// </example>
public class RemoteSqlDataSet
{
+ /// <summary>
+ /// Gets or sets the dataset columns.
+ /// </summary>
public RemoteSqlColumnCollection Columns { get; set; }
private ObservableCollection<RemoteSqlRow> _rows;
+ /// <summary>
+ /// Gets or sets the dataset rows.
+ /// </summary>
public ObservableCollection<RemoteSqlRow> Rows
{
get { return _rows; }
set { _rows = value; OnRowsChanged(); }
}
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RemoteSqlDataSet"/> class.
+ /// </summary>
public RemoteSqlDataSet()
{
Columns = new RemoteSqlColumnCollection();
@@ -61,6 +81,11 @@ namespace Tango.PPC.Shared.SQL
}
}
+ /// <summary>
+ /// Creates a new <see cref="RemoteSqlDataSet"/> using the specified <see cref="SqlDataReader"/>.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ /// <returns></returns>
public static Task<RemoteSqlDataSet> Load(SqlDataReader reader)
{
return Task.Factory.StartNew<RemoteSqlDataSet>(() =>
@@ -100,11 +125,21 @@ namespace Tango.PPC.Shared.SQL
});
}
+ /// <summary>
+ /// Returns a <see cref="System.String" /> that represents this instance.
+ /// </summary>
+ /// <returns>
+ /// A <see cref="System.String" /> that represents this instance.
+ /// </returns>
public override string ToString()
{
return String.Join(", ", Columns.Select(x => x.Name)) + "\n" + String.Join(Environment.NewLine, Rows.Select(x => x.ToString()));
}
+ /// <summary>
+ /// Formats this dataset as a string with columns and rows.
+ /// </summary>
+ /// <returns></returns>
public String ToTableString()
{
Dictionary<int, int> columnsMaxLength = new Dictionary<int, int>();
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Shared/SQL/RemoteSqlRow.cs b/Software/Visual_Studio/PPC/Tango.PPC.Shared/SQL/RemoteSqlRow.cs
index bf6b0ba0c..dfabacfea 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Shared/SQL/RemoteSqlRow.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Shared/SQL/RemoteSqlRow.cs
@@ -10,28 +10,61 @@ using Tango.BL.Entities;
namespace Tango.PPC.Shared.SQL
{
+ /// <summary>
+ /// Represents a <see cref="RemoteSqlDataSet"/> row.
+ /// </summary>
+ /// <example>
+ /// <para>
+ /// <i>
+ /// The following example demonstrates how to set the connected machine's demo state and query for the connected machine's jobs.
+ /// </i>
+ /// </para>
+ /// <code lang="C#" source="../Tango.FSE.Procedures/Examples/Sql/Program.cs" title="Remote SQL" region="Example" />
+ /// </example>
public class RemoteSqlRow
{
private Func<String, Object> _getFuncKey;
private Func<int, Object> _getFuncIndex;
+ /// <summary>
+ /// Gets or sets the row values.
+ /// </summary>
public List<Object> Values { get; set; }
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RemoteSqlRow"/> class.
+ /// </summary>
public RemoteSqlRow()
{
Values = new List<object>();
}
+ /// <summary>
+ /// Gets a row value by its column name.
+ /// </summary>
+ /// <param name="columnName">Name of the column.</param>
+ /// <returns>The column value.</returns>
public Object Get(String columnName)
{
return _getFuncKey.Invoke(columnName);
}
+ /// <summary>
+ /// Gets a row value by its column index.
+ /// </summary>
+ /// <param name="columnIndex">Index of the column.</param>
+ /// <returns>The column value.</returns>
public Object Get(int columnIndex)
{
return _getFuncIndex.Invoke(columnIndex);
}
+ /// <summary>
+ /// Gets a row value as type T by its column name.
+ /// </summary>
+ /// <typeparam name="T">Expected column type.</typeparam>
+ /// <param name="columnName">Name of the column.</param>
+ /// <returns>The column value.</returns>
public T Get<T>(String columnName)
{
var value = _getFuncKey.Invoke(columnName);
@@ -46,6 +79,12 @@ namespace Tango.PPC.Shared.SQL
}
}
+ /// <summary>
+ /// Gets a row value by its column index.
+ /// </summary>
+ /// <typeparam name="T">Expected column type</typeparam>
+ /// <param name="columnIndex">Index of the column.</param>
+ /// <returns>The column value.</returns>
public T Get<T>(int columnIndex)
{
var value = _getFuncIndex.Invoke(columnIndex);
@@ -66,11 +105,22 @@ namespace Tango.PPC.Shared.SQL
_getFuncIndex = getFuncIndex;
}
+ /// <summary>
+ /// Returns a <see cref="System.String" /> that represents this instance.
+ /// </summary>
+ /// <returns>
+ /// A <see cref="System.String" /> that represents this instance.
+ /// </returns>
public override string ToString()
{
return String.Join(", ", Values);
}
+ /// <summary>
+ /// Creates an object of type T and maps this row to it based on its properties decorated with <see cref="ColumnAttribute"/>.
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <returns></returns>
public T Map<T>() where T : class, new()
{
var obj = Activator.CreateInstance<T>();
@@ -78,6 +128,11 @@ namespace Tango.PPC.Shared.SQL
return obj;
}
+ /// <summary>
+ /// Maps this row to the specified object based on its properties decorated with <see cref="ColumnAttribute"/>.
+ /// </summary>
+ /// <typeparam name="T">Model type</typeparam>
+ /// <param name="obj">The object.</param>
public void Map<T>(T obj) where T : class
{
foreach (var prop in typeof(T).GetPropertiesWithAttribute<ColumnAttribute>())
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Shared/Tango.PPC.Shared.csproj b/Software/Visual_Studio/PPC/Tango.PPC.Shared/Tango.PPC.Shared.csproj
index 10993399c..a0cc9b153 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Shared/Tango.PPC.Shared.csproj
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Shared/Tango.PPC.Shared.csproj
@@ -22,6 +22,8 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
+ <DocumentationFile>..\..\Build\PPC\Debug\Tango.PPC.Shared.xml</DocumentationFile>
+ <NoWarn>1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -30,6 +32,8 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
+ <DocumentationFile>..\..\Build\PPC\Release\Tango.PPC.Shared.xml</DocumentationFile>
+ <NoWarn>1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/App.xaml.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/App.xaml.cs
index ff0b1018b..78536803c 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/App.xaml.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/App.xaml.cs
@@ -17,6 +17,7 @@ using Tango.Integration.Operation;
using Tango.Logging;
using Tango.PPC.Common;
using Tango.PPC.Common.EventLogging;
+using Tango.PPC.Common.Helpers;
using Tango.PPC.Common.Notifications;
using Tango.PPC.Common.WatchDog;
using Tango.Settings;
@@ -39,7 +40,11 @@ namespace Tango.PPC.UI
/// <param name="e">A <see cref="T:System.Windows.StartupEventArgs" /> that contains the event data.</param>
protected override void OnStartup(StartupEventArgs e)
{
- ThreadPool.SetMaxThreads(1000, 1000);
+ //throw new InvalidOperationException("This is a fake exception!!!");
+
+ //removed due to possibly causing this issue:
+ //https://stackoverflow.com/questions/41543956/how-to-debug-not-enough-storage-is-available-to-process-this-command
+ //ThreadPool.SetMaxThreads(1000, 1000);
//If no debugger is attached and the argument -debug was passed launch the debugger.
if (e.Args.Contains("-debug") && !Debugger.IsAttached)
@@ -51,7 +56,10 @@ namespace Tango.PPC.UI
//LogManager.RegisterLogger(new ConsoleLogger("Tango PPC Debug"));
LogManager.RegisterLogger(new FileLogger() { EnableAutoLogRemoval = true, EnableMaxFileSizeLimit = true });
+
+#if DEBUG
LogManager.RegisterLogger(new VSOutputLogger());
+#endif
//Configure machine operator logger.
var operatorLogger = MachineOperator.EmbeddedLogManager.RegisteredLoggers.SingleOrDefault(x => x is FileLogger) as FileLogger;
@@ -61,7 +69,9 @@ namespace Tango.PPC.UI
operatorLogger.EnableMaxFileSizeLimit = true;
}
- LogManager.Log("Application Started...");
+
+ LogsHelper.SetLogSafe(LogManager.CreateLogSafe());
+ LogManager.Log($"Application Started... Version: '{AssemblyHelper.GetCurrentAssemblyVersion()}'.");
base.OnStartup(e);
@@ -77,10 +87,21 @@ namespace Tango.PPC.UI
};
WebRequest.DefaultWebProxy = null;
+
+ GetLastApplicationCrashFromWindows();
}
#region Global Exception Trapping
+ private async void GetLastApplicationCrashFromWindows()
+ {
+ var logItem = await exceptionTrapper.GetLastApplicationCrashEventLog();
+ if (logItem != null)
+ {
+ LogManager.Log(logItem);
+ }
+ }
+
/// <summary>
/// Handles the ApplicationCrashed event of the ExceptionTrapper.
/// </summary>
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs
index 05d844782..b5da9f066 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs
@@ -15,6 +15,7 @@ using Tango.PPC.Common.EventLogging;
using Tango.PPC.Common.ExternalBridge;
using Tango.PPC.Common.FileSystem;
using Tango.PPC.Common.HotSpot;
+using Tango.PPC.Common.Insights;
using Tango.PPC.Common.MachineSetup;
using Tango.PPC.Common.MachineUpdate;
using Tango.PPC.Common.Modules;
@@ -92,6 +93,7 @@ namespace Tango.PPC.UI
TangoIOC.Default.Unregister<IFileSystemService>();
TangoIOC.Default.Unregister<IRemoteJobService>();
TangoIOC.Default.Unregister<IRemoteSqlService>();
+ TangoIOC.Default.Unregister<IInsightsService>();
if (App.StartupArgs != null && App.StartupArgs.Contains("-webDebug"))
{
@@ -132,6 +134,7 @@ namespace Tango.PPC.UI
TangoIOC.Default.Register<IRemoteDesktopService, DefaultRemoteDesktopService>();
TangoIOC.Default.Register<IRemoteJobService, DefaultRemoteJobService>();
TangoIOC.Default.Register<IRemoteSqlService, DefaultRemoteSqlService>();
+ TangoIOC.Default.Register<IInsightsService, DefaultInsightsService>();
TangoIOC.Default.Register<LoadingViewVM>();
TangoIOC.Default.Register<MainViewVM>();
diff --git a/Software/Visual_Studio/Project Templates/Tango FSE Procedure Example.zip b/Software/Visual_Studio/Project Templates/Tango FSE Procedure Example.zip
new file mode 100644
index 000000000..e220c4f8c
--- /dev/null
+++ b/Software/Visual_Studio/Project Templates/Tango FSE Procedure Example.zip
Binary files differ
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Project.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Project.cs
index 8ca64ca18..7500e404f 100644
--- a/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Project.cs
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/Project.cs
@@ -21,6 +21,8 @@ namespace Tango.Scripting.Basic
{
public class Project<T> : ExtendedObject where T : IContext
{
+ private object _compileLock = new object();
+
public String ID { get; set; }
private String _name;
@@ -37,6 +39,22 @@ namespace Tango.Scripting.Basic
set { _description = value; RaisePropertyChangedAuto(); }
}
+ private bool _isRunning;
+ [JsonIgnore]
+ public bool IsRunning
+ {
+ get { return _isRunning; }
+ set { _isRunning = value; RaisePropertyChangedAuto(); }
+ }
+
+ private bool _isCompiling;
+ [JsonIgnore]
+ public bool IsCompiling
+ {
+ get { return _isCompiling; }
+ set { _isCompiling = value; RaisePropertyChangedAuto(); }
+ }
+
public ApartmentState ApartmentState { get; set; }
public ObservableCollection<ReferenceAssembly> ReferenceAssemblies { get; set; }
@@ -52,6 +70,9 @@ namespace Tango.Scripting.Basic
}
}
+ [JsonIgnore]
+ public List<ScriptBreakPoint> BreakPoints { get; set; }
+
public Project()
{
ID = Guid.NewGuid().ToString();
@@ -62,99 +83,121 @@ namespace Tango.Scripting.Basic
Scripts = new ObservableCollection<Script>();
Scripts.CollectionChanged += (x, e) => { RaisePropertyChanged(nameof(AdditionalScripts)); };
+
+ BreakPoints = new List<ScriptBreakPoint>();
}
public Task<CompilationResult> Compile()
{
return Task.Factory.StartNew<CompilationResult>(() =>
{
- var result = new CompilationResult();
- var tempFolder = TemporaryManager.CreateFolder(Name + "_" + ID);
- result.TemporaryProjectPath = tempFolder;
+ lock (_compileLock)
+ {
+ try
+ {
+ IsCompiling = true;
+ var result = new CompilationResult();
+ var tempFolder = TemporaryManager.CreateFolder(Name + "_" + ID);
+ result.TemporaryProjectPath = tempFolder;
- String mainScriptCode = String.Empty;
+ String mainScriptCode = String.Empty;
- foreach (var script in Scripts)
- {
- script.LoadCount = 0;
- script.LoadCharCount = 0;
- String code = script.Code;
- String codeFile = Path.Combine(tempFolder, script.Name);
+ foreach (var script in Scripts)
+ {
+ script.LoadCount = 0;
+ script.LoadCharCount = 0;
+ String code = script.Code;
+ String codeFile = Path.Combine(tempFolder, script.Name);
- String loadingString = String.Empty;
+ String loadingString = String.Empty;
- foreach (var file in Scripts.Where(x => !x.IsEntryPoint && script != x).Select(x => Path.Combine(tempFolder, x.Name)))
- {
- loadingString += $"#load \"{file}\"\n";
- script.LoadCount++;
- }
+ foreach (var file in Scripts.Where(x => !x.IsEntryPoint && script != x).Select(x => Path.Combine(tempFolder, x.Name)))
+ {
+ loadingString += $"#load \"{file}\"\n";
+ script.LoadCount++;
+ }
- script.LoadCharCount += loadingString.Length;
+ script.LoadCharCount += loadingString.Length;
- code = loadingString + code;
+ code = loadingString + code;
- if (!script.IsEntryPoint)
- {
- //In case we use #load
- //foreach (var match in Regex.Matches(code, "#load \".+\"").OfType<Match>())
- //{
- // String line = match.ToString();
- // var pathMatch = Regex.Match(line, "(?<=\")(.*?)(?=\")");
- // if (pathMatch.Success)
- // {
- // String path = pathMatch.ToString();
+ int debugLinesLength = 0;
- // if (!System.IO.Path.IsPathRooted(path))
- // {
- // StringBuilder builder = new StringBuilder(code);
- // builder.Insert(match.Index + pathMatch.Index, System.IO.Path.GetFullPath(tempFolder + "\\"));
- // code = builder.ToString();
- // }
- // }
- //}
- File.WriteAllText(codeFile, code);
- }
- else
- {
- code += Environment.NewLine + Environment.NewLine + "new Program().OnExecute(GlobalContext);";
- mainScriptCode = code;
- }
- }
+ foreach (var breakPoint in BreakPoints.Where(x => x.Script == script).OrderBy(x => x.LineNumber))
+ {
+ var debugLine = $"context.BreakPoint(\"{script.Name}\",{breakPoint.LineNumber}";
- var scriptOptions = ScriptOptions.Default.WithReferences(LoadReferenceAssemblies());
+ foreach (var symbol in breakPoint.ContextSymbols)
+ {
+ debugLine += $",\"{symbol.Name}\",{symbol.Offset},{symbol.Length},{symbol.Name}";
+ }
- var s = CSharpScript.Create<object>(mainScriptCode, scriptOptions, typeof(GlobalObject<T>));
- result.Script = s;
+ debugLine += ");";
- var compileResults = s.Compile();
+ StringBuilder builder = new StringBuilder(code);
+ builder.Insert(breakPoint.LineStartOffset + loadingString.Length + debugLinesLength, debugLine);
+ code = builder.ToString();
- GC.Collect();
+ debugLinesLength += debugLine.Length;
+ }
- foreach (var error in compileResults.Where(x => x.Severity == Microsoft.CodeAnalysis.DiagnosticSeverity.Error))
- {
- CompilationError cError = new CompilationError();
- cError.File = System.IO.Path.GetFileName(error.Location.SourceTree.FilePath);
- if (cError.File == String.Empty)
+ if (!script.IsEntryPoint)
+ {
+ File.WriteAllText(codeFile, code);
+ }
+ else
+ {
+ code += Environment.NewLine + Environment.NewLine + "new Program().OnExecute(GlobalContext);";
+ mainScriptCode = code;
+ }
+ }
+
+ var scriptOptions = ScriptOptions.Default.WithReferences(LoadReferenceAssemblies()).WithEmitDebugInformation(true);
+
+ var s = CSharpScript.Create<object>(mainScriptCode, scriptOptions, typeof(GlobalObject<T>));
+
+ result.Script = s;
+
+ var compileResults = s.Compile();
+
+ GC.Collect();
+
+ foreach (var error in compileResults.Where(x => x.Severity == Microsoft.CodeAnalysis.DiagnosticSeverity.Error))
+ {
+ CompilationError cError = new CompilationError();
+ cError.File = System.IO.Path.GetFileName(error.Location.SourceTree.FilePath);
+ if (cError.File == String.Empty)
+ {
+ cError.File = Scripts.Single(x => x.IsEntryPoint).Name;
+ }
+ Script errorScript = Scripts.Single(x => x.Name == cError.File);
+ cError.Message = error.GetMessage();
+ cError.Severity = error.Severity;
+ cError.Position = error.Location.SourceSpan.Start - (errorScript != null ? errorScript.LoadCharCount : 0);
+ var line = error.Location.GetMappedLineSpan();
+ cError.Line = line.StartLinePosition.Line + 1 - (errorScript != null ? errorScript.LoadCount : 0);
+ cError.Column = line.StartLinePosition.Character + 1;
+ cError.Length = line.EndLinePosition.Character - line.StartLinePosition.Character;
+ result.Errors.Add(cError);
+ }
+
+ return result;
+ }
+ catch (Exception)
+ {
+ throw;
+ }
+ finally
{
- cError.File = Scripts.Single(x => x.IsEntryPoint).Name;
+ IsCompiling = false;
}
- Script errorScript = Scripts.Single(x => x.Name == cError.File);
- cError.Message = error.GetMessage();
- cError.Severity = error.Severity;
- cError.Position = error.Location.SourceSpan.Start - (errorScript != null ? errorScript.LoadCharCount : 0);
- var line = error.Location.GetMappedLineSpan();
- cError.Line = line.StartLinePosition.Line + 1 - (errorScript != null ? errorScript.LoadCount : 0);
- cError.Column = line.StartLinePosition.Character + 1;
- cError.Length = line.EndLinePosition.Character - line.StartLinePosition.Character;
- result.Errors.Add(cError);
}
-
- return result;
});
}
public async Task<ProjectSession<T>> Run(T context)
{
+ IsRunning = true;
var result = await Compile();
if (result.Errors.Count > 0)
@@ -175,6 +218,7 @@ namespace Tango.Scripting.Basic
try
{
var runResult = result.Script.RunAsync(globals: new GlobalObject<T>() { GlobalContext = context }).Result;
+ IsRunning = false;
session.Completed(runResult.ReturnValue);
}
catch (ThreadAbortException)
@@ -187,7 +231,9 @@ namespace Tango.Scripting.Basic
}
finally
{
+ BreakPoints.Clear();
GC.Collect();
+ IsRunning = false;
}
});
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Core/BreakPoint.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Core/BreakPoint.cs
new file mode 100644
index 000000000..e847ea03e
--- /dev/null
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Core/BreakPoint.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.Scripting.Core
+{
+ public class BreakPoint
+ {
+ public int LineNumber { get; set; }
+ public bool IsActive { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Core/ScriptBreakPoint.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Core/ScriptBreakPoint.cs
new file mode 100644
index 000000000..626c1abc6
--- /dev/null
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Core/ScriptBreakPoint.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Scripting.Core;
+
+namespace Tango.Scripting.Core
+{
+ public class ScriptBreakPoint
+ {
+ public IScriptSource Script { get; set; }
+ public int LineNumber { get; set; }
+ public int LineStartOffset { get; set; }
+ public int LineEndOffset { get; set; }
+ public List<ScriptBreakPointSymbol> ContextSymbols { get; set; }
+
+ public ScriptBreakPoint()
+ {
+ ContextSymbols = new List<ScriptBreakPointSymbol>();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Core/ScriptBreakPointSymbol.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Core/ScriptBreakPointSymbol.cs
new file mode 100644
index 000000000..8da35fe55
--- /dev/null
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Core/ScriptBreakPointSymbol.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.Scripting.Core
+{
+ public class ScriptBreakPointSymbol
+ {
+ public String Name { get; set; }
+ public int Offset { get; set; }
+ public int Length { get; set; }
+ public Object SymbolObject { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Core/Tango.Scripting.Core.csproj b/Software/Visual_Studio/Scripting/Tango.Scripting.Core/Tango.Scripting.Core.csproj
index aa4bbb240..bb623a4fe 100644
--- a/Software/Visual_Studio/Scripting/Tango.Scripting.Core/Tango.Scripting.Core.csproj
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Core/Tango.Scripting.Core.csproj
@@ -41,8 +41,11 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="BreakPoint.cs" />
<Compile Include="IScriptSource.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="ScriptBreakPoint.cs" />
+ <Compile Include="ScriptBreakPointSymbol.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/BreakPointSymbolPressedEventArgs.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/BreakPointSymbolPressedEventArgs.cs
new file mode 100644
index 000000000..1728bb565
--- /dev/null
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/BreakPointSymbolPressedEventArgs.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using Tango.Scripting.Core;
+
+namespace Tango.Scripting.Editors
+{
+ public class BreakPointSymbolPressedEventArgs : EventArgs
+ {
+ public ScriptBreakPointSymbol BreakPointSymbol { get; set; }
+ public Point Position { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Editing/BreakPointMargin.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Editing/BreakPointMargin.cs
new file mode 100644
index 000000000..e566e6aa9
--- /dev/null
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Editing/BreakPointMargin.cs
@@ -0,0 +1,285 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Media.TextFormatting;
+using Tango.Scripting.Core;
+using Tango.Scripting.Editors.Document;
+using Tango.Scripting.Editors.Rendering;
+using Tango.Scripting.Editors.Utils;
+
+namespace Tango.Scripting.Editors.Editing
+{
+ public class BreakPointMargin : AbstractMargin, IWeakEventListener
+ {
+ private TextArea textArea;
+ private int maxLineNumberLength = 1;
+ private BitmapSource _arrowBitmap;
+ private ScriptEditor _editor;
+
+ public ObservableCollection<BreakPoint> BreakPoints { get; set; }
+
+ public Brush Background
+ {
+ get { return (Brush)GetValue(BackgroundProperty); }
+ set { SetValue(BackgroundProperty, value); }
+ }
+ public static readonly DependencyProperty BackgroundProperty =
+ DependencyProperty.Register("Background", typeof(Brush), typeof(BreakPointMargin), new PropertyMetadata(new SolidColorBrush(Color.FromRgb(50, 50, 50))));
+
+ public Brush Foreground
+ {
+ get { return (Brush)GetValue(ForegroundProperty); }
+ set { SetValue(ForegroundProperty, value); }
+ }
+ public static readonly DependencyProperty ForegroundProperty =
+ DependencyProperty.Register("Foreground", typeof(Brush), typeof(BreakPointMargin), new PropertyMetadata(Brushes.Red));
+
+ static BreakPointMargin()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(BreakPointMargin),
+ new FrameworkPropertyMetadata(typeof(BreakPointMargin)));
+ }
+
+ public BreakPointMargin(ScriptEditor editor)
+ {
+ _editor = editor;
+ BreakPoints = new ObservableCollection<BreakPoint>();
+ BreakPoints.CollectionChanged += BreakPoints_CollectionChanged;
+ RenderOptions.SetEdgeMode(this, EdgeMode.Unspecified);
+
+ _arrowBitmap = new BitmapImage(new Uri($"pack://application:,,,/Tango.Scripting.Editors;component/Images/break_point_arrow.png", UriKind.Absolute));
+ }
+
+ private void BreakPoints_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
+ {
+ InvalidateVisual();
+ }
+
+ protected override Size MeasureOverride(Size availableSize)
+ {
+ return new Size(20, 0);
+ }
+
+ protected override void OnRender(DrawingContext drawingContext)
+ {
+ TextView textView = this.TextView;
+ Size renderSize = this.RenderSize;
+ if (textView != null && textView.VisualLinesValid)
+ {
+ drawingContext.DrawRectangle(Background, new Pen(Background, 1), new Rect(0, 0, ActualWidth, ActualHeight));
+
+ var foreground = Foreground;
+ foreach (VisualLine line in textView.VisualLines)
+ {
+ int lineNumber = line.FirstDocumentLine.LineNumber;
+
+ BreakPoint b = BreakPoints.FirstOrDefault(x => x.LineNumber == lineNumber);
+
+ if (b != null)
+ {
+ double y = line.GetTextLineVisualYPosition(line.TextLines[0], VisualYPosition.TextTop);
+ drawingContext.DrawEllipse(Foreground, new Pen(Brushes.Gainsboro, 1), new Point(10, y - textView.VerticalOffset + 8), 6, 6);
+
+ if (b.IsActive)
+ {
+ drawingContext.DrawImage(_arrowBitmap, new Rect(6, y - textView.VerticalOffset + 2.5, 8.5, 10));
+ }
+ }
+ }
+ }
+ }
+
+ protected override void OnTextViewChanged(TextView oldTextView, TextView newTextView)
+ {
+ if (oldTextView != null)
+ {
+ oldTextView.VisualLinesChanged -= TextViewVisualLinesChanged;
+ }
+ base.OnTextViewChanged(oldTextView, newTextView);
+ if (newTextView != null)
+ {
+ newTextView.VisualLinesChanged += TextViewVisualLinesChanged;
+
+ // find the text area belonging to the new text view
+ textArea = newTextView.Services.GetService(typeof(TextArea)) as TextArea;
+ }
+ else
+ {
+ textArea = null;
+ }
+ InvalidateVisual();
+ }
+
+ protected override void OnDocumentChanged(TextDocument oldDocument, TextDocument newDocument)
+ {
+ if (oldDocument != null)
+ {
+ PropertyChangedEventManager.RemoveListener(oldDocument, this, "LineCount");
+ }
+ base.OnDocumentChanged(oldDocument, newDocument);
+ if (newDocument != null)
+ {
+ PropertyChangedEventManager.AddListener(newDocument, this, "LineCount");
+ }
+ OnDocumentLineCountChanged();
+ }
+
+ protected virtual bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
+ {
+ if (managerType == typeof(PropertyChangedEventManager))
+ {
+ OnDocumentLineCountChanged();
+ return true;
+ }
+ return false;
+ }
+
+ bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
+ {
+ return ReceiveWeakEvent(managerType, sender, e);
+ }
+
+ private void OnDocumentLineCountChanged()
+ {
+ int documentLineCount = Document != null ? Document.LineCount : 1;
+ int newLength = documentLineCount.ToString(CultureInfo.CurrentCulture).Length;
+
+ foreach (var breakPoint in BreakPoints.ToList())
+ {
+ if (breakPoint.LineNumber > documentLineCount)
+ {
+ BreakPoints.Remove(breakPoint);
+ }
+ else
+ {
+ try
+ {
+ var line = Document.GetLineByNumber(breakPoint.LineNumber);
+ if (line != null)
+ {
+ String lineText = Document.GetText(line.Offset, line.Length);
+ if (!IsBreakPointValid(lineText))
+ {
+ BreakPoints.Remove(breakPoint);
+ }
+ }
+ }
+ catch { }
+ }
+ }
+
+ // The margin looks too small when there is only one digit, so always reserve space for
+ // at least two digits
+ if (newLength < 2)
+ newLength = 2;
+
+ if (newLength != maxLineNumberLength)
+ {
+ maxLineNumberLength = newLength;
+ InvalidateMeasure();
+ }
+ }
+
+ private void TextViewVisualLinesChanged(object sender, EventArgs e)
+ {
+ InvalidateVisual();
+ }
+
+ protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
+ {
+ // accept clicks even when clicking on the background
+ return new PointHitTestResult(this, hitTestParameters.HitPoint);
+ }
+
+ private VisualLine GetLineNumberByMousePosition(MouseEventArgs e)
+ {
+ Point pos = e.GetPosition(TextView);
+ pos.X = 0;
+ pos.Y += TextView.VerticalOffset;
+ VisualLine vl = TextView.GetVisualLineFromVisualTop(pos.Y);
+ return vl;
+ }
+
+ private bool IsBreakPointValid(String lineText)
+ {
+ if (lineText.EndsWith(";") && !lineText.StartsWith("using"))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ protected override void OnPreviewMouseMove(MouseEventArgs e)
+ {
+ base.OnPreviewMouseMove(e);
+
+ if (_editor.DisableBreakPoints)
+ {
+ Cursor = Cursors.No;
+ }
+ else
+ {
+ Cursor = Cursors.Arrow;
+ }
+ }
+
+ protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
+ {
+ base.OnMouseLeftButtonDown(e);
+
+ if (_editor.DisableBreakPoints)
+ {
+ return;
+ }
+
+ try
+ {
+ if (!e.Handled && TextView != null && textArea != null)
+ {
+ e.Handled = true;
+ textArea.Focus();
+
+ var visualLine = GetLineNumberByMousePosition(e);
+
+ int? lineNumber = visualLine != null ? (int?)visualLine.FirstDocumentLine.LineNumber : null;
+
+ if (lineNumber != null)
+ {
+ var breakPoint = BreakPoints.FirstOrDefault(x => x.LineNumber == lineNumber.Value);
+ if (breakPoint != null)
+ {
+ BreakPoints.Remove(breakPoint);
+ }
+ else
+ {
+ var lineText = Document.GetText(visualLine.FirstDocumentLine.Offset, visualLine.FirstDocumentLine.Length).Trim();
+
+ if (IsBreakPointValid(lineText))
+ {
+ BreakPoint newBreakPoint = new BreakPoint();
+ newBreakPoint.LineNumber = lineNumber.Value;
+ BreakPoints.Add(newBreakPoint);
+ }
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine(ex);
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/Resources/CSharp-Mode.xshd b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/Resources/CSharp-Mode.xshd
index 6f400c4f5..1f6139ff6 100644
--- a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/Resources/CSharp-Mode.xshd
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Highlighting/Resources/CSharp-Mode.xshd
@@ -11,7 +11,7 @@
<Color name="InterfaceTypes" foreground="#B5CE8A" exampleText="object o;" />
<Color name="MethodCall" foreground="Gainsboro" exampleText="o.ToString();"/>
<Color name="NumberLiteral" foreground="#B5CE8A" exampleText="3.1415f"/>
- <Color name="ThisOrBaseReference" exampleText="this.Do(); base.Do();"/>
+ <Color name="ThisOrBaseReference" foreground="#3F8FD6" exampleText="this.Do(); base.Do();"/>
<Color name="NullOrValueKeywords" exampleText="if (value == null)"/>
<Color name="Keywords" foreground="#3F8FD6" exampleText="if (a) {} else {}"/>
<Color name="GotoKeywords" foreground="#3F8FD6" exampleText="continue; return null;"/>
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Images/break_point_arrow.png b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Images/break_point_arrow.png
new file mode 100644
index 000000000..e8d367028
--- /dev/null
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Images/break_point_arrow.png
Binary files differ
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/HideIntellisenseAttribute.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/HideIntellisenseAttribute.cs
new file mode 100644
index 000000000..548bd909e
--- /dev/null
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/HideIntellisenseAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.Scripting.Editors.Intellisense
+{
+ public class HideIntellisenseAttribute : Attribute
+ {
+ }
+}
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/KnownType.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/KnownType.cs
index 3dc796152..c2e7ac422 100644
--- a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/KnownType.cs
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Intellisense/KnownType.cs
@@ -137,6 +137,8 @@ namespace Tango.Scripting.Editors.Intellisense
{
var method = methods[i];
+ if (method.GetCustomAttribute<HideIntellisenseAttribute>() != null) continue;
+
KnownTypeMethod m = new KnownTypeMethod(this);
m.Name = method.Name;
m.ReturnType = method.ReturnType;
@@ -183,17 +185,14 @@ namespace Tango.Scripting.Editors.Intellisense
//Load Properties
{
- if (Type == typeof(Color))
- {
-
- }
-
var properties = Type.GetProperties(BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static).ToList();
for (int i = 0; i < properties.Count; i++)
{
var property = properties[i];
+ if (property.GetCustomAttribute<HideIntellisenseAttribute>() != null) continue;
+
KnownTypeProperty p = new KnownTypeProperty(this);
p.Name = property.Name;
p.ReturnType = property.PropertyType;
@@ -211,6 +210,8 @@ namespace Tango.Scripting.Editors.Intellisense
{
var ev = events[i];
+ if (ev.GetCustomAttribute<HideIntellisenseAttribute>() != null) continue;
+
KnownTypeEvent p = new KnownTypeEvent(this);
p.Name = ev.Name;
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ScriptEditor.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ScriptEditor.cs
index 0802cf456..6c248b63d 100644
--- a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ScriptEditor.cs
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/ScriptEditor.cs
@@ -47,7 +47,10 @@ namespace Tango.Scripting.Editors
private char[] word_separators = { ' ', '\t', '\n', '.', '(', ',', '-', '*', '/', '+', '$', '=', '<', '>' };
private string[] _blocking_type_words = { "class", "void" };
+ public event EventHandler<BreakPointSymbolPressedEventArgs> BreakPointSymbolPressed;
+
private DispatcherTimer _update_timer;
+ private BreakPointMargin breakPointMargin;
private Popup _popup;
private FoldingManager foldingManager;
private BraceFoldingStrategy foldingStrategy;
@@ -58,6 +61,11 @@ namespace Tango.Scripting.Editors
private List<ScriptType> _declaredTypes;
private bool _isLoadingTypes;
private TextMarkerService errorMarkerService;
+ private List<ScriptBreakPointSymbol> _breakPointSymbols;
+ private int _breakPointLineNumber;
+ private ScriptBreakPointSymbol _currentBreakPointSymbol;
+ private Point _currentBreakPointSymbolPosition;
+
private static JsonSerializerSettings _jsonSettings;
private static Dictionary<Type, KnownType> _knownTypesCache;
private static String KNOWN_TYPES_CACHE_FOLDER;
@@ -191,6 +199,47 @@ namespace Tango.Scripting.Editors
public static readonly DependencyProperty ColorizeBrushProperty =
DependencyProperty.Register("ColorizeBrush", typeof(Brush), typeof(ScriptEditor), new PropertyMetadata(new SolidColorBrush(Colors.YellowGreen) { Opacity = 0.5 }));
+ public Brush ErrorLineBrush
+ {
+ get { return (Brush)GetValue(ErrorLineBrushProperty); }
+ set { SetValue(ErrorLineBrushProperty, value); }
+ }
+ public static readonly DependencyProperty ErrorLineBrushProperty =
+ DependencyProperty.Register("ErrorLineBrush", typeof(Brush), typeof(ScriptEditor), new PropertyMetadata(new SolidColorBrush(Colors.Red) { Opacity = 0.5 }));
+
+ public Brush DebugLineBrush
+ {
+ get { return (Brush)GetValue(DebugLineBrushProperty); }
+ set { SetValue(DebugLineBrushProperty, value); }
+ }
+ public static readonly DependencyProperty DebugLineBrushProperty =
+ DependencyProperty.Register("DebugLineBrush", typeof(Brush), typeof(ScriptEditor), new PropertyMetadata(new SolidColorBrush(Colors.Gray) { Opacity = 0.5 }));
+
+ public Brush BreakPointLineBrush
+ {
+ get { return (Brush)GetValue(BreakPointLineBrushProperty); }
+ set { SetValue(BreakPointLineBrushProperty, value); }
+ }
+ public static readonly DependencyProperty BreakPointLineBrushProperty =
+ DependencyProperty.Register("BreakPointLineBrush", typeof(Brush), typeof(ScriptEditor), new PropertyMetadata(new SolidColorBrush(Colors.Yellow) { Opacity = 0.5 }));
+
+ public IScriptSource ScriptSource
+ {
+ get { return (IScriptSource)GetValue(ScriptSourceProperty); }
+ set { SetValue(ScriptSourceProperty, value); }
+ }
+ public static readonly DependencyProperty ScriptSourceProperty =
+ DependencyProperty.Register("ScriptSource", typeof(IScriptSource), typeof(ScriptEditor), new PropertyMetadata(null));
+
+ public bool DisableBreakPoints
+ {
+ get { return (bool)GetValue(DisableBreakPointsProperty); }
+ set { SetValue(DisableBreakPointsProperty, value); }
+ }
+ public static readonly DependencyProperty DisableBreakPointsProperty =
+ DependencyProperty.Register("DisableBreakPoints", typeof(bool), typeof(ScriptEditor), new PropertyMetadata(false));
+
+
#endregion
#region Constructors
@@ -329,6 +378,17 @@ namespace Tango.Scripting.Editors
TextArea.TextView.LineTransformers.Add(errorMarkerService);
Unloaded += ScriptEditor_Unloaded;
+
+ breakPointMargin = new BreakPointMargin(this);
+ _breakPointSymbols = new List<ScriptBreakPointSymbol>();
+ Loaded += ScriptEditor_Loaded;
+
+ MouseMove += ScriptEditor_MouseMove;
+ }
+
+ private void ScriptEditor_Loaded(object sender, RoutedEventArgs e)
+ {
+ TextArea.LeftMargins.Insert(0, breakPointMargin);
}
private void ScriptEditor_Unloaded(object sender, RoutedEventArgs e)
@@ -492,6 +552,8 @@ namespace Tango.Scripting.Editors
private void TextArea_TextEntered(object sender, TextCompositionEventArgs e)
{
+ if (IsReadOnly) return;
+
try
{
List<Object> items = new List<object>();
@@ -2486,6 +2548,246 @@ namespace Tango.Scripting.Editors
errorMarkerService.RemoveAll(m => true);
}
+ public void HighlightErrorLine(int lineNumber)
+ {
+ Document.BeginUpdate();
+
+ var line = Document.GetLineByNumber(lineNumber);
+ OffsetColorizer errorLineColrizer = new OffsetColorizer(line, line.Offset, line.EndOffset, ErrorLineBrush);
+ TextArea.TextView.LineTransformers.Add(errorLineColrizer);
+
+ Document.EndUpdate();
+ }
+
+ public void HighlightDebugLine(int lineNumber)
+ {
+ Document.BeginUpdate();
+
+ var line = Document.GetLineByNumber(lineNumber);
+ OffsetColorizer errorLineColrizer = new OffsetColorizer(line, line.Offset, line.EndOffset, DebugLineBrush);
+ TextArea.TextView.LineTransformers.Add(errorLineColrizer);
+
+ Document.EndUpdate();
+ }
+
+ public void HighlightBreakPoint(int lineNumber, List<ScriptBreakPointSymbol> symbols)
+ {
+ _breakPointLineNumber = lineNumber;
+ _breakPointSymbols = symbols.ToList();
+ _currentBreakPointSymbol = null;
+
+ Document.BeginUpdate();
+
+ var line = Document.GetLineByNumber(lineNumber);
+ OffsetColorizer errorLineColrizer = new OffsetColorizer(line, line.Offset, line.EndOffset, BreakPointLineBrush);
+ TextArea.TextView.LineTransformers.Add(errorLineColrizer);
+
+ var breakPoint = breakPointMargin.BreakPoints.FirstOrDefault(x => x.LineNumber == lineNumber);
+ breakPoint.IsActive = true;
+ breakPointMargin.InvalidateVisual();
+
+ Document.EndUpdate();
+ }
+
+ public void ResetBreakPointLine()
+ {
+ _breakPointSymbols = new List<ScriptBreakPointSymbol>();
+ _currentBreakPointSymbol = null;
+ ResetColorizationByKeyword();
+ breakPointMargin.BreakPoints.ToList().ForEach(x => x.IsActive = false);
+ Mouse.OverrideCursor = null;
+ ClearErrors();
+ breakPointMargin.InvalidateVisual();
+ }
+
+ public Point? GetLineVisualPosition(int lineNumber)
+ {
+ double top = TextArea.TextView.GetVisualTopByDocumentLine(lineNumber);
+ var visualLine = TextArea.TextView.GetVisualLine(lineNumber);
+
+ if (visualLine != null)
+ {
+ var textLine = visualLine.GetTextLine(0);
+ var x = visualLine.GetTextLineVisualXPosition(textLine, visualLine.VisualLengthWithEndOfLineMarker);
+ var left = visualLine.VisualLengthWithEndOfLineMarker;
+ return new Point(x, top);
+ }
+
+ return null;
+ }
+
+ public List<ScriptBreakPoint> GetBreakPoints()
+ {
+ List<ScriptBreakPoint> breakPoints = new List<ScriptBreakPoint>();
+
+ foreach (var b in breakPointMargin.BreakPoints)
+ {
+ ScriptBreakPoint breakPoint = new ScriptBreakPoint();
+ breakPoint.Script = ScriptSource;
+ breakPoint.LineNumber = b.LineNumber;
+
+ var line = Document.GetLineByNumber(b.LineNumber);
+ breakPoint.LineStartOffset = line.Offset;
+ breakPoint.LineEndOffset = line.EndOffset;
+
+ var symbols = _parser.GetContextSymbols(Document.Text, line.Offset);
+
+ foreach (var symbol in symbols.Where(x => (x.Kind == SymbolKind.Property || x.Kind == SymbolKind.Field || x.Kind == SymbolKind.Local || x.Kind == SymbolKind.Parameter) && !x.IsUnassigned))
+ {
+ if (symbol.Offset < line.Offset)
+ {
+ breakPoint.ContextSymbols.Add(new ScriptBreakPointSymbol()
+ {
+ Name = symbol.Name,
+ Offset = symbol.Offset,
+ Length = symbol.Length,
+ });
+ }
+ }
+
+ breakPoints.Add(breakPoint);
+ }
+
+ return breakPoints;
+ }
+
+ #endregion
+
+ #region BreakPoint Symbols Search
+
+ private void ScriptEditor_MouseMove(object sender, MouseEventArgs e)
+ {
+ if (IsReadOnly && _breakPointSymbols.Count > 0)
+ {
+ try
+ {
+ var word_separators_plus = word_separators.ToList();
+ word_separators_plus.Add(')');
+ word_separators_plus.Add(';');
+
+ var textView = TextArea.TextView;
+ Point position = e.GetPosition(textView);
+ position.Y += textView.VerticalOffset;
+ VisualLine visualLine = textView.GetVisualLineFromVisualTop(position.Y);
+ int columnIndex = visualLine.GetVisualColumnFloor(position, false);
+ String line = Document.GetText(visualLine.FirstDocumentLine.Offset, visualLine.FirstDocumentLine.Length);
+ if (columnIndex < line.Length)
+ {
+ int wordStartIndex = columnIndex;
+ int wordEndIndex = columnIndex;
+
+ while (wordStartIndex > 0)
+ {
+ if (word_separators_plus.Contains(line[wordStartIndex])) break;
+ wordStartIndex--;
+ }
+
+ while (wordEndIndex < line.Length)
+ {
+ if (word_separators_plus.Contains(line[wordEndIndex])) break;
+ wordEndIndex++;
+ }
+
+ if (wordStartIndex > 0)
+ {
+ wordStartIndex++;
+ }
+
+ String word = line.Substring(wordStartIndex, wordEndIndex - wordStartIndex);
+
+ var breakPointSymbol = _breakPointSymbols.FirstOrDefault(x => x.Name == word);
+
+ if (breakPointSymbol != null)
+ {
+ int wordStartOffset = visualLine.FirstDocumentLine.Offset + wordStartIndex;
+
+ ClearErrors();
+ ITextMarker marker = errorMarkerService.Create(wordStartOffset, word.Length);
+ marker.MarkerTypes = TextMarkerTypes.NormalUnderline;
+ marker.MarkerColor = Colors.Yellow;
+ Mouse.OverrideCursor = Cursors.Hand;
+
+ _currentBreakPointSymbol = breakPointSymbol;
+ _currentBreakPointSymbolPosition = visualLine.GetVisualPosition(wordEndIndex, VisualYPosition.LineTop);
+ }
+ else
+ {
+ _currentBreakPointSymbol = null;
+ Mouse.OverrideCursor = null;
+ ClearErrors();
+ }
+ }
+ else
+ {
+ _currentBreakPointSymbol = null;
+ Mouse.OverrideCursor = null;
+ ClearErrors();
+ }
+ }
+ catch (Exception ex)
+ {
+ _currentBreakPointSymbol = null;
+ Mouse.OverrideCursor = null;
+ ClearErrors();
+ Debug.WriteLine(ex.Message);
+ }
+ }
+ }
+
+ protected override void OnPreviewMouseLeftButtonUp(MouseButtonEventArgs e)
+ {
+ base.OnPreviewMouseLeftButtonUp(e);
+
+ if (_currentBreakPointSymbol != null)
+ {
+ Mouse.OverrideCursor = null;
+ Debug.WriteLine($"Pressed on break point symbol: {_currentBreakPointSymbol.Name}");
+ BreakPointSymbolPressed?.Invoke(this, new BreakPointSymbolPressedEventArgs()
+ {
+ BreakPointSymbol = _currentBreakPointSymbol,
+ Position = _currentBreakPointSymbolPosition
+ });
+ }
+ }
+
+ public String GetCaretWord()
+ {
+ try
+ {
+ var word_separators_plus = word_separators.ToList();
+ word_separators_plus.Add(')');
+ word_separators_plus.Add(';');
+
+ int wordStartOffset = CaretOffset;
+ int wordEndOffset = CaretOffset;
+
+ while (wordStartOffset > 0)
+ {
+ if (word_separators_plus.Contains(Document.Text[wordStartOffset])) break;
+ wordStartOffset--;
+ }
+
+ while (wordEndOffset < Document.Text.Length)
+ {
+ if (word_separators_plus.Contains(Document.Text[wordEndOffset])) break;
+ wordEndOffset++;
+ }
+
+ if (wordStartOffset > 0)
+ {
+ wordStartOffset++;
+ }
+
+ String word = Document.Text.Substring(wordStartOffset, wordEndOffset - wordStartOffset);
+
+ return word;
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
#endregion
}
}
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Tango.Scripting.Editors.csproj b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Tango.Scripting.Editors.csproj
index a70bbf3de..11e023f86 100644
--- a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Tango.Scripting.Editors.csproj
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Tango.Scripting.Editors.csproj
@@ -180,6 +180,7 @@
<Link>GlobalVersionInfo.cs</Link>
</Compile>
<Compile Include="AvalonEditCommands.cs" />
+ <Compile Include="BreakPointSymbolPressedEventArgs.cs" />
<Compile Include="CachedAssembly.cs" />
<Compile Include="CachedUsing.cs" />
<Compile Include="CodeCompletion\CompletionListBox.cs" />
@@ -196,6 +197,7 @@
<Compile Include="CodeCompletion\OverloadViewer.cs" />
<Compile Include="Converters\BooleanToVisibilityConverter.cs" />
<Compile Include="Converters\BooleanToVisibilityInversedConverter.cs" />
+ <Compile Include="Editing\BreakPointMargin.cs" />
<Compile Include="Errors\ITextMarker.cs" />
<Compile Include="Errors\TextMarkerService.cs" />
<Compile Include="ExtensionMethods.cs" />
@@ -207,6 +209,7 @@
<Compile Include="Intellisense\EventCompletionItem.cs" />
<Compile Include="Intellisense\FieldCompletionItem.cs" />
<Compile Include="Intellisense\FieldCompletionItemPopup.cs" />
+ <Compile Include="Intellisense\HideIntellisenseAttribute.cs" />
<Compile Include="Intellisense\ICompletionItem.cs" />
<Compile Include="Intellisense\ICompletionProvider.cs" />
<Compile Include="Intellisense\InterfaceCompletionItem.cs" />
@@ -651,6 +654,9 @@
<ItemGroup>
<Resource Include="Images\snippet.png" />
</ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\break_point_arrow.png" />
+ </ItemGroup>
<ProjectExtensions>
<VisualStudio>
<UserProperties BuildVersion_StartDate="2000/1/1" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" BuildVersion_UseGlobalSettings="True" />
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Tango.Scripting.Editors_di35u2uj_wpftmp.csproj b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Tango.Scripting.Editors_di35u2uj_wpftmp.csproj
new file mode 100644
index 000000000..70a4840c4
--- /dev/null
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Tango.Scripting.Editors_di35u2uj_wpftmp.csproj
@@ -0,0 +1,628 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <ProjectGuid>{DA62FA39-668B-47A6-B0F2-D2C1DAF777B0}</ProjectGuid>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <OutputType>Library</OutputType>
+ <RootNamespace>Tango.Scripting.Editors</RootNamespace>
+ <AssemblyName>Tango.Scripting.Editors</AssemblyName>
+ <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <SourceAnalysisOverrideSettingsFile>"C:\Program Files\SharpDevelop\3.0\bin\..\AddIns\AddIns\Misc\SourceAnalysis\Settings.SourceAnalysis"</SourceAnalysisOverrideSettingsFile>
+ <AllowUnsafeBlocks>False</AllowUnsafeBlocks>
+ <NoStdLib>False</NoStdLib>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
+ <SignAssembly>false</SignAssembly>
+ <AssemblyOriginatorKeyFile>ICSharpCode.AvalonEdit.snk</AssemblyOriginatorKeyFile>
+ <DelaySign>False</DelaySign>
+ <AssemblyOriginatorKeyMode>File</AssemblyOriginatorKeyMode>
+ <RunCodeAnalysis>False</RunCodeAnalysis>
+ <CodeAnalysisRules>-Microsoft.Design#CA1020;-Microsoft.Design#CA1033;-Microsoft.Performance#CA1805;-Microsoft.Performance#CA1810</CodeAnalysisRules>
+ <OutputPath>..\bin\$(Configuration)</OutputPath>
+ <DocumentationFile>..\bin\$(Configuration)\ICSharpCode.AvalonEdit.xml</DocumentationFile>
+ <NoWarn>1607</NoWarn>
+ <TargetFrameworkProfile>
+ </TargetFrameworkProfile>
+ <SccProjectName>SAK</SccProjectName>
+ <SccLocalPath>SAK</SccLocalPath>
+ <SccAuxPath>SAK</SccAuxPath>
+ <SccProvider>SAK</SccProvider>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>Full</DebugType>
+ <Optimize>False</Optimize>
+ <CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
+ <DefineConstants>DEBUG;TRACE;DOTNET4</DefineConstants>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
+ <DebugSymbols>false</DebugSymbols>
+ <DebugType>PdbOnly</DebugType>
+ <Optimize>True</Optimize>
+ <CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
+ <DefineConstants>TRACE;DOTNET4</DefineConstants>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' ">
+ <RegisterForComInterop>False</RegisterForComInterop>
+ <GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
+ <BaseAddress>4194304</BaseAddress>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <FileAlignment>4096</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
+ <OutputPath>..\..\Build\Scripting\Debug\</OutputPath>
+ <DocumentationFile>
+ </DocumentationFile>
+ <Prefer32Bit>false</Prefer32Bit>
+ <DefineConstants>TRACE;DEBUG</DefineConstants>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
+ <Prefer32Bit>false</Prefer32Bit>
+ <OutputPath>..\..\Build\Scripting\Release\</OutputPath>
+ <DocumentationFile />
+ </PropertyGroup>
+ <PropertyGroup>
+ <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ </PropertyGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\..\Versioning\GlobalVersionInfo.cs">
+ <Link>GlobalVersionInfo.cs</Link>
+ </Compile>
+ <Compile Include="AvalonEditCommands.cs" />
+ <Compile Include="CachedAssembly.cs" />
+ <Compile Include="CachedUsing.cs" />
+ <Compile Include="CodeCompletion\CompletionListBox.cs" />
+ <Compile Include="CodeCompletion\CompletionListBoxItem.cs" />
+ <Compile Include="CodeCompletion\CompletionWindowBase.cs" />
+ <Compile Include="CodeCompletion\CompletionList.cs" />
+ <Compile Include="CodeCompletion\CompletionWindow.cs">
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="CodeCompletion\ICompletionData.cs" />
+ <Compile Include="CodeCompletion\InsightWindow.cs" />
+ <Compile Include="CodeCompletion\IOverloadProvider.cs" />
+ <Compile Include="CodeCompletion\OverloadInsightWindow.cs" />
+ <Compile Include="CodeCompletion\OverloadViewer.cs" />
+ <Compile Include="Converters\BooleanToVisibilityConverter.cs" />
+ <Compile Include="Converters\BooleanToVisibilityInversedConverter.cs" />
+ <Compile Include="Editing\BreakPoint.cs" />
+ <Compile Include="Editing\BreakPointMargin.cs" />
+ <Compile Include="Errors\ITextMarker.cs" />
+ <Compile Include="Errors\TextMarkerService.cs" />
+ <Compile Include="ExtensionMethods.cs" />
+ <Compile Include="Intellisense\ClassCompletionItemPopup.cs" />
+ <Compile Include="Intellisense\CompletionItem.cs" />
+ <Compile Include="Intellisense\CompletionItemPopupControl.cs" />
+ <Compile Include="Intellisense\EnumCompletionItem.cs" />
+ <Compile Include="Intellisense\EnumCompletionItemPopup.cs" />
+ <Compile Include="Intellisense\EventCompletionItem.cs" />
+ <Compile Include="Intellisense\FieldCompletionItem.cs" />
+ <Compile Include="Intellisense\FieldCompletionItemPopup.cs" />
+ <Compile Include="Intellisense\ICompletionItem.cs" />
+ <Compile Include="Intellisense\ICompletionProvider.cs" />
+ <Compile Include="Intellisense\InterfaceCompletionItem.cs" />
+ <Compile Include="Intellisense\InterfaceCompletionItemPopup.cs" />
+ <Compile Include="Intellisense\KnownType.cs" />
+ <Compile Include="Document\ChangeTrackingCheckpoint.cs" />
+ <Compile Include="Document\DocumentChangeOperation.cs">
+ <DependentUpon>UndoStack.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Document\ILineTracker.cs" />
+ <Compile Include="Document\ISegment.cs" />
+ <Compile Include="Document\ITextSource.cs" />
+ <Compile Include="Document\IUndoableOperation.cs">
+ <DependentUpon>UndoStack.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Document\LineNode.cs">
+ <DependentUpon>DocumentLine.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Document\NewLineFinder.cs" />
+ <Compile Include="Document\OffsetChangeMap.cs" />
+ <Compile Include="Document\TextDocumentWeakEventManager.cs">
+ <DependentUpon>TextDocument.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Document\TextSegmentCollection.cs" />
+ <Compile Include="Document\TextAnchor.cs" />
+ <Compile Include="Document\TextAnchorNode.cs">
+ <DependentUpon>TextAnchor.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Document\TextAnchorTree.cs">
+ <DependentUpon>TextAnchor.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Document\TextLocation.cs" />
+ <Compile Include="Document\TextSegment.cs" />
+ <Compile Include="Document\TextUtilities.cs" />
+ <Compile Include="Document\UndoOperationGroup.cs">
+ <DependentUpon>UndoStack.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Document\UndoStack.cs">
+ </Compile>
+ <Compile Include="Document\WeakLineTracker.cs">
+ <DependentUpon>ILineTracker.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Editing\AbstractMargin.cs" />
+ <Compile Include="Editing\Caret.cs" />
+ <Compile Include="Editing\CaretLayer.cs">
+ </Compile>
+ <Compile Include="Editing\CaretNavigationCommandHandler.cs">
+ </Compile>
+ <Compile Include="Editing\CaretWeakEventHandler.cs" />
+ <Compile Include="Editing\DottedLineMargin.cs" />
+ <Compile Include="Editing\DragDropException.cs" />
+ <Compile Include="Editing\EditingCommandHandler.cs" />
+ <Compile Include="Editing\EmptySelection.cs">
+ <DependentUpon>Selection.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Editing\ImeNativeWrapper.cs" />
+ <Compile Include="Editing\SelectionSegment.cs" />
+ <Compile Include="Editing\ImeSupport.cs" />
+ <Compile Include="Folding\AbstractFoldingStrategy.cs" />
+ <Compile Include="Folding\BraceFoldingStrategy.cs" />
+ <Compile Include="Folding\FoldingElementGenerator.cs" />
+ <Compile Include="Folding\FoldingManager.cs" />
+ <Compile Include="Folding\FoldingMargin.cs" />
+ <Compile Include="Folding\FoldingMarginMarker.cs" />
+ <Compile Include="Folding\FoldingSection.cs" />
+ <Compile Include="Editing\IReadOnlySectionProvider.cs" />
+ <Compile Include="Editing\LineNumberMargin.cs" />
+ <Compile Include="Editing\NoReadOnlySections.cs">
+ <DependentUpon>IReadOnlySectionProvider.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Editing\RectangleSelection.cs">
+ <DependentUpon>Selection.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Editing\Selection.cs" />
+ <Compile Include="Editing\SelectionColorizer.cs">
+ <DependentUpon>Selection.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Editing\SelectionLayer.cs">
+ <DependentUpon>Selection.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Editing\SelectionMouseHandler.cs">
+ <DependentUpon>Selection.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Editing\SimpleSelection.cs">
+ <DependentUpon>Selection.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Editing\TextArea.cs" />
+ <Compile Include="Editing\TextAreaDefaultInputHandlers.cs" />
+ <Compile Include="Editing\TextAreaInputHandler.cs" />
+ <Compile Include="Editing\TextSegmentReadOnlySectionProvider.cs">
+ <DependentUpon>IReadOnlySectionProvider.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Folding\NewFolding.cs" />
+ <Compile Include="Folding\XmlFoldingStrategy.cs" />
+ <Compile Include="Highlighting\DocumentHighlighter.cs" />
+ <Compile Include="Highlighting\HighlightedInlineBuilder.cs" />
+ <Compile Include="Highlighting\HighlightedLine.cs" />
+ <Compile Include="Highlighting\HighlightedSection.cs" />
+ <Compile Include="Highlighting\HighlightingBrush.cs" />
+ <Compile Include="Highlighting\HighlightingColor.cs" />
+ <Compile Include="Highlighting\HighlightingColorizer.cs" />
+ <Compile Include="Highlighting\HighlightingDefinitionInvalidException.cs" />
+ <Compile Include="Highlighting\HighlightingDefinitionTypeConverter.cs" />
+ <Compile Include="Highlighting\HighlightingManager.cs" />
+ <Compile Include="Highlighting\HtmlClipboard.cs" />
+ <Compile Include="Highlighting\IHighlighter.cs" />
+ <Compile Include="Highlighting\IHighlightingDefinition.cs" />
+ <Compile Include="Highlighting\HighlightingRule.cs" />
+ <Compile Include="Highlighting\OffsetColorizer.cs" />
+ <Compile Include="Highlighting\Resources\Resources.cs" />
+ <Compile Include="Highlighting\HighlightingRuleSet.cs" />
+ <Compile Include="Highlighting\HighlightingSpan.cs" />
+ <Compile Include="Highlighting\IHighlightingDefinitionReferenceResolver.cs">
+ </Compile>
+ <Compile Include="Highlighting\Xshd\HighlightingLoader.cs" />
+ <Compile Include="Highlighting\Xshd\IXshdVisitor.cs" />
+ <Compile Include="Highlighting\Xshd\SaveXshdVisitor.cs" />
+ <Compile Include="Highlighting\Xshd\V1Loader.cs" />
+ <Compile Include="Highlighting\Xshd\V2Loader.cs" />
+ <Compile Include="Highlighting\Xshd\XmlHighlightingDefinition.cs" />
+ <Compile Include="Highlighting\Xshd\XshdColor.cs" />
+ <Compile Include="Highlighting\Xshd\XshdImport.cs" />
+ <Compile Include="Highlighting\Xshd\XshdProperty.cs" />
+ <Compile Include="Highlighting\Xshd\XshdReference.cs" />
+ <Compile Include="Highlighting\Xshd\XshdElement.cs" />
+ <Compile Include="Highlighting\Xshd\XshdKeywords.cs" />
+ <Compile Include="Highlighting\Xshd\XshdRule.cs" />
+ <Compile Include="Highlighting\Xshd\XshdRuleSet.cs" />
+ <Compile Include="Highlighting\Xshd\XshdSpan.cs" />
+ <Compile Include="Highlighting\Xshd\XshdSyntaxDefinition.cs" />
+ <Compile Include="Indentation\CSharp\CSharpIndentationHelper.cs" />
+ <Compile Include="Indentation\CSharp\IndentationReformatter.cs" />
+ <Compile Include="Indentation\CSharp\CSharpIndentationStrategy.cs" />
+ <Compile Include="Indentation\CSharp\DocumentAccessor.cs" />
+ <Compile Include="Indentation\DefaultIndentationStrategy.cs" />
+ <Compile Include="Indentation\IIndentationStrategy.cs" />
+ <Compile Include="Intellisense\KnownTypeConstructor.cs" />
+ <Compile Include="Intellisense\KnownTypeEvent.cs" />
+ <Compile Include="Intellisense\KnownTypeField.cs" />
+ <Compile Include="Intellisense\KnownTypeMember.cs" />
+ <Compile Include="Intellisense\KnownTypeMethodParameter.cs" />
+ <Compile Include="Intellisense\KnownTypeMethod.cs" />
+ <Compile Include="Intellisense\KnownTypeProperty.cs" />
+ <Compile Include="Intellisense\ClassCompletionItem.cs" />
+ <Compile Include="Intellisense\MethodCompletionItem.cs" />
+ <Compile Include="Intellisense\MethodCompletionItemPopup.cs" />
+ <Compile Include="Intellisense\NamespaceCompletionItem.cs" />
+ <Compile Include="Intellisense\NamespaceCompletionItemPopup.cs" />
+ <Compile Include="Intellisense\PropertyCompletionItem.cs" />
+ <Compile Include="Intellisense\PropertyCompletionItemPopup.cs" />
+ <Compile Include="Intellisense\SnippetCompletionItem.cs" />
+ <Compile Include="Intellisense\StructCompletionItem.cs" />
+ <Compile Include="Intellisense\StructCompletionItemPopup.cs" />
+ <Compile Include="Intellisense\Utils.cs" />
+ <Compile Include="Popups\MethodDescription.cs" />
+ <Compile Include="Popups\MethodPopup.cs" />
+ <Compile Include="Popups\ParameterDescription.cs" />
+ <Compile Include="Rendering\BackgroundGeometryBuilder.cs">
+ <DependentUpon>IBackgroundRenderer.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Rendering\CollapsedLineSection.cs">
+ <DependentUpon>HeightTree.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Rendering\ColorizingTransformer.cs">
+ <DependentUpon>IVisualLineTransformer.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Rendering\ColumnRulerRenderer.cs" />
+ <Compile Include="Rendering\DefaultTextRunTypographyProperties.cs" />
+ <Compile Include="Rendering\DocumentColorizingTransformer.cs">
+ <DependentUpon>IVisualLineTransformer.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Rendering\FormattedTextElement.cs" />
+ <Compile Include="Rendering\GlobalTextRunProperties.cs">
+ <DependentUpon>TextView.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Rendering\HeightTree.cs" />
+ <Compile Include="Rendering\HeightTreeLineNode.cs">
+ <DependentUpon>HeightTree.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Rendering\HeightTreeNode.cs">
+ <DependentUpon>HeightTree.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Rendering\IBackgroundRenderer.cs" />
+ <Compile Include="Rendering\InlineObjectRun.cs" />
+ <Compile Include="Rendering\ITextRunConstructionContext.cs">
+ <DependentUpon>VisualLineElementGenerator.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Rendering\ITextViewConnect.cs">
+ <DependentUpon>TextView.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Rendering\IVisualLineTransformer.cs" />
+ <Compile Include="Rendering\Layer.cs">
+ <DependentUpon>TextView.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Rendering\LayerPosition.cs">
+ <DependentUpon>TextView.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Rendering\LinkElementGenerator.cs" />
+ <Compile Include="Rendering\MouseHoverLogic.cs" />
+ <Compile Include="Rendering\SimpleTextSource.cs">
+ <DependentUpon>FormattedTextElement.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Rendering\SingleCharacterElementGenerator.cs" />
+ <Compile Include="Rendering\TextLayer.cs">
+ <DependentUpon>TextView.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Rendering\TextView.cs" />
+ <Compile Include="Rendering\TextViewCachedElements.cs" />
+ <Compile Include="Rendering\TextViewWeakEventManager.cs">
+ <DependentUpon>TextView.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Rendering\VisualLine.cs" />
+ <Compile Include="Rendering\VisualLineConstructionStartEventArgs.cs" />
+ <Compile Include="Rendering\VisualLineElement.cs" />
+ <Compile Include="Rendering\VisualLineElementGenerator.cs" />
+ <Compile Include="Rendering\VisualLineElementTextRunProperties.cs">
+ <DependentUpon>VisualLine.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Rendering\VisualLineLinkText.cs" />
+ <Compile Include="Rendering\VisualLinesInvalidException.cs" />
+ <Compile Include="Rendering\VisualLineText.cs" />
+ <Compile Include="Rendering\VisualLineTextParagraphProperties.cs">
+ <DependentUpon>VisualLine.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Rendering\VisualLineTextSource.cs">
+ <DependentUpon>VisualLineElementGenerator.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Rendering\VisualYPosition.cs">
+ <DependentUpon>VisualLine.cs</DependentUpon>
+ </Compile>
+ <Compile Include="ScriptEditor.cs" />
+ <Compile Include="Search\Localization.cs" />
+ <Compile Include="Search\RegexSearchStrategy.cs" />
+ <Compile Include="Search\DropDownButton.cs" />
+ <Compile Include="Search\ISearchStrategy.cs" />
+ <Compile Include="Search\SearchCommands.cs" />
+ <Compile Include="Search\SearchResultBackgroundRenderer.cs" />
+ <Compile Include="Search\SearchPanel.cs">
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="Search\SearchStrategyFactory.cs" />
+ <Compile Include="Snippets\IActiveElement.cs" />
+ <Compile Include="Snippets\SnippetAnchorElement.cs" />
+ <Compile Include="Snippets\SnippetEventArgs.cs" />
+ <Compile Include="Snippets\SnippetInputHandler.cs" />
+ <Compile Include="Snippets\Snippet.cs" />
+ <Compile Include="Snippets\SnippetBoundElement.cs" />
+ <Compile Include="Snippets\SnippetCaretElement.cs" />
+ <Compile Include="Snippets\SnippetContainerElement.cs" />
+ <Compile Include="Snippets\SnippetElement.cs" />
+ <Compile Include="Snippets\InsertionContext.cs" />
+ <Compile Include="Snippets\SnippetReplaceableTextElement.cs" />
+ <Compile Include="Snippets\SnippetSelectionElement.cs" />
+ <Compile Include="Snippets\SnippetTextElement.cs" />
+ <Compile Include="TextEditor.cs" />
+ <Compile Include="TextEditorAutomationPeer.cs" />
+ <Compile Include="TextEditorComponent.cs">
+ </Compile>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Document\DocumentChangeEventArgs.cs" />
+ <Compile Include="Document\GapTextBuffer.cs">
+ <DependentUpon>TextDocument.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Document\LineManager.cs">
+ <DependentUpon>TextDocument.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Document\DocumentLine.cs" />
+ <Compile Include="Document\DocumentLineTree.cs">
+ <DependentUpon>DocumentLine.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Document\TextDocument.cs" />
+ <Compile Include="TextEditorOptions.cs" />
+ <Compile Include="TextEditorWeakEventManager.cs">
+ <DependentUpon>TextEditor.cs</DependentUpon>
+ </Compile>
+ <Compile Include="TextViewPosition.cs" />
+ <Compile Include="Utils\Boxes.cs" />
+ <Compile Include="Utils\BusyManager.cs">
+ <DependentUpon>ObserveAddRemoveCollection.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Utils\CharRope.cs" />
+ <Compile Include="Utils\CompressingTreeList.cs" />
+ <Compile Include="Utils\Constants.cs" />
+ <Compile Include="Utils\DelayedEvents.cs" />
+ <Compile Include="Utils\CallbackOnDispose.cs" />
+ <Compile Include="Utils\Deque.cs" />
+ <Compile Include="Utils\Empty.cs" />
+ <Compile Include="Utils\ExtensionMethods.cs" />
+ <Compile Include="Utils\FileReader.cs" />
+ <Compile Include="Utils\ImmutableStack.cs" />
+ <Compile Include="Utils\NullSafeCollection.cs" />
+ <Compile Include="Utils\ObserveAddRemoveCollection.cs" />
+ <Compile Include="Utils\PropertyChangedWeakEventManager.cs" />
+ <Compile Include="Utils\Rope.cs" />
+ <Compile Include="Utils\RopeNode.cs" />
+ <Compile Include="Utils\RopeTextReader.cs" />
+ <Compile Include="Utils\StringSegment.cs" />
+ <Compile Include="Utils\TextFormatterFactory.cs" />
+ <Compile Include="Utils\WeakEventManagerBase.cs" />
+ <Compile Include="Utils\PixelSnapHelpers.cs" />
+ <Compile Include="Utils\ThrowUtil.cs" />
+ <Compile Include="Utils\Win32.cs" />
+ <CodeAnalysisDictionary Include="Properties\CodeAnalysisDictionary.xml" />
+ <Compile Include="XamlEditor.cs" />
+ <Compile Include="Xml\AbstractAXmlVisitor.cs" />
+ <Compile Include="Xml\AXmlAttribute.cs" />
+ <Compile Include="Xml\AXmlAttributeCollection.cs" />
+ <Compile Include="Xml\AXmlContainer.cs" />
+ <Compile Include="Xml\AXmlDocument.cs" />
+ <Compile Include="Xml\AXmlElement.cs" />
+ <Compile Include="Xml\AXmlObject.cs" />
+ <Compile Include="Xml\AXmlObjectCollection.cs" />
+ <Compile Include="Xml\AXmlObjectEventArgs.cs" />
+ <Compile Include="Xml\AXmlParser.cs" />
+ <Compile Include="Xml\AXmlTag.cs" />
+ <Compile Include="Xml\AXmlText.cs" />
+ <Compile Include="Xml\CanonicalPrintAXmlVisitor.cs" />
+ <Compile Include="Xml\InternalException.cs" />
+ <Compile Include="Xml\TrackedSegmentCollection.cs">
+ <DependentUpon>AXmlParser.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Xml\ExtensionMethods.cs" />
+ <Compile Include="Xml\FilteredCollection.cs" />
+ <Compile Include="Xml\IAXmlVisitor.cs" />
+ <Compile Include="Xml\MergedCollection.cs" />
+ <Compile Include="Xml\PrettyPrintAXmlVisitor.cs" />
+ <Compile Include="Xml\SyntaxError.cs" />
+ <Compile Include="Xml\TagMatchingHeuristics.cs">
+ <DependentUpon>AXmlParser.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Xml\TagReader.cs">
+ <DependentUpon>AXmlParser.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Xml\TextType.cs">
+ <DependentUpon>AXmlText.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Xml\TokenReader.cs">
+ <DependentUpon>AXmlParser.cs</DependentUpon>
+ </Compile>
+ <EmbeddedResource Include="Highlighting\Resources\ASPX.xshd" />
+ <EmbeddedResource Include="Highlighting\Resources\Boo.xshd" />
+ <EmbeddedResource Include="Highlighting\Resources\Coco-Mode.xshd" />
+ <EmbeddedResource Include="Highlighting\Resources\CPP-Mode.xshd" />
+ <EmbeddedResource Include="Highlighting\Resources\HTML-Mode.xshd" />
+ <EmbeddedResource Include="Highlighting\Resources\Java-Mode.xshd" />
+ <EmbeddedResource Include="Highlighting\Resources\JavaScript-Mode.xshd" />
+ <EmbeddedResource Include="Highlighting\Resources\Patch-Mode.xshd" />
+ <EmbeddedResource Include="Highlighting\Resources\PHP-Mode.xshd" />
+ <EmbeddedResource Include="Highlighting\Resources\Tex-Mode.xshd" />
+ <EmbeddedResource Include="Highlighting\Resources\VBNET-Mode.xshd" />
+ <EmbeddedResource Include="Highlighting\Resources\XML-Mode.xshd" />
+ <EmbeddedResource Include="Highlighting\Resources\ModeV1.xsd" />
+ <EmbeddedResource Include="Highlighting\Resources\ModeV2.xsd" />
+ <EmbeddedResource Include="Highlighting\Resources\CSharp-Mode.xshd" />
+ <EmbeddedResource Include="Highlighting\Resources\XmlDoc.xshd" />
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Highlighting\Resources\CSS-Mode.xshd" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Tango.Core\Tango.Core.csproj">
+ <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project>
+ <Name>Tango.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Tango.Scripting.Core\Tango.Scripting.Core.csproj">
+ <Project>{5812E1C6-ABAA-4066-94AC-971C27B4F46A}</Project>
+ <Name>Tango.Scripting.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Tango.Scripting.Formatting\Tango.Scripting.Formatting.csproj">
+ <Project>{8d8f06ed-7f75-4933-b0c5-829b0ff654d0}</Project>
+ <Name>Tango.Scripting.Formatting</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Tango.Scripting\Tango.Scripting.csproj">
+ <Project>{1e938fd2-c669-4738-98c9-77f96ce4d451}</Project>
+ <Name>Tango.Scripting</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Highlighting\Resources\PowerShell.xshd" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Highlighting\Resources\MarkDown-Mode.xshd" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="app.config" />
+ <None Include="packages.config" />
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <Analyzer Include="..\..\packages\Microsoft.CodeAnalysis.Analyzers.1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.Analyzers.dll" />
+ <Analyzer Include="..\..\packages\Microsoft.CodeAnalysis.Analyzers.1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.CSharp.Analyzers.dll" />
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ProjectExtensions>
+ <VisualStudio>
+ <UserProperties BuildVersion_UseGlobalSettings="True" BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_StartDate="2000/1/1" />
+ </VisualStudio>
+ </ProjectExtensions>
+ <ItemGroup>
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\FontAwesome.WPF.4.7.0.9\lib\net40\FontAwesome.WPF.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\Microsoft.CodeAnalysis.CSharp.2.4.0\lib\netstandard1.3\Microsoft.CodeAnalysis.CSharp.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\Microsoft.CodeAnalysis.Common.2.4.0\lib\netstandard1.3\Microsoft.CodeAnalysis.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\mscorlib.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\PresentationCore.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\PresentationFramework.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Collections.Immutable.1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.ComponentModel.Composition.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Console.4.3.0\lib\net46\System.Console.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Core.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Data.DataSetExtensions.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Data.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Diagnostics.FileVersionInfo.4.3.0\lib\net46\System.Diagnostics.FileVersionInfo.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Diagnostics.StackTrace.4.3.0\lib\net46\System.Diagnostics.StackTrace.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Drawing.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Numerics.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Reflection.Metadata.1.4.2\lib\portable-net45+win8\System.Reflection.Metadata.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Text.Encoding.CodePages.4.3.0\lib\net46\System.Text.Encoding.CodePages.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Threading.Thread.4.3.0\lib\net46\System.Threading.Thread.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.ValueTuple.4.3.0\lib\netstandard1.0\System.ValueTuple.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Windows.Forms.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Xaml.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Xml.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Xml.Linq.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Xml.ReaderWriter.4.3.0\lib\net46\System.Xml.ReaderWriter.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Xml.XmlDocument.4.3.0\lib\net46\System.Xml.XmlDocument.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Xml.XPath.4.3.0\lib\net46\System.Xml.XPath.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\packages\System.Xml.XPath.XDocument.4.3.0\lib\net46\System.Xml.XPath.XDocument.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\Build\Core\Debug\Tango.Core.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\Scripting\Tango.Scripting.Core\bin\Debug\Tango.Scripting.Core.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\Build\Scripting\Debug\Tango.Scripting.dll" />
+ <ReferencePath Include="C:\DATA\Development\Tango\Software\Visual_Studio\Scripting\Tango.Scripting.Formatting\bin\Debug\Tango.Scripting.Formatting.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\UIAutomationProvider.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\UIAutomationTypes.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\WindowsBase.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Collections.Concurrent.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Collections.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.ComponentModel.Annotations.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.ComponentModel.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.ComponentModel.EventBasedAsync.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Diagnostics.Contracts.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Diagnostics.Debug.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Diagnostics.Tools.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Diagnostics.Tracing.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Dynamic.Runtime.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Globalization.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.IO.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Linq.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Linq.Expressions.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Linq.Parallel.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Linq.Queryable.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Net.NetworkInformation.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Net.Primitives.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Net.Requests.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Net.WebHeaderCollection.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.ObjectModel.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Reflection.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Reflection.Emit.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Reflection.Emit.ILGeneration.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Reflection.Emit.Lightweight.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Reflection.Extensions.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Reflection.Primitives.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Resources.ResourceManager.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Runtime.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Runtime.Extensions.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Runtime.Handles.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Runtime.InteropServices.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Runtime.InteropServices.WindowsRuntime.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Runtime.Numerics.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Runtime.Serialization.Json.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Runtime.Serialization.Primitives.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Runtime.Serialization.Xml.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Security.Principal.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.ServiceModel.Duplex.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.ServiceModel.Http.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.ServiceModel.NetTcp.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.ServiceModel.Primitives.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.ServiceModel.Security.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Text.Encoding.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Text.Encoding.Extensions.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Text.RegularExpressions.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Threading.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Threading.Tasks.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Threading.Tasks.Parallel.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Threading.Timer.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Xml.XDocument.dll" />
+ <ReferencePath Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\Facades\System.Xml.XmlSerializer.dll" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="C:\DATA\Development\Tango\Software\Visual_Studio\Scripting\Tango.Scripting.Editors\obj\Debug\GeneratedInternalTypeHelper.g.cs" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/TextEditor.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/TextEditor.cs
index d2fc9e02b..cd9977520 100644
--- a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/TextEditor.cs
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/TextEditor.cs
@@ -3,6 +3,7 @@
using System;
using System.ComponentModel;
+using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
@@ -24,1121 +25,1229 @@ using Tango.Scripting.Editors.Utils;
namespace Tango.Scripting.Editors
{
- /// <summary>
- /// The text editor control.
- /// Contains a scrollable TextArea.
- /// </summary>
- [Localizability(LocalizationCategory.Text), ContentProperty("Text")]
- public class TextEditor : Control, ITextEditorComponent, IServiceProvider, IWeakEventListener
- {
- #region Constructors
- static TextEditor()
- {
- DefaultStyleKeyProperty.OverrideMetadata(typeof(TextEditor),
- new FrameworkPropertyMetadata(typeof(TextEditor)));
- FocusableProperty.OverrideMetadata(typeof(TextEditor),
- new FrameworkPropertyMetadata(Boxes.True));
- }
-
- /// <summary>
- /// Creates a new TextEditor instance.
- /// </summary>
- public TextEditor() : this(new TextArea())
- {
- }
-
- /// <summary>
- /// Creates a new TextEditor instance.
- /// </summary>
- protected TextEditor(TextArea textArea)
- {
- if (textArea == null)
- throw new ArgumentNullException("textArea");
- this.textArea = textArea;
-
- textArea.TextView.Services.AddService(typeof(TextEditor), this);
-
- SetCurrentValue(OptionsProperty, textArea.Options);
- SetCurrentValue(DocumentProperty, new TextDocument());
- }
-
- #endregion
-
- /// <inheritdoc/>
- protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer()
- {
- return new TextEditorAutomationPeer(this);
- }
-
- /// Forward focus to TextArea.
- /// <inheritdoc/>
- protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
- {
- base.OnGotKeyboardFocus(e);
- if (e.NewFocus == this) {
- Keyboard.Focus(this.TextArea);
- e.Handled = true;
- }
- }
-
- #region Document property
- /// <summary>
- /// Document property.
- /// </summary>
- public static readonly DependencyProperty DocumentProperty
- = TextView.DocumentProperty.AddOwner(
- typeof(TextEditor), new FrameworkPropertyMetadata(OnDocumentChanged));
-
- /// <summary>
- /// Gets/Sets the document displayed by the text editor.
- /// This is a dependency property.
- /// </summary>
- public TextDocument Document {
- get { return (TextDocument)GetValue(DocumentProperty); }
- set { SetValue(DocumentProperty, value); }
- }
-
- /// <summary>
- /// Occurs when the document property has changed.
- /// </summary>
- public event EventHandler DocumentChanged;
-
- /// <summary>
- /// Raises the <see cref="DocumentChanged"/> event.
- /// </summary>
- protected virtual void OnDocumentChanged(EventArgs e)
- {
- if (DocumentChanged != null) {
- DocumentChanged(this, e);
- }
- }
-
- static void OnDocumentChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
- {
- ((TextEditor)dp).OnDocumentChanged((TextDocument)e.OldValue, (TextDocument)e.NewValue);
- }
-
- void OnDocumentChanged(TextDocument oldValue, TextDocument newValue)
- {
- if (oldValue != null) {
- TextDocumentWeakEventManager.TextChanged.RemoveListener(oldValue, this);
- PropertyChangedEventManager.RemoveListener(oldValue.UndoStack, this, "IsOriginalFile");
- }
- textArea.Document = newValue;
- if (newValue != null) {
- TextDocumentWeakEventManager.TextChanged.AddListener(newValue, this);
- PropertyChangedEventManager.AddListener(newValue.UndoStack, this, "IsOriginalFile");
- }
- OnDocumentChanged(EventArgs.Empty);
- OnTextChanged(EventArgs.Empty);
- }
- #endregion
-
- #region Options property
- /// <summary>
- /// Options property.
- /// </summary>
- public static readonly DependencyProperty OptionsProperty
- = TextView.OptionsProperty.AddOwner(typeof(TextEditor), new FrameworkPropertyMetadata(OnOptionsChanged));
-
- /// <summary>
- /// Gets/Sets the options currently used by the text editor.
- /// </summary>
- public TextEditorOptions Options {
- get { return (TextEditorOptions)GetValue(OptionsProperty); }
- set { SetValue(OptionsProperty, value); }
- }
-
- /// <summary>
- /// Occurs when a text editor option has changed.
- /// </summary>
- public event PropertyChangedEventHandler OptionChanged;
-
- /// <summary>
- /// Raises the <see cref="OptionChanged"/> event.
- /// </summary>
- protected virtual void OnOptionChanged(PropertyChangedEventArgs e)
- {
- if (OptionChanged != null) {
- OptionChanged(this, e);
- }
- }
-
- static void OnOptionsChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
- {
- ((TextEditor)dp).OnOptionsChanged((TextEditorOptions)e.OldValue, (TextEditorOptions)e.NewValue);
- }
-
- void OnOptionsChanged(TextEditorOptions oldValue, TextEditorOptions newValue)
- {
- if (oldValue != null) {
- PropertyChangedWeakEventManager.RemoveListener(oldValue, this);
- }
- textArea.Options = newValue;
- if (newValue != null) {
- PropertyChangedWeakEventManager.AddListener(newValue, this);
- }
- OnOptionChanged(new PropertyChangedEventArgs(null));
- }
-
- /// <inheritdoc cref="IWeakEventListener.ReceiveWeakEvent"/>
- protected virtual bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
- {
- if (managerType == typeof(PropertyChangedWeakEventManager)) {
- OnOptionChanged((PropertyChangedEventArgs)e);
- return true;
- } else if (managerType == typeof(TextDocumentWeakEventManager.TextChanged)) {
- OnTextChanged(e);
- return true;
- } else if (managerType == typeof(PropertyChangedEventManager)) {
- return HandleIsOriginalChanged((PropertyChangedEventArgs)e);
- }
- return false;
- }
-
- bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
- {
- return ReceiveWeakEvent(managerType, sender, e);
- }
- #endregion
-
- #region Text property
- /// <summary>
- /// Gets/Sets the text of the current document.
- /// </summary>
- [Localizability(LocalizationCategory.Text), DefaultValue("")]
- public string Text {
- get {
- TextDocument document = this.Document;
- return document != null ? document.Text : string.Empty;
- }
- set {
- TextDocument document = GetDocument();
- document.Text = value ?? string.Empty;
- // after replacing the full text, the caret is positioned at the end of the document
- // - reset it to the beginning.
- this.CaretOffset = 0;
- document.UndoStack.ClearAll();
- }
- }
-
- TextDocument GetDocument()
- {
- TextDocument document = this.Document;
- if (document == null)
- throw ThrowUtil.NoDocumentAssigned();
- return document;
- }
-
- /// <summary>
- /// Occurs when the Text property changes.
- /// </summary>
- public event EventHandler TextChanged;
-
- /// <summary>
- /// Raises the <see cref="TextChanged"/> event.
- /// </summary>
- protected virtual void OnTextChanged(EventArgs e)
- {
- if (TextChanged != null) {
- TextChanged(this, e);
- }
- }
- #endregion
-
- #region TextArea / ScrollViewer properties
- readonly TextArea textArea;
- ScrollViewer scrollViewer;
-
- /// <summary>
- /// Is called after the template was applied.
- /// </summary>
- public override void OnApplyTemplate()
- {
- base.OnApplyTemplate();
- scrollViewer = (ScrollViewer)Template.FindName("PART_ScrollViewer", this);
- }
-
- /// <summary>
- /// Gets the text area.
- /// </summary>
- public TextArea TextArea {
- get {
- return textArea;
- }
- }
-
- /// <summary>
- /// Gets the scroll viewer used by the text editor.
- /// This property can return null if the template has not been applied / does not contain a scroll viewer.
- /// </summary>
- internal ScrollViewer ScrollViewer {
- get { return scrollViewer; }
- }
-
- bool CanExecute(RoutedUICommand command)
- {
- TextArea textArea = this.TextArea;
- if (textArea == null)
- return false;
- else
- return command.CanExecute(null, textArea);
- }
-
- void Execute(RoutedUICommand command)
- {
- TextArea textArea = this.TextArea;
- if (textArea != null)
- command.Execute(null, textArea);
- }
- #endregion
-
- #region Syntax highlighting
- /// <summary>
- /// The <see cref="SyntaxHighlighting"/> property.
- /// </summary>
- public static readonly DependencyProperty SyntaxHighlightingProperty =
- DependencyProperty.Register("SyntaxHighlighting", typeof(IHighlightingDefinition), typeof(TextEditor),
- new FrameworkPropertyMetadata(OnSyntaxHighlightingChanged));
-
-
- /// <summary>
- /// Gets/sets the syntax highlighting definition used to colorize the text.
- /// </summary>
- public IHighlightingDefinition SyntaxHighlighting {
- get { return (IHighlightingDefinition)GetValue(SyntaxHighlightingProperty); }
- set { SetValue(SyntaxHighlightingProperty, value); }
- }
-
- IVisualLineTransformer colorizer;
-
- static void OnSyntaxHighlightingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- ((TextEditor)d).OnSyntaxHighlightingChanged(e.NewValue as IHighlightingDefinition);
- }
-
- void OnSyntaxHighlightingChanged(IHighlightingDefinition newValue)
- {
- if (colorizer != null) {
- this.TextArea.TextView.LineTransformers.Remove(colorizer);
- colorizer = null;
- }
- if (newValue != null) {
- colorizer = CreateColorizer(newValue);
- this.TextArea.TextView.LineTransformers.Insert(0, colorizer);
- }
- }
-
- /// <summary>
- /// Creates the highlighting colorizer for the specified highlighting definition.
- /// Allows derived classes to provide custom colorizer implementations for special highlighting definitions.
- /// </summary>
- /// <returns></returns>
- protected virtual IVisualLineTransformer CreateColorizer(IHighlightingDefinition highlightingDefinition)
- {
- if (highlightingDefinition == null)
- throw new ArgumentNullException("highlightingDefinition");
- return new HighlightingColorizer(highlightingDefinition.MainRuleSet);
- }
- #endregion
-
- #region WordWrap
- /// <summary>
- /// Word wrap dependency property.
- /// </summary>
- public static readonly DependencyProperty WordWrapProperty =
- DependencyProperty.Register("WordWrap", typeof(bool), typeof(TextEditor),
- new FrameworkPropertyMetadata(Boxes.False));
-
- /// <summary>
- /// Specifies whether the text editor uses word wrapping.
- /// </summary>
- /// <remarks>
- /// Setting WordWrap=true has the same effect as setting HorizontalScrollBarVisibility=Disabled and will override the
- /// HorizontalScrollBarVisibility setting.
- /// </remarks>
- public bool WordWrap {
- get { return (bool)GetValue(WordWrapProperty); }
- set { SetValue(WordWrapProperty, Boxes.Box(value)); }
- }
- #endregion
-
- #region IsReadOnly
- /// <summary>
- /// IsReadOnly dependency property.
- /// </summary>
- public static readonly DependencyProperty IsReadOnlyProperty =
- DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(TextEditor),
- new FrameworkPropertyMetadata(Boxes.False, OnIsReadOnlyChanged));
-
- /// <summary>
- /// Specifies whether the user can change the text editor content.
- /// Setting this property will replace the
- /// <see cref="Editing.TextArea.ReadOnlySectionProvider">TextArea.ReadOnlySectionProvider</see>.
- /// </summary>
- public bool IsReadOnly {
- get { return (bool)GetValue(IsReadOnlyProperty); }
- set { SetValue(IsReadOnlyProperty, Boxes.Box(value)); }
- }
-
- static void OnIsReadOnlyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- TextEditor editor = d as TextEditor;
- if (editor != null) {
- if ((bool)e.NewValue)
- editor.TextArea.ReadOnlySectionProvider = ReadOnlyDocument.Instance;
- else
- editor.TextArea.ReadOnlySectionProvider = NoReadOnlySections.Instance;
-
- TextEditorAutomationPeer peer = TextEditorAutomationPeer.FromElement(editor) as TextEditorAutomationPeer;
- if (peer != null) {
- peer.RaiseIsReadOnlyChanged((bool)e.OldValue, (bool)e.NewValue);
- }
- }
- }
- #endregion
-
- #region IsModified
- /// <summary>
- /// Dependency property for <see cref="IsModified"/>
- /// </summary>
- public static readonly DependencyProperty IsModifiedProperty =
- DependencyProperty.Register("IsModified", typeof(bool), typeof(TextEditor),
- new FrameworkPropertyMetadata(Boxes.False, OnIsModifiedChanged));
-
- /// <summary>
- /// Gets/Sets the 'modified' flag.
- /// </summary>
- public bool IsModified {
- get { return (bool)GetValue(IsModifiedProperty); }
- set { SetValue(IsModifiedProperty, Boxes.Box(value)); }
- }
-
- static void OnIsModifiedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- TextEditor editor = d as TextEditor;
- if (editor != null) {
- TextDocument document = editor.Document;
- if (document != null) {
- UndoStack undoStack = document.UndoStack;
- if ((bool)e.NewValue) {
- if (undoStack.IsOriginalFile)
- undoStack.DiscardOriginalFileMarker();
- } else {
- undoStack.MarkAsOriginalFile();
- }
- }
- }
- }
-
- bool HandleIsOriginalChanged(PropertyChangedEventArgs e)
- {
- if (e.PropertyName == "IsOriginalFile") {
- TextDocument document = this.Document;
- if (document != null) {
- SetCurrentValue(IsModifiedProperty, Boxes.Box(!document.UndoStack.IsOriginalFile));
- }
- return true;
- } else {
- return false;
- }
- }
- #endregion
-
- #region ShowLineNumbers
- /// <summary>
- /// ShowLineNumbers dependency property.
- /// </summary>
- public static readonly DependencyProperty ShowLineNumbersProperty =
- DependencyProperty.Register("ShowLineNumbers", typeof(bool), typeof(TextEditor),
- new FrameworkPropertyMetadata(Boxes.False, OnShowLineNumbersChanged));
-
- /// <summary>
- /// Specifies whether line numbers are shown on the left to the text view.
- /// </summary>
- public bool ShowLineNumbers {
- get { return (bool)GetValue(ShowLineNumbersProperty); }
- set { SetValue(ShowLineNumbersProperty, Boxes.Box(value)); }
- }
-
- static void OnShowLineNumbersChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- TextEditor editor = (TextEditor)d;
- var leftMargins = editor.TextArea.LeftMargins;
- if ((bool)e.NewValue) {
- LineNumberMargin lineNumbers = new LineNumberMargin();
- Line line = (Line)DottedLineMargin.Create();
- leftMargins.Insert(0, lineNumbers);
- leftMargins.Insert(1, line);
- var lineNumbersForeground = new Binding("LineNumbersForeground") { Source = editor };
- line.SetBinding(Line.StrokeProperty, lineNumbersForeground);
- lineNumbers.SetBinding(Control.ForegroundProperty, lineNumbersForeground);
- } else {
- for (int i = 0; i < leftMargins.Count; i++) {
- if (leftMargins[i] is LineNumberMargin) {
- leftMargins.RemoveAt(i);
- if (i < leftMargins.Count && DottedLineMargin.IsDottedLineMargin(leftMargins[i])) {
- leftMargins.RemoveAt(i);
- }
- break;
- }
- }
- }
- }
- #endregion
-
- #region LineNumbersForeground
- /// <summary>
- /// LineNumbersForeground dependency property.
- /// </summary>
- public static readonly DependencyProperty LineNumbersForegroundProperty =
- DependencyProperty.Register("LineNumbersForeground", typeof(Brush), typeof(TextEditor),
- new FrameworkPropertyMetadata(Brushes.Gray, OnLineNumbersForegroundChanged));
-
- /// <summary>
- /// Gets/sets the Brush used for displaying the foreground color of line numbers.
- /// </summary>
- public Brush LineNumbersForeground {
- get { return (Brush)GetValue(LineNumbersForegroundProperty); }
- set { SetValue(LineNumbersForegroundProperty, value); }
- }
-
- static void OnLineNumbersForegroundChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- TextEditor editor = (TextEditor)d;
- var lineNumberMargin = editor.TextArea.LeftMargins.FirstOrDefault(margin => margin is LineNumberMargin) as LineNumberMargin;;
-
- if (lineNumberMargin != null) {
- lineNumberMargin.SetValue(Control.ForegroundProperty, e.NewValue);
- }
- }
- #endregion
-
- #region TextBoxBase-like methods
- /// <summary>
- /// Appends text to the end of the document.
- /// </summary>
- public void AppendText(string textData)
- {
- var document = GetDocument();
- document.Insert(document.TextLength, textData);
- }
-
- /// <summary>
- /// Begins a group of document changes.
- /// </summary>
- public void BeginChange()
- {
- GetDocument().BeginUpdate();
- }
-
- /// <summary>
- /// Copies the current selection to the clipboard.
- /// </summary>
- public void Copy()
- {
- Execute(ApplicationCommands.Copy);
- }
-
- /// <summary>
- /// Removes the current selection and copies it to the clipboard.
- /// </summary>
- public void Cut()
- {
- Execute(ApplicationCommands.Cut);
- }
-
- /// <summary>
- /// Begins a group of document changes and returns an object that ends the group of document
- /// changes when it is disposed.
- /// </summary>
- public IDisposable DeclareChangeBlock()
- {
- return GetDocument().RunUpdate();
- }
-
- /// <summary>
- /// Ends the current group of document changes.
- /// </summary>
- public void EndChange()
- {
- GetDocument().EndUpdate();
- }
-
- /// <summary>
- /// Scrolls one line down.
- /// </summary>
- public void LineDown()
- {
- if (scrollViewer != null)
- scrollViewer.LineDown();
- }
-
- /// <summary>
- /// Scrolls to the left.
- /// </summary>
- public void LineLeft()
- {
- if (scrollViewer != null)
- scrollViewer.LineLeft();
- }
-
- /// <summary>
- /// Scrolls to the right.
- /// </summary>
- public void LineRight()
- {
- if (scrollViewer != null)
- scrollViewer.LineRight();
- }
-
- /// <summary>
- /// Scrolls one line up.
- /// </summary>
- public void LineUp()
- {
- if (scrollViewer != null)
- scrollViewer.LineUp();
- }
-
- /// <summary>
- /// Scrolls one page down.
- /// </summary>
- public void PageDown()
- {
- if (scrollViewer != null)
- scrollViewer.PageDown();
- }
-
- /// <summary>
- /// Scrolls one page up.
- /// </summary>
- public void PageUp()
- {
- if (scrollViewer != null)
- scrollViewer.PageUp();
- }
-
- /// <summary>
- /// Scrolls one page left.
- /// </summary>
- public void PageLeft()
- {
- if (scrollViewer != null)
- scrollViewer.PageLeft();
- }
-
- /// <summary>
- /// Scrolls one page right.
- /// </summary>
- public void PageRight()
- {
- if (scrollViewer != null)
- scrollViewer.PageRight();
- }
-
- /// <summary>
- /// Pastes the clipboard content.
- /// </summary>
- public void Paste()
- {
- Execute(ApplicationCommands.Paste);
- }
-
- /// <summary>
- /// Redoes the most recent undone command.
- /// </summary>
- /// <returns>True is the redo operation was successful, false is the redo stack is empty.</returns>
- public bool Redo()
- {
- if (CanExecute(ApplicationCommands.Redo)) {
- Execute(ApplicationCommands.Redo);
- return true;
- }
- return false;
- }
-
- /// <summary>
- /// Scrolls to the end of the document.
- /// </summary>
- public void ScrollToEnd()
- {
- ApplyTemplate(); // ensure scrollViewer is created
- if (scrollViewer != null)
- scrollViewer.ScrollToEnd();
- }
-
- /// <summary>
- /// Scrolls to the start of the document.
- /// </summary>
- public void ScrollToHome()
- {
- ApplyTemplate(); // ensure scrollViewer is created
- if (scrollViewer != null)
- scrollViewer.ScrollToHome();
- }
-
- /// <summary>
- /// Scrolls to the specified position in the document.
- /// </summary>
- public void ScrollToHorizontalOffset(double offset)
- {
- ApplyTemplate(); // ensure scrollViewer is created
- if (scrollViewer != null)
- scrollViewer.ScrollToHorizontalOffset(offset);
- }
-
- /// <summary>
- /// Scrolls to the specified position in the document.
- /// </summary>
- public void ScrollToVerticalOffset(double offset)
- {
- ApplyTemplate(); // ensure scrollViewer is created
- if (scrollViewer != null)
- scrollViewer.ScrollToVerticalOffset(offset);
- }
-
- /// <summary>
- /// Selects the entire text.
- /// </summary>
- public void SelectAll()
- {
- Execute(ApplicationCommands.SelectAll);
- }
-
- /// <summary>
- /// Undoes the most recent command.
- /// </summary>
- /// <returns>True is the undo operation was successful, false is the undo stack is empty.</returns>
- public bool Undo()
- {
- if (CanExecute(ApplicationCommands.Undo)) {
- Execute(ApplicationCommands.Undo);
- return true;
- }
- return false;
- }
-
- /// <summary>
- /// Gets if the most recent undone command can be redone.
- /// </summary>
- public bool CanRedo {
- get { return CanExecute(ApplicationCommands.Redo); }
- }
-
- /// <summary>
- /// Gets if the most recent command can be undone.
- /// </summary>
- public bool CanUndo {
- get { return CanExecute(ApplicationCommands.Undo); }
- }
-
- /// <summary>
- /// Gets the vertical size of the document.
- /// </summary>
- public double ExtentHeight {
- get {
- return scrollViewer != null ? scrollViewer.ExtentHeight : 0;
- }
- }
-
- /// <summary>
- /// Gets the horizontal size of the current document region.
- /// </summary>
- public double ExtentWidth {
- get {
- return scrollViewer != null ? scrollViewer.ExtentWidth : 0;
- }
- }
-
- /// <summary>
- /// Gets the horizontal size of the viewport.
- /// </summary>
- public double ViewportHeight {
- get {
- return scrollViewer != null ? scrollViewer.ViewportHeight : 0;
- }
- }
-
- /// <summary>
- /// Gets the horizontal size of the viewport.
- /// </summary>
- public double ViewportWidth {
- get {
- return scrollViewer != null ? scrollViewer.ViewportWidth : 0;
- }
- }
-
- /// <summary>
- /// Gets the vertical scroll position.
- /// </summary>
- public double VerticalOffset {
- get {
- return scrollViewer != null ? scrollViewer.VerticalOffset : 0;
- }
- }
-
- /// <summary>
- /// Gets the horizontal scroll position.
- /// </summary>
- public double HorizontalOffset {
- get {
- return scrollViewer != null ? scrollViewer.HorizontalOffset : 0;
- }
- }
- #endregion
-
- #region TextBox methods
- /// <summary>
- /// Gets/Sets the selected text.
- /// </summary>
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public string SelectedText {
- get {
- TextArea textArea = this.TextArea;
- // We'll get the text from the whole surrounding segment.
- // This is done to ensure that SelectedText.Length == SelectionLength.
- if (textArea != null && textArea.Document != null && !textArea.Selection.IsEmpty)
- return textArea.Document.GetText(textArea.Selection.SurroundingSegment);
- else
- return string.Empty;
- }
- set {
- if (value == null)
- throw new ArgumentNullException("value");
- TextArea textArea = this.TextArea;
- if (textArea != null && textArea.Document != null) {
- int offset = this.SelectionStart;
- int length = this.SelectionLength;
- textArea.Document.Replace(offset, length, value);
- // keep inserted text selected
- textArea.Selection = SimpleSelection.Create(textArea, offset, offset + value.Length);
- }
- }
- }
-
- /// <summary>
- /// Gets/sets the caret position.
- /// </summary>
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public int CaretOffset {
- get {
- TextArea textArea = this.TextArea;
- if (textArea != null)
- return textArea.Caret.Offset;
- else
- return 0;
- }
- set {
- TextArea textArea = this.TextArea;
- if (textArea != null)
- textArea.Caret.Offset = value;
- }
- }
-
- /// <summary>
- /// Gets/sets the start position of the selection.
- /// </summary>
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public int SelectionStart {
- get {
- TextArea textArea = this.TextArea;
- if (textArea != null) {
- if (textArea.Selection.IsEmpty)
- return textArea.Caret.Offset;
- else
- return textArea.Selection.SurroundingSegment.Offset;
- } else {
- return 0;
- }
- }
- set {
- Select(value, SelectionLength);
- }
- }
-
- /// <summary>
- /// Gets/sets the length of the selection.
- /// </summary>
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public int SelectionLength {
- get {
- TextArea textArea = this.TextArea;
- if (textArea != null && !textArea.Selection.IsEmpty)
- return textArea.Selection.SurroundingSegment.Length;
- else
- return 0;
- }
- set {
- Select(SelectionStart, value);
- }
- }
-
- /// <summary>
- /// Selects the specified text section.
- /// </summary>
- public void Select(int start, int length)
- {
- int documentLength = Document != null ? Document.TextLength : 0;
- if (start < 0 || start > documentLength)
- throw new ArgumentOutOfRangeException("start", start, "Value must be between 0 and " + documentLength);
- if (length < 0 || start + length > documentLength)
- throw new ArgumentOutOfRangeException("length", length, "Value must be between 0 and " + (documentLength - length));
- textArea.Selection = SimpleSelection.Create(textArea, start, start + length);
- textArea.Caret.Offset = start + length;
- }
-
- /// <summary>
- /// Gets the number of lines in the document.
- /// </summary>
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public int LineCount {
- get {
- TextDocument document = this.Document;
- if (document != null)
- return document.LineCount;
- else
- return 1;
- }
- }
-
- /// <summary>
- /// Clears the text.
- /// </summary>
- public void Clear()
- {
- this.Text = string.Empty;
- }
- #endregion
-
- #region Loading from stream
- /// <summary>
- /// Loads the text from the stream, auto-detecting the encoding.
- /// </summary>
- /// <remarks>
- /// This method sets <see cref="IsModified"/> to false.
- /// </remarks>
- public void Load(Stream stream)
- {
- using (StreamReader reader = FileReader.OpenStream(stream, this.Encoding ?? Encoding.UTF8)) {
- this.Text = reader.ReadToEnd();
- this.Encoding = reader.CurrentEncoding; // assign encoding after ReadToEnd() so that the StreamReader can autodetect the encoding
- }
- this.IsModified = false;
- }
-
- /// <summary>
- /// Loads the text from the stream, auto-detecting the encoding.
- /// </summary>
- public void Load(string fileName)
- {
- if (fileName == null)
- throw new ArgumentNullException("fileName");
- using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) {
- Load(fs);
- }
- }
-
- /// <summary>
- /// Gets/sets the encoding used when the file is saved.
- /// </summary>
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public Encoding Encoding { get; set; }
-
- /// <summary>
- /// Saves the text to the stream.
- /// </summary>
- /// <remarks>
- /// This method sets <see cref="IsModified"/> to false.
- /// </remarks>
- public void Save(Stream stream)
- {
- if (stream == null)
- throw new ArgumentNullException("stream");
- StreamWriter writer = new StreamWriter(stream, this.Encoding ?? Encoding.UTF8);
- writer.Write(this.Text);
- writer.Flush();
- // do not close the stream
- this.IsModified = false;
- }
-
- /// <summary>
- /// Saves the text to the file.
- /// </summary>
- public void Save(string fileName)
- {
- if (fileName == null)
- throw new ArgumentNullException("fileName");
- using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) {
- Save(fs);
- }
- }
- #endregion
-
- #region MouseHover events
- /// <summary>
- /// The PreviewMouseHover event.
- /// </summary>
- public static readonly RoutedEvent PreviewMouseHoverEvent =
- TextView.PreviewMouseHoverEvent.AddOwner(typeof(TextEditor));
-
- /// <summary>
- /// The MouseHover event.
- /// </summary>
- public static readonly RoutedEvent MouseHoverEvent =
- TextView.MouseHoverEvent.AddOwner(typeof(TextEditor));
-
-
- /// <summary>
- /// The PreviewMouseHoverStopped event.
- /// </summary>
- public static readonly RoutedEvent PreviewMouseHoverStoppedEvent =
- TextView.PreviewMouseHoverStoppedEvent.AddOwner(typeof(TextEditor));
-
- /// <summary>
- /// The MouseHoverStopped event.
- /// </summary>
- public static readonly RoutedEvent MouseHoverStoppedEvent =
- TextView.MouseHoverStoppedEvent.AddOwner(typeof(TextEditor));
-
-
- /// <summary>
- /// Occurs when the mouse has hovered over a fixed location for some time.
- /// </summary>
- public event MouseEventHandler PreviewMouseHover {
- add { AddHandler(PreviewMouseHoverEvent, value); }
- remove { RemoveHandler(PreviewMouseHoverEvent, value); }
- }
-
- /// <summary>
- /// Occurs when the mouse has hovered over a fixed location for some time.
- /// </summary>
- public event MouseEventHandler MouseHover {
- add { AddHandler(MouseHoverEvent, value); }
- remove { RemoveHandler(MouseHoverEvent, value); }
- }
-
- /// <summary>
- /// Occurs when the mouse had previously hovered but now started moving again.
- /// </summary>
- public event MouseEventHandler PreviewMouseHoverStopped {
- add { AddHandler(PreviewMouseHoverStoppedEvent, value); }
- remove { RemoveHandler(PreviewMouseHoverStoppedEvent, value); }
- }
-
- /// <summary>
- /// Occurs when the mouse had previously hovered but now started moving again.
- /// </summary>
- public event MouseEventHandler MouseHoverStopped {
- add { AddHandler(MouseHoverStoppedEvent, value); }
- remove { RemoveHandler(MouseHoverStoppedEvent, value); }
- }
- #endregion
-
- #region ScrollBarVisibility
- /// <summary>
- /// Dependency property for <see cref="HorizontalScrollBarVisibility"/>
- /// </summary>
- public static readonly DependencyProperty HorizontalScrollBarVisibilityProperty = ScrollViewer.HorizontalScrollBarVisibilityProperty.AddOwner(typeof(TextEditor), new FrameworkPropertyMetadata(ScrollBarVisibility.Visible));
-
- /// <summary>
- /// Gets/Sets the horizontal scroll bar visibility.
- /// </summary>
- public ScrollBarVisibility HorizontalScrollBarVisibility {
- get { return (ScrollBarVisibility)GetValue(HorizontalScrollBarVisibilityProperty); }
- set { SetValue(HorizontalScrollBarVisibilityProperty, value); }
- }
-
- /// <summary>
- /// Dependency property for <see cref="VerticalScrollBarVisibility"/>
- /// </summary>
- public static readonly DependencyProperty VerticalScrollBarVisibilityProperty = ScrollViewer.VerticalScrollBarVisibilityProperty.AddOwner(typeof(TextEditor), new FrameworkPropertyMetadata(ScrollBarVisibility.Visible));
-
- /// <summary>
- /// Gets/Sets the vertical scroll bar visibility.
- /// </summary>
- public ScrollBarVisibility VerticalScrollBarVisibility {
- get { return (ScrollBarVisibility)GetValue(VerticalScrollBarVisibilityProperty); }
- set { SetValue(VerticalScrollBarVisibilityProperty, value); }
- }
- #endregion
-
- object IServiceProvider.GetService(Type serviceType)
- {
- return textArea.GetService(serviceType);
- }
-
- /// <summary>
- /// Gets the text view position from a point inside the editor.
- /// </summary>
- /// <param name="point">The position, relative to top left
- /// corner of TextEditor control</param>
- /// <returns>The text view position, or null if the point is outside the document.</returns>
- public TextViewPosition? GetPositionFromPoint(Point point)
- {
- if (this.Document == null)
- return null;
- TextView textView = this.TextArea.TextView;
- return textView.GetPosition(TranslatePoint(point, textView) + textView.ScrollOffset);
- }
-
- /// <summary>
- /// Scrolls to the specified line.
- /// This method requires that the TextEditor was already assigned a size (WPF layout must have run prior).
- /// </summary>
- public void ScrollToLine(int line)
- {
- ScrollTo(line, -1);
- }
-
- /// <summary>
- /// Scrolls to the specified line/column.
- /// This method requires that the TextEditor was already assigned a size (WPF layout must have run prior).
- /// </summary>
- public void ScrollTo(int line, int column)
- {
- const double MinimumScrollPercentage = 0.3;
-
- TextView textView = textArea.TextView;
- TextDocument document = textView.Document;
- if (scrollViewer != null && document != null) {
- if (line < 1)
- line = 1;
- if (line > document.LineCount)
- line = document.LineCount;
-
- IScrollInfo scrollInfo = textView;
- if (!scrollInfo.CanHorizontallyScroll) {
- // Word wrap is enabled. Ensure that we have up-to-date info about line height so that we scroll
- // to the correct position.
- // This avoids that the user has to repeat the ScrollTo() call several times when there are very long lines.
- VisualLine vl = textView.GetOrConstructVisualLine(document.GetLineByNumber(line));
- double remainingHeight = scrollViewer.ViewportHeight / 2;
- while (remainingHeight > 0) {
- DocumentLine prevLine = vl.FirstDocumentLine.PreviousLine;
- if (prevLine == null)
- break;
- vl = textView.GetOrConstructVisualLine(prevLine);
- remainingHeight -= vl.Height;
- }
- }
-
- Point p = textArea.TextView.GetVisualPosition(new TextViewPosition(line, Math.Max(1, column)), VisualYPosition.LineMiddle);
- double verticalPos = p.Y - scrollViewer.ViewportHeight / 2;
- if (Math.Abs(verticalPos - scrollViewer.VerticalOffset) > MinimumScrollPercentage * scrollViewer.ViewportHeight) {
- scrollViewer.ScrollToVerticalOffset(Math.Max(0, verticalPos));
- }
- if (column > 0) {
- if (p.X > scrollViewer.ViewportWidth - Caret.MinimumDistanceToViewBorder * 2) {
- double horizontalPos = Math.Max(0, p.X - scrollViewer.ViewportWidth / 2);
- if (Math.Abs(horizontalPos - scrollViewer.HorizontalOffset) > MinimumScrollPercentage * scrollViewer.ViewportWidth) {
- scrollViewer.ScrollToHorizontalOffset(horizontalPos);
- }
- } else {
- scrollViewer.ScrollToHorizontalOffset(0);
- }
- }
- }
- }
- }
+ /// <summary>
+ /// The text editor control.
+ /// Contains a scrollable TextArea.
+ /// </summary>
+ [Localizability(LocalizationCategory.Text), ContentProperty("Text")]
+ public class TextEditor : Control, ITextEditorComponent, IServiceProvider, IWeakEventListener
+ {
+ #region Constructors
+ static TextEditor()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(TextEditor),
+ new FrameworkPropertyMetadata(typeof(TextEditor)));
+ FocusableProperty.OverrideMetadata(typeof(TextEditor),
+ new FrameworkPropertyMetadata(Boxes.True));
+ }
+
+ /// <summary>
+ /// Creates a new TextEditor instance.
+ /// </summary>
+ public TextEditor() : this(new TextArea())
+ {
+ }
+
+ /// <summary>
+ /// Creates a new TextEditor instance.
+ /// </summary>
+ protected TextEditor(TextArea textArea)
+ {
+ if (textArea == null)
+ throw new ArgumentNullException("textArea");
+ this.textArea = textArea;
+
+ textArea.TextView.Services.AddService(typeof(TextEditor), this);
+
+ SetCurrentValue(OptionsProperty, textArea.Options);
+ SetCurrentValue(DocumentProperty, new TextDocument());
+ }
+
+ #endregion
+
+ /// <inheritdoc/>
+ protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer()
+ {
+ return new TextEditorAutomationPeer(this);
+ }
+
+ /// Forward focus to TextArea.
+ /// <inheritdoc/>
+ protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
+ {
+ base.OnGotKeyboardFocus(e);
+ if (e.NewFocus == this)
+ {
+ Keyboard.Focus(this.TextArea);
+ e.Handled = true;
+ }
+ }
+
+ #region Document property
+ /// <summary>
+ /// Document property.
+ /// </summary>
+ public static readonly DependencyProperty DocumentProperty
+ = TextView.DocumentProperty.AddOwner(
+ typeof(TextEditor), new FrameworkPropertyMetadata(OnDocumentChanged));
+
+ /// <summary>
+ /// Gets/Sets the document displayed by the text editor.
+ /// This is a dependency property.
+ /// </summary>
+ public TextDocument Document
+ {
+ get { return (TextDocument)GetValue(DocumentProperty); }
+ set { SetValue(DocumentProperty, value); }
+ }
+
+ /// <summary>
+ /// Occurs when the document property has changed.
+ /// </summary>
+ public event EventHandler DocumentChanged;
+
+ /// <summary>
+ /// Raises the <see cref="DocumentChanged"/> event.
+ /// </summary>
+ protected virtual void OnDocumentChanged(EventArgs e)
+ {
+ if (DocumentChanged != null)
+ {
+ DocumentChanged(this, e);
+ }
+ }
+
+ static void OnDocumentChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
+ {
+ ((TextEditor)dp).OnDocumentChanged((TextDocument)e.OldValue, (TextDocument)e.NewValue);
+ }
+
+ void OnDocumentChanged(TextDocument oldValue, TextDocument newValue)
+ {
+ if (oldValue != null)
+ {
+ TextDocumentWeakEventManager.TextChanged.RemoveListener(oldValue, this);
+ PropertyChangedEventManager.RemoveListener(oldValue.UndoStack, this, "IsOriginalFile");
+ }
+ textArea.Document = newValue;
+ if (newValue != null)
+ {
+ TextDocumentWeakEventManager.TextChanged.AddListener(newValue, this);
+ PropertyChangedEventManager.AddListener(newValue.UndoStack, this, "IsOriginalFile");
+ }
+ OnDocumentChanged(EventArgs.Empty);
+ OnTextChanged(EventArgs.Empty);
+ }
+ #endregion
+
+ #region Options property
+ /// <summary>
+ /// Options property.
+ /// </summary>
+ public static readonly DependencyProperty OptionsProperty
+ = TextView.OptionsProperty.AddOwner(typeof(TextEditor), new FrameworkPropertyMetadata(OnOptionsChanged));
+
+ /// <summary>
+ /// Gets/Sets the options currently used by the text editor.
+ /// </summary>
+ public TextEditorOptions Options
+ {
+ get { return (TextEditorOptions)GetValue(OptionsProperty); }
+ set { SetValue(OptionsProperty, value); }
+ }
+
+ /// <summary>
+ /// Occurs when a text editor option has changed.
+ /// </summary>
+ public event PropertyChangedEventHandler OptionChanged;
+
+ /// <summary>
+ /// Raises the <see cref="OptionChanged"/> event.
+ /// </summary>
+ protected virtual void OnOptionChanged(PropertyChangedEventArgs e)
+ {
+ if (OptionChanged != null)
+ {
+ OptionChanged(this, e);
+ }
+ }
+
+ static void OnOptionsChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
+ {
+ ((TextEditor)dp).OnOptionsChanged((TextEditorOptions)e.OldValue, (TextEditorOptions)e.NewValue);
+ }
+
+ void OnOptionsChanged(TextEditorOptions oldValue, TextEditorOptions newValue)
+ {
+ if (oldValue != null)
+ {
+ PropertyChangedWeakEventManager.RemoveListener(oldValue, this);
+ }
+ textArea.Options = newValue;
+ if (newValue != null)
+ {
+ PropertyChangedWeakEventManager.AddListener(newValue, this);
+ }
+ OnOptionChanged(new PropertyChangedEventArgs(null));
+ }
+
+ /// <inheritdoc cref="IWeakEventListener.ReceiveWeakEvent"/>
+ protected virtual bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
+ {
+ if (managerType == typeof(PropertyChangedWeakEventManager))
+ {
+ OnOptionChanged((PropertyChangedEventArgs)e);
+ return true;
+ }
+ else if (managerType == typeof(TextDocumentWeakEventManager.TextChanged))
+ {
+ OnTextChanged(e);
+ return true;
+ }
+ else if (managerType == typeof(PropertyChangedEventManager))
+ {
+ return HandleIsOriginalChanged((PropertyChangedEventArgs)e);
+ }
+ return false;
+ }
+
+ bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
+ {
+ return ReceiveWeakEvent(managerType, sender, e);
+ }
+ #endregion
+
+ #region Text property
+ /// <summary>
+ /// Gets/Sets the text of the current document.
+ /// </summary>
+ [Localizability(LocalizationCategory.Text), DefaultValue("")]
+ public string Text
+ {
+ get
+ {
+ TextDocument document = this.Document;
+ return document != null ? document.Text : string.Empty;
+ }
+ set
+ {
+ TextDocument document = GetDocument();
+ document.Text = value ?? string.Empty;
+ // after replacing the full text, the caret is positioned at the end of the document
+ // - reset it to the beginning.
+ this.CaretOffset = 0;
+ document.UndoStack.ClearAll();
+ }
+ }
+
+ TextDocument GetDocument()
+ {
+ TextDocument document = this.Document;
+ if (document == null)
+ throw ThrowUtil.NoDocumentAssigned();
+ return document;
+ }
+
+ /// <summary>
+ /// Occurs when the Text property changes.
+ /// </summary>
+ public event EventHandler TextChanged;
+
+ /// <summary>
+ /// Raises the <see cref="TextChanged"/> event.
+ /// </summary>
+ protected virtual void OnTextChanged(EventArgs e)
+ {
+ if (TextChanged != null)
+ {
+ TextChanged(this, e);
+ }
+ }
+ #endregion
+
+ #region TextArea / ScrollViewer properties
+ readonly TextArea textArea;
+ ScrollViewer scrollViewer;
+
+ /// <summary>
+ /// Is called after the template was applied.
+ /// </summary>
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+ scrollViewer = (ScrollViewer)Template.FindName("PART_ScrollViewer", this);
+ }
+
+ /// <summary>
+ /// Gets the text area.
+ /// </summary>
+ public TextArea TextArea
+ {
+ get
+ {
+ return textArea;
+ }
+ }
+
+ /// <summary>
+ /// Gets the scroll viewer used by the text editor.
+ /// This property can return null if the template has not been applied / does not contain a scroll viewer.
+ /// </summary>
+ internal ScrollViewer ScrollViewer
+ {
+ get { return scrollViewer; }
+ }
+
+ bool CanExecute(RoutedUICommand command)
+ {
+ TextArea textArea = this.TextArea;
+ if (textArea == null)
+ return false;
+ else
+ return command.CanExecute(null, textArea);
+ }
+
+ void Execute(RoutedUICommand command)
+ {
+ TextArea textArea = this.TextArea;
+ if (textArea != null)
+ command.Execute(null, textArea);
+ }
+ #endregion
+
+ #region Syntax highlighting
+ /// <summary>
+ /// The <see cref="SyntaxHighlighting"/> property.
+ /// </summary>
+ public static readonly DependencyProperty SyntaxHighlightingProperty =
+ DependencyProperty.Register("SyntaxHighlighting", typeof(IHighlightingDefinition), typeof(TextEditor),
+ new FrameworkPropertyMetadata(OnSyntaxHighlightingChanged));
+
+
+ /// <summary>
+ /// Gets/sets the syntax highlighting definition used to colorize the text.
+ /// </summary>
+ public IHighlightingDefinition SyntaxHighlighting
+ {
+ get { return (IHighlightingDefinition)GetValue(SyntaxHighlightingProperty); }
+ set { SetValue(SyntaxHighlightingProperty, value); }
+ }
+
+ IVisualLineTransformer colorizer;
+
+ static void OnSyntaxHighlightingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ ((TextEditor)d).OnSyntaxHighlightingChanged(e.NewValue as IHighlightingDefinition);
+ }
+
+ void OnSyntaxHighlightingChanged(IHighlightingDefinition newValue)
+ {
+ if (colorizer != null)
+ {
+ this.TextArea.TextView.LineTransformers.Remove(colorizer);
+ colorizer = null;
+ }
+ if (newValue != null)
+ {
+ colorizer = CreateColorizer(newValue);
+ this.TextArea.TextView.LineTransformers.Insert(0, colorizer);
+ }
+ }
+
+ /// <summary>
+ /// Creates the highlighting colorizer for the specified highlighting definition.
+ /// Allows derived classes to provide custom colorizer implementations for special highlighting definitions.
+ /// </summary>
+ /// <returns></returns>
+ protected virtual IVisualLineTransformer CreateColorizer(IHighlightingDefinition highlightingDefinition)
+ {
+ if (highlightingDefinition == null)
+ throw new ArgumentNullException("highlightingDefinition");
+ return new HighlightingColorizer(highlightingDefinition.MainRuleSet);
+ }
+ #endregion
+
+ #region WordWrap
+ /// <summary>
+ /// Word wrap dependency property.
+ /// </summary>
+ public static readonly DependencyProperty WordWrapProperty =
+ DependencyProperty.Register("WordWrap", typeof(bool), typeof(TextEditor),
+ new FrameworkPropertyMetadata(Boxes.False));
+
+ /// <summary>
+ /// Specifies whether the text editor uses word wrapping.
+ /// </summary>
+ /// <remarks>
+ /// Setting WordWrap=true has the same effect as setting HorizontalScrollBarVisibility=Disabled and will override the
+ /// HorizontalScrollBarVisibility setting.
+ /// </remarks>
+ public bool WordWrap
+ {
+ get { return (bool)GetValue(WordWrapProperty); }
+ set { SetValue(WordWrapProperty, Boxes.Box(value)); }
+ }
+ #endregion
+
+ #region IsReadOnly
+ /// <summary>
+ /// IsReadOnly dependency property.
+ /// </summary>
+ public static readonly DependencyProperty IsReadOnlyProperty =
+ DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(TextEditor),
+ new FrameworkPropertyMetadata(Boxes.False, OnIsReadOnlyChanged));
+
+ /// <summary>
+ /// Specifies whether the user can change the text editor content.
+ /// Setting this property will replace the
+ /// <see cref="Editing.TextArea.ReadOnlySectionProvider">TextArea.ReadOnlySectionProvider</see>.
+ /// </summary>
+ public bool IsReadOnly
+ {
+ get { return (bool)GetValue(IsReadOnlyProperty); }
+ set { SetValue(IsReadOnlyProperty, Boxes.Box(value)); }
+ }
+
+ static void OnIsReadOnlyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ TextEditor editor = d as TextEditor;
+ if (editor != null)
+ {
+ if ((bool)e.NewValue)
+ editor.TextArea.ReadOnlySectionProvider = ReadOnlyDocument.Instance;
+ else
+ editor.TextArea.ReadOnlySectionProvider = NoReadOnlySections.Instance;
+
+ TextEditorAutomationPeer peer = TextEditorAutomationPeer.FromElement(editor) as TextEditorAutomationPeer;
+ if (peer != null)
+ {
+ peer.RaiseIsReadOnlyChanged((bool)e.OldValue, (bool)e.NewValue);
+ }
+ }
+ }
+ #endregion
+
+ #region IsModified
+ /// <summary>
+ /// Dependency property for <see cref="IsModified"/>
+ /// </summary>
+ public static readonly DependencyProperty IsModifiedProperty =
+ DependencyProperty.Register("IsModified", typeof(bool), typeof(TextEditor),
+ new FrameworkPropertyMetadata(Boxes.False, OnIsModifiedChanged));
+
+ /// <summary>
+ /// Gets/Sets the 'modified' flag.
+ /// </summary>
+ public bool IsModified
+ {
+ get { return (bool)GetValue(IsModifiedProperty); }
+ set { SetValue(IsModifiedProperty, Boxes.Box(value)); }
+ }
+
+ static void OnIsModifiedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ TextEditor editor = d as TextEditor;
+ if (editor != null)
+ {
+ TextDocument document = editor.Document;
+ if (document != null)
+ {
+ UndoStack undoStack = document.UndoStack;
+ if ((bool)e.NewValue)
+ {
+ if (undoStack.IsOriginalFile)
+ undoStack.DiscardOriginalFileMarker();
+ }
+ else
+ {
+ undoStack.MarkAsOriginalFile();
+ }
+ }
+ }
+ }
+
+ bool HandleIsOriginalChanged(PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "IsOriginalFile")
+ {
+ TextDocument document = this.Document;
+ if (document != null)
+ {
+ SetCurrentValue(IsModifiedProperty, Boxes.Box(!document.UndoStack.IsOriginalFile));
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ #endregion
+
+ #region ShowLineNumbers
+ /// <summary>
+ /// ShowLineNumbers dependency property.
+ /// </summary>
+ public static readonly DependencyProperty ShowLineNumbersProperty =
+ DependencyProperty.Register("ShowLineNumbers", typeof(bool), typeof(TextEditor),
+ new FrameworkPropertyMetadata(Boxes.False, OnShowLineNumbersChanged));
+
+ /// <summary>
+ /// Specifies whether line numbers are shown on the left to the text view.
+ /// </summary>
+ public bool ShowLineNumbers
+ {
+ get { return (bool)GetValue(ShowLineNumbersProperty); }
+ set { SetValue(ShowLineNumbersProperty, Boxes.Box(value)); }
+ }
+
+ static void OnShowLineNumbersChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ TextEditor editor = (TextEditor)d;
+ var leftMargins = editor.TextArea.LeftMargins;
+ if ((bool)e.NewValue)
+ {
+ LineNumberMargin lineNumbers = new LineNumberMargin();
+ Line line = (Line)DottedLineMargin.Create();
+ leftMargins.Insert(0, lineNumbers);
+ leftMargins.Insert(1, line);
+ var lineNumbersForeground = new Binding("LineNumbersForeground") { Source = editor };
+ line.SetBinding(Line.StrokeProperty, lineNumbersForeground);
+ lineNumbers.SetBinding(Control.ForegroundProperty, lineNumbersForeground);
+ }
+ else
+ {
+ for (int i = 0; i < leftMargins.Count; i++)
+ {
+ if (leftMargins[i] is LineNumberMargin)
+ {
+ leftMargins.RemoveAt(i);
+ if (i < leftMargins.Count && DottedLineMargin.IsDottedLineMargin(leftMargins[i]))
+ {
+ leftMargins.RemoveAt(i);
+ }
+ break;
+ }
+ }
+ }
+ }
+ #endregion
+
+ #region LineNumbersForeground
+ /// <summary>
+ /// LineNumbersForeground dependency property.
+ /// </summary>
+ public static readonly DependencyProperty LineNumbersForegroundProperty =
+ DependencyProperty.Register("LineNumbersForeground", typeof(Brush), typeof(TextEditor),
+ new FrameworkPropertyMetadata(Brushes.Gray, OnLineNumbersForegroundChanged));
+
+ /// <summary>
+ /// Gets/sets the Brush used for displaying the foreground color of line numbers.
+ /// </summary>
+ public Brush LineNumbersForeground
+ {
+ get { return (Brush)GetValue(LineNumbersForegroundProperty); }
+ set { SetValue(LineNumbersForegroundProperty, value); }
+ }
+
+ static void OnLineNumbersForegroundChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ TextEditor editor = (TextEditor)d;
+ var lineNumberMargin = editor.TextArea.LeftMargins.FirstOrDefault(margin => margin is LineNumberMargin) as LineNumberMargin; ;
+
+ if (lineNumberMargin != null)
+ {
+ lineNumberMargin.SetValue(Control.ForegroundProperty, e.NewValue);
+ }
+ }
+ #endregion
+
+ #region TextBoxBase-like methods
+ /// <summary>
+ /// Appends text to the end of the document.
+ /// </summary>
+ public void AppendText(string textData)
+ {
+ var document = GetDocument();
+ document.Insert(document.TextLength, textData);
+ }
+
+ /// <summary>
+ /// Begins a group of document changes.
+ /// </summary>
+ public void BeginChange()
+ {
+ GetDocument().BeginUpdate();
+ }
+
+ /// <summary>
+ /// Copies the current selection to the clipboard.
+ /// </summary>
+ public void Copy()
+ {
+ Execute(ApplicationCommands.Copy);
+ }
+
+ /// <summary>
+ /// Removes the current selection and copies it to the clipboard.
+ /// </summary>
+ public void Cut()
+ {
+ Execute(ApplicationCommands.Cut);
+ }
+
+ /// <summary>
+ /// Begins a group of document changes and returns an object that ends the group of document
+ /// changes when it is disposed.
+ /// </summary>
+ public IDisposable DeclareChangeBlock()
+ {
+ return GetDocument().RunUpdate();
+ }
+
+ /// <summary>
+ /// Ends the current group of document changes.
+ /// </summary>
+ public void EndChange()
+ {
+ GetDocument().EndUpdate();
+ }
+
+ /// <summary>
+ /// Scrolls one line down.
+ /// </summary>
+ public void LineDown()
+ {
+ if (scrollViewer != null)
+ scrollViewer.LineDown();
+ }
+
+ /// <summary>
+ /// Scrolls to the left.
+ /// </summary>
+ public void LineLeft()
+ {
+ if (scrollViewer != null)
+ scrollViewer.LineLeft();
+ }
+
+ /// <summary>
+ /// Scrolls to the right.
+ /// </summary>
+ public void LineRight()
+ {
+ if (scrollViewer != null)
+ scrollViewer.LineRight();
+ }
+
+ /// <summary>
+ /// Scrolls one line up.
+ /// </summary>
+ public void LineUp()
+ {
+ if (scrollViewer != null)
+ scrollViewer.LineUp();
+ }
+
+ /// <summary>
+ /// Scrolls one page down.
+ /// </summary>
+ public void PageDown()
+ {
+ if (scrollViewer != null)
+ scrollViewer.PageDown();
+ }
+
+ /// <summary>
+ /// Scrolls one page up.
+ /// </summary>
+ public void PageUp()
+ {
+ if (scrollViewer != null)
+ scrollViewer.PageUp();
+ }
+
+ /// <summary>
+ /// Scrolls one page left.
+ /// </summary>
+ public void PageLeft()
+ {
+ if (scrollViewer != null)
+ scrollViewer.PageLeft();
+ }
+
+ /// <summary>
+ /// Scrolls one page right.
+ /// </summary>
+ public void PageRight()
+ {
+ if (scrollViewer != null)
+ scrollViewer.PageRight();
+ }
+
+ /// <summary>
+ /// Pastes the clipboard content.
+ /// </summary>
+ public void Paste()
+ {
+ Execute(ApplicationCommands.Paste);
+ }
+
+ /// <summary>
+ /// Redoes the most recent undone command.
+ /// </summary>
+ /// <returns>True is the redo operation was successful, false is the redo stack is empty.</returns>
+ public bool Redo()
+ {
+ if (CanExecute(ApplicationCommands.Redo))
+ {
+ Execute(ApplicationCommands.Redo);
+ return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Scrolls to the end of the document.
+ /// </summary>
+ public void ScrollToEnd()
+ {
+ ApplyTemplate(); // ensure scrollViewer is created
+ if (scrollViewer != null)
+ scrollViewer.ScrollToEnd();
+ }
+
+ /// <summary>
+ /// Scrolls to the start of the document.
+ /// </summary>
+ public void ScrollToHome()
+ {
+ ApplyTemplate(); // ensure scrollViewer is created
+ if (scrollViewer != null)
+ scrollViewer.ScrollToHome();
+ }
+
+ /// <summary>
+ /// Scrolls to the specified position in the document.
+ /// </summary>
+ public void ScrollToHorizontalOffset(double offset)
+ {
+ ApplyTemplate(); // ensure scrollViewer is created
+ if (scrollViewer != null)
+ scrollViewer.ScrollToHorizontalOffset(offset);
+ }
+
+ /// <summary>
+ /// Scrolls to the specified position in the document.
+ /// </summary>
+ public void ScrollToVerticalOffset(double offset)
+ {
+ ApplyTemplate(); // ensure scrollViewer is created
+ if (scrollViewer != null)
+ scrollViewer.ScrollToVerticalOffset(offset);
+ }
+
+ /// <summary>
+ /// Selects the entire text.
+ /// </summary>
+ public void SelectAll()
+ {
+ Execute(ApplicationCommands.SelectAll);
+ }
+
+ /// <summary>
+ /// Undoes the most recent command.
+ /// </summary>
+ /// <returns>True is the undo operation was successful, false is the undo stack is empty.</returns>
+ public bool Undo()
+ {
+ if (CanExecute(ApplicationCommands.Undo))
+ {
+ Execute(ApplicationCommands.Undo);
+ return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Gets if the most recent undone command can be redone.
+ /// </summary>
+ public bool CanRedo
+ {
+ get { return CanExecute(ApplicationCommands.Redo); }
+ }
+
+ /// <summary>
+ /// Gets if the most recent command can be undone.
+ /// </summary>
+ public bool CanUndo
+ {
+ get { return CanExecute(ApplicationCommands.Undo); }
+ }
+
+ /// <summary>
+ /// Gets the vertical size of the document.
+ /// </summary>
+ public double ExtentHeight
+ {
+ get
+ {
+ return scrollViewer != null ? scrollViewer.ExtentHeight : 0;
+ }
+ }
+
+ /// <summary>
+ /// Gets the horizontal size of the current document region.
+ /// </summary>
+ public double ExtentWidth
+ {
+ get
+ {
+ return scrollViewer != null ? scrollViewer.ExtentWidth : 0;
+ }
+ }
+
+ /// <summary>
+ /// Gets the horizontal size of the viewport.
+ /// </summary>
+ public double ViewportHeight
+ {
+ get
+ {
+ return scrollViewer != null ? scrollViewer.ViewportHeight : 0;
+ }
+ }
+
+ /// <summary>
+ /// Gets the horizontal size of the viewport.
+ /// </summary>
+ public double ViewportWidth
+ {
+ get
+ {
+ return scrollViewer != null ? scrollViewer.ViewportWidth : 0;
+ }
+ }
+
+ /// <summary>
+ /// Gets the vertical scroll position.
+ /// </summary>
+ public double VerticalOffset
+ {
+ get
+ {
+ return scrollViewer != null ? scrollViewer.VerticalOffset : 0;
+ }
+ }
+
+ /// <summary>
+ /// Gets the horizontal scroll position.
+ /// </summary>
+ public double HorizontalOffset
+ {
+ get
+ {
+ return scrollViewer != null ? scrollViewer.HorizontalOffset : 0;
+ }
+ }
+ #endregion
+
+ #region TextBox methods
+ /// <summary>
+ /// Gets/Sets the selected text.
+ /// </summary>
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public string SelectedText
+ {
+ get
+ {
+ TextArea textArea = this.TextArea;
+ // We'll get the text from the whole surrounding segment.
+ // This is done to ensure that SelectedText.Length == SelectionLength.
+ if (textArea != null && textArea.Document != null && !textArea.Selection.IsEmpty)
+ return textArea.Document.GetText(textArea.Selection.SurroundingSegment);
+ else
+ return string.Empty;
+ }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+ TextArea textArea = this.TextArea;
+ if (textArea != null && textArea.Document != null)
+ {
+ int offset = this.SelectionStart;
+ int length = this.SelectionLength;
+ textArea.Document.Replace(offset, length, value);
+ // keep inserted text selected
+ textArea.Selection = SimpleSelection.Create(textArea, offset, offset + value.Length);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets/sets the caret position.
+ /// </summary>
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public int CaretOffset
+ {
+ get
+ {
+ TextArea textArea = this.TextArea;
+ if (textArea != null)
+ return textArea.Caret.Offset;
+ else
+ return 0;
+ }
+ set
+ {
+ TextArea textArea = this.TextArea;
+ if (textArea != null)
+ textArea.Caret.Offset = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets/sets the start position of the selection.
+ /// </summary>
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public int SelectionStart
+ {
+ get
+ {
+ TextArea textArea = this.TextArea;
+ if (textArea != null)
+ {
+ if (textArea.Selection.IsEmpty)
+ return textArea.Caret.Offset;
+ else
+ return textArea.Selection.SurroundingSegment.Offset;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ set
+ {
+ Select(value, SelectionLength);
+ }
+ }
+
+ /// <summary>
+ /// Gets/sets the length of the selection.
+ /// </summary>
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public int SelectionLength
+ {
+ get
+ {
+ TextArea textArea = this.TextArea;
+ if (textArea != null && !textArea.Selection.IsEmpty)
+ return textArea.Selection.SurroundingSegment.Length;
+ else
+ return 0;
+ }
+ set
+ {
+ Select(SelectionStart, value);
+ }
+ }
+
+ /// <summary>
+ /// Selects the specified text section.
+ /// </summary>
+ public void Select(int start, int length)
+ {
+ int documentLength = Document != null ? Document.TextLength : 0;
+
+ if (start < 0 || start > documentLength)
+ {
+ Debug.WriteLine(new ArgumentOutOfRangeException("start", start, "Value must be between 0 and " + documentLength));
+ return;
+ }
+
+ if (length < 0 || start + length > documentLength)
+ {
+ Debug.WriteLine(new ArgumentOutOfRangeException("length", length, "Value must be between 0 and " + (documentLength - length)));
+ return;
+ }
+
+ textArea.Selection = SimpleSelection.Create(textArea, start, start + length);
+ textArea.Caret.Offset = start + length;
+ }
+
+ /// <summary>
+ /// Gets the number of lines in the document.
+ /// </summary>
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public int LineCount
+ {
+ get
+ {
+ TextDocument document = this.Document;
+ if (document != null)
+ return document.LineCount;
+ else
+ return 1;
+ }
+ }
+
+ /// <summary>
+ /// Clears the text.
+ /// </summary>
+ public void Clear()
+ {
+ this.Text = string.Empty;
+ }
+ #endregion
+
+ #region Loading from stream
+ /// <summary>
+ /// Loads the text from the stream, auto-detecting the encoding.
+ /// </summary>
+ /// <remarks>
+ /// This method sets <see cref="IsModified"/> to false.
+ /// </remarks>
+ public void Load(Stream stream)
+ {
+ using (StreamReader reader = FileReader.OpenStream(stream, this.Encoding ?? Encoding.UTF8))
+ {
+ this.Text = reader.ReadToEnd();
+ this.Encoding = reader.CurrentEncoding; // assign encoding after ReadToEnd() so that the StreamReader can autodetect the encoding
+ }
+ this.IsModified = false;
+ }
+
+ /// <summary>
+ /// Loads the text from the stream, auto-detecting the encoding.
+ /// </summary>
+ public void Load(string fileName)
+ {
+ if (fileName == null)
+ throw new ArgumentNullException("fileName");
+ using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
+ {
+ Load(fs);
+ }
+ }
+
+ /// <summary>
+ /// Gets/sets the encoding used when the file is saved.
+ /// </summary>
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public Encoding Encoding { get; set; }
+
+ /// <summary>
+ /// Saves the text to the stream.
+ /// </summary>
+ /// <remarks>
+ /// This method sets <see cref="IsModified"/> to false.
+ /// </remarks>
+ public void Save(Stream stream)
+ {
+ if (stream == null)
+ throw new ArgumentNullException("stream");
+ StreamWriter writer = new StreamWriter(stream, this.Encoding ?? Encoding.UTF8);
+ writer.Write(this.Text);
+ writer.Flush();
+ // do not close the stream
+ this.IsModified = false;
+ }
+
+ /// <summary>
+ /// Saves the text to the file.
+ /// </summary>
+ public void Save(string fileName)
+ {
+ if (fileName == null)
+ throw new ArgumentNullException("fileName");
+ using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
+ {
+ Save(fs);
+ }
+ }
+ #endregion
+
+ #region MouseHover events
+ /// <summary>
+ /// The PreviewMouseHover event.
+ /// </summary>
+ public static readonly RoutedEvent PreviewMouseHoverEvent =
+ TextView.PreviewMouseHoverEvent.AddOwner(typeof(TextEditor));
+
+ /// <summary>
+ /// The MouseHover event.
+ /// </summary>
+ public static readonly RoutedEvent MouseHoverEvent =
+ TextView.MouseHoverEvent.AddOwner(typeof(TextEditor));
+
+
+ /// <summary>
+ /// The PreviewMouseHoverStopped event.
+ /// </summary>
+ public static readonly RoutedEvent PreviewMouseHoverStoppedEvent =
+ TextView.PreviewMouseHoverStoppedEvent.AddOwner(typeof(TextEditor));
+
+ /// <summary>
+ /// The MouseHoverStopped event.
+ /// </summary>
+ public static readonly RoutedEvent MouseHoverStoppedEvent =
+ TextView.MouseHoverStoppedEvent.AddOwner(typeof(TextEditor));
+
+
+ /// <summary>
+ /// Occurs when the mouse has hovered over a fixed location for some time.
+ /// </summary>
+ public event MouseEventHandler PreviewMouseHover
+ {
+ add { AddHandler(PreviewMouseHoverEvent, value); }
+ remove { RemoveHandler(PreviewMouseHoverEvent, value); }
+ }
+
+ /// <summary>
+ /// Occurs when the mouse has hovered over a fixed location for some time.
+ /// </summary>
+ public event MouseEventHandler MouseHover
+ {
+ add { AddHandler(MouseHoverEvent, value); }
+ remove { RemoveHandler(MouseHoverEvent, value); }
+ }
+
+ /// <summary>
+ /// Occurs when the mouse had previously hovered but now started moving again.
+ /// </summary>
+ public event MouseEventHandler PreviewMouseHoverStopped
+ {
+ add { AddHandler(PreviewMouseHoverStoppedEvent, value); }
+ remove { RemoveHandler(PreviewMouseHoverStoppedEvent, value); }
+ }
+
+ /// <summary>
+ /// Occurs when the mouse had previously hovered but now started moving again.
+ /// </summary>
+ public event MouseEventHandler MouseHoverStopped
+ {
+ add { AddHandler(MouseHoverStoppedEvent, value); }
+ remove { RemoveHandler(MouseHoverStoppedEvent, value); }
+ }
+ #endregion
+
+ #region ScrollBarVisibility
+ /// <summary>
+ /// Dependency property for <see cref="HorizontalScrollBarVisibility"/>
+ /// </summary>
+ public static readonly DependencyProperty HorizontalScrollBarVisibilityProperty = ScrollViewer.HorizontalScrollBarVisibilityProperty.AddOwner(typeof(TextEditor), new FrameworkPropertyMetadata(ScrollBarVisibility.Visible));
+
+ /// <summary>
+ /// Gets/Sets the horizontal scroll bar visibility.
+ /// </summary>
+ public ScrollBarVisibility HorizontalScrollBarVisibility
+ {
+ get { return (ScrollBarVisibility)GetValue(HorizontalScrollBarVisibilityProperty); }
+ set { SetValue(HorizontalScrollBarVisibilityProperty, value); }
+ }
+
+ /// <summary>
+ /// Dependency property for <see cref="VerticalScrollBarVisibility"/>
+ /// </summary>
+ public static readonly DependencyProperty VerticalScrollBarVisibilityProperty = ScrollViewer.VerticalScrollBarVisibilityProperty.AddOwner(typeof(TextEditor), new FrameworkPropertyMetadata(ScrollBarVisibility.Visible));
+
+ /// <summary>
+ /// Gets/Sets the vertical scroll bar visibility.
+ /// </summary>
+ public ScrollBarVisibility VerticalScrollBarVisibility
+ {
+ get { return (ScrollBarVisibility)GetValue(VerticalScrollBarVisibilityProperty); }
+ set { SetValue(VerticalScrollBarVisibilityProperty, value); }
+ }
+ #endregion
+
+ object IServiceProvider.GetService(Type serviceType)
+ {
+ return textArea.GetService(serviceType);
+ }
+
+ /// <summary>
+ /// Gets the text view position from a point inside the editor.
+ /// </summary>
+ /// <param name="point">The position, relative to top left
+ /// corner of TextEditor control</param>
+ /// <returns>The text view position, or null if the point is outside the document.</returns>
+ public TextViewPosition? GetPositionFromPoint(Point point)
+ {
+ if (this.Document == null)
+ return null;
+ TextView textView = this.TextArea.TextView;
+ return textView.GetPosition(TranslatePoint(point, textView) + textView.ScrollOffset);
+ }
+
+ /// <summary>
+ /// Scrolls to the specified line.
+ /// This method requires that the TextEditor was already assigned a size (WPF layout must have run prior).
+ /// </summary>
+ public void ScrollToLine(int line)
+ {
+ ScrollTo(line, -1);
+ }
+
+ /// <summary>
+ /// Scrolls to the specified line/column.
+ /// This method requires that the TextEditor was already assigned a size (WPF layout must have run prior).
+ /// </summary>
+ public void ScrollTo(int line, int column)
+ {
+ const double MinimumScrollPercentage = 0.3;
+
+ TextView textView = textArea.TextView;
+ TextDocument document = textView.Document;
+ if (scrollViewer != null && document != null)
+ {
+ if (line < 1)
+ line = 1;
+ if (line > document.LineCount)
+ line = document.LineCount;
+
+ IScrollInfo scrollInfo = textView;
+ if (!scrollInfo.CanHorizontallyScroll)
+ {
+ // Word wrap is enabled. Ensure that we have up-to-date info about line height so that we scroll
+ // to the correct position.
+ // This avoids that the user has to repeat the ScrollTo() call several times when there are very long lines.
+ VisualLine vl = textView.GetOrConstructVisualLine(document.GetLineByNumber(line));
+ double remainingHeight = scrollViewer.ViewportHeight / 2;
+ while (remainingHeight > 0)
+ {
+ DocumentLine prevLine = vl.FirstDocumentLine.PreviousLine;
+ if (prevLine == null)
+ break;
+ vl = textView.GetOrConstructVisualLine(prevLine);
+ remainingHeight -= vl.Height;
+ }
+ }
+
+ Point p = textArea.TextView.GetVisualPosition(new TextViewPosition(line, Math.Max(1, column)), VisualYPosition.LineMiddle);
+ double verticalPos = p.Y - scrollViewer.ViewportHeight / 2;
+ if (Math.Abs(verticalPos - scrollViewer.VerticalOffset) > MinimumScrollPercentage * scrollViewer.ViewportHeight)
+ {
+ scrollViewer.ScrollToVerticalOffset(Math.Max(0, verticalPos));
+ }
+ if (column > 0)
+ {
+ if (p.X > scrollViewer.ViewportWidth - Caret.MinimumDistanceToViewBorder * 2)
+ {
+ double horizontalPos = Math.Max(0, p.X - scrollViewer.ViewportWidth / 2);
+ if (Math.Abs(horizontalPos - scrollViewer.HorizontalOffset) > MinimumScrollPercentage * scrollViewer.ViewportWidth)
+ {
+ scrollViewer.ScrollToHorizontalOffset(horizontalPos);
+ }
+ }
+ else
+ {
+ scrollViewer.ScrollToHorizontalOffset(0);
+ }
+ }
+ }
+ }
+ }
} \ No newline at end of file
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting/Parsing/ScriptParser.cs b/Software/Visual_Studio/Scripting/Tango.Scripting/Parsing/ScriptParser.cs
index e9cb8fc4c..2e7086ce0 100644
--- a/Software/Visual_Studio/Scripting/Tango.Scripting/Parsing/ScriptParser.cs
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting/Parsing/ScriptParser.cs
@@ -138,9 +138,32 @@ namespace Tango.Scripting.Parsing
varSymbol.Type = type;
varSymbol.Class = ReplaceFakeScript(symbol.ContainingType?.Name);
varSymbol.Kind = symbol.Kind;
+ varSymbol.RealSymbol = symbol;
varSymbol.Accessibility = symbol.DeclaredAccessibility;
varSymbol.ContainingNamespace = ReplaceFakeScript(symbol.ContainingNamespace?.Name);
varSymbol.Summary = GetSymbolDocumentation(symbol);
+
+ try
+ {
+ if (symbol.Kind == SymbolKind.Local && symbol.DeclaringSyntaxReferences.Count() > 0)
+ {
+ var node = symbol.DeclaringSyntaxReferences.First().GetSyntax() as VariableDeclaratorSyntax;
+
+ if (node != null)
+ {
+ varSymbol.IsUnassigned = node.Initializer == null;
+ }
+ }
+ }
+ catch { }
+
+ try
+ {
+ varSymbol.Offset = symbol.Locations[0].SourceSpan.Start;
+ varSymbol.Length = symbol.Locations[0].SourceSpan.Length;
+ }
+ catch { }
+
vars.Add(varSymbol);
if (type == "?")
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting/Parsing/ScriptSymbol.cs b/Software/Visual_Studio/Scripting/Tango.Scripting/Parsing/ScriptSymbol.cs
index d6fdaeebf..4b34837af 100644
--- a/Software/Visual_Studio/Scripting/Tango.Scripting/Parsing/ScriptSymbol.cs
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting/Parsing/ScriptSymbol.cs
@@ -17,6 +17,10 @@ namespace Tango.Scripting.Parsing
public String ContainingNamespace { get; set; }
public List<KeyValuePair<String,String>> Parameters { get; set; }
public String Summary { get; set; }
+ public int Offset { get; set; }
+ public int Length { get; set; }
+ public bool IsUnassigned { get; set; }
+ public ISymbol RealSymbol { get; set; }
public ScriptSymbol()
{
diff --git a/Software/Visual_Studio/Tango.BL/Entities/HardwareVersion.cs b/Software/Visual_Studio/Tango.BL/Entities/HardwareVersion.cs
index ed8596192..590fe9e13 100644
--- a/Software/Visual_Studio/Tango.BL/Entities/HardwareVersion.cs
+++ b/Software/Visual_Studio/Tango.BL/Entities/HardwareVersion.cs
@@ -1,5 +1,7 @@
+using Newtonsoft.Json;
using System;
using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -93,6 +95,13 @@ namespace Tango.BL.Entities
});
}
+ [NotMapped]
+ [JsonIgnore]
+ public String FullName
+ {
+ get { return $"{Name} v{Version}"; }
+ }
+
/// <summary>
/// Initializes a new instance of the <see cref="HardwareVersion" /> class.
/// </summary>
diff --git a/Software/Visual_Studio/Tango.ColorLib.GradientTest.CLI/Program.cs b/Software/Visual_Studio/Tango.ColorLib.GradientTest.CLI/Program.cs
index 608228026..beec3a37c 100644
--- a/Software/Visual_Studio/Tango.ColorLib.GradientTest.CLI/Program.cs
+++ b/Software/Visual_Studio/Tango.ColorLib.GradientTest.CLI/Program.cs
@@ -116,26 +116,33 @@ namespace Tango.ColorLib.GradientTest.CLI
Key = 0.0682,*/
});
//RGB Stop 3
- input.Stops.Add(new GradientInputStop()
+ GradientInputStop a = new GradientInputStop()
{
- // ColorSpace = ColorSpace.Rgb,
- // Offset = 0,
- // Red = 25,
- // Green = 139,
- // Blue = 246,
- ColorSpace = ColorSpace.Lab,
+ ColorSpace = ColorSpace.Volume,
Offset = 0.75,
- L =32,
- A = 9.3326,
- B = -9.6336,
- /* ColorSpace = ColorSpace.Volume,
- Offset = 0,
-
- Cyan = 41.7186,
- Magenta = 28.1257,
- Yellow =0,
- Key = 0.5887*/
+ };
+ a.LiquidVolumes.Add(new LiquidVolume()
+ {
+ LiquidType = LiquidType.Cyan,
+ Volume = 50
+ });
+ a.LiquidVolumes.Add(new LiquidVolume()
+ {
+ LiquidType = LiquidType.Magenta,
+ Volume = 0
});
+ a.LiquidVolumes.Add(new LiquidVolume()
+ {
+ LiquidType = LiquidType.Yellow,
+ Volume = 50
+ });
+ a.LiquidVolumes.Add(new LiquidVolume()
+ {
+ LiquidType = LiquidType.Black,
+ Volume = 0
+ });
+ input.Stops.Add(a);
+
//RGB Stop 4
input.Stops.Add(new GradientInputStop()
{
diff --git a/Software/Visual_Studio/Tango.Insights/InsightsFrame.cs b/Software/Visual_Studio/Tango.Insights/InsightsFrame.cs
new file mode 100644
index 000000000..4ea2a1c13
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Insights/InsightsFrame.cs
@@ -0,0 +1,64 @@
+using LiteDB;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.PMR.Diagnostics;
+using Tango.PMR.Insights;
+using Tango.Transport.Compression;
+
+namespace Tango.Insights
+{
+ public class InsightsFrame
+ {
+ [BsonId(true)]
+ public int Id { get; set; }
+ public DateTime Time { get; set; }
+ public bool IsEmpty { get; set; }
+ public byte[] MonitorsData { get; set; }
+
+ public static InsightsFrame CreateEmpty(DateTime timeUtc)
+ {
+ InsightsFrame frame = new InsightsFrame();
+ frame.Time = timeUtc;
+ frame.IsEmpty = true;
+ frame.MonitorsData = null;
+ return frame;
+ }
+
+ public static InsightsFrame FromDiagnosticsMonitors(DiagnosticsMonitors diagnosticsMonitors, DateTime timeUtc)
+ {
+ InsightsMonitors insightsMonitors = InsightsHelper.MapMonitors(diagnosticsMonitors);
+ return FromInsightsMonitors(insightsMonitors, timeUtc);
+ }
+
+ public static InsightsFrame FromInsightsMonitors(InsightsMonitors insightsMonitors, DateTime timeUtc)
+ {
+ InsightsFrame frame = new InsightsFrame();
+ frame.Time = timeUtc;
+
+ byte[] data = insightsMonitors.ToBytes();
+ byte[] compressedData = SevenZipHelper.Compress(data);
+
+ frame.MonitorsData = compressedData;
+
+ return frame;
+ }
+
+ public InsightsMonitors ToInsightsMonitors()
+ {
+ if (IsEmpty)
+ {
+ return InsightsHelper.CreateEmptyGap();
+ }
+ else
+ {
+ var uncompressed = SevenZipHelper.Decompress(MonitorsData);
+ var insightsMonitors = InsightsMonitors.Parser.ParseFrom(uncompressed);
+ return insightsMonitors;
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Insights/InsightsHelper.cs b/Software/Visual_Studio/Tango.Insights/InsightsHelper.cs
new file mode 100644
index 000000000..202e2574d
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Insights/InsightsHelper.cs
@@ -0,0 +1,85 @@
+using Google.Protobuf.Collections;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.PMR.Diagnostics;
+using Tango.PMR.Insights;
+
+namespace Tango.Insights
+{
+ public static class InsightsHelper
+ {
+ private static List<PropertyInfo> _diagnosticsProperties;
+ private static List<PropertyInfo> _insightsProperties;
+
+ static InsightsHelper()
+ {
+ _diagnosticsProperties = new List<PropertyInfo>();
+ _insightsProperties = new List<PropertyInfo>();
+
+ foreach (var prop in typeof(DiagnosticsMonitors).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
+ {
+ _diagnosticsProperties.Add(prop);
+ }
+
+ foreach (var prop in typeof(InsightsMonitors).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
+ {
+ _insightsProperties.Add(prop);
+ }
+ }
+
+ public static InsightsMonitors MapMonitors(DiagnosticsMonitors diagnosticsMonitors)
+ {
+ InsightsMonitors insightsMonitors = new InsightsMonitors();
+
+ for (int i = 0; i < _diagnosticsProperties.Count; i++)
+ {
+ if (_diagnosticsProperties[i].PropertyType == typeof(RepeatedField<double>))
+ {
+ var arr = _diagnosticsProperties[i].GetValue(diagnosticsMonitors) as RepeatedField<double>;
+
+ if (arr.Count > 0)
+ {
+ _insightsProperties[i].SetValue(insightsMonitors, arr.Average());
+ }
+ }
+ }
+
+ return insightsMonitors;
+ }
+
+ public static InsightsMonitors AverageMonitors(List<InsightsMonitors> insightsMonitorsCollection)
+ {
+ InsightsMonitors monitors = new InsightsMonitors();
+
+ foreach (var prop in _insightsProperties.Where(x => !typeof(IEnumerable).IsAssignableFrom(x.PropertyType)).ToList())
+ {
+ prop.SetValue(monitors, insightsMonitorsCollection.Average(x => (double)prop.GetValue(x)));
+ }
+
+ return monitors;
+ }
+
+ public static InsightsMonitors AverageMonitors(List<DiagnosticsMonitors> diagnosticsMonitorsCollection)
+ {
+ List<InsightsMonitors> insightsMonitorsCollection = diagnosticsMonitorsCollection.ToList().Select(x => InsightsHelper.MapMonitors(x)).ToList();
+ return AverageMonitors(insightsMonitorsCollection);
+ }
+
+ public static InsightsMonitors CreateEmptyGap()
+ {
+ InsightsMonitors monitors = new InsightsMonitors();
+
+ foreach (var prop in _insightsProperties.Where(x => !typeof(IEnumerable).IsAssignableFrom(x.PropertyType)).ToList())
+ {
+ prop.SetValue(monitors, double.NaN);
+ }
+
+ return monitors;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Insights/InsightsListener.cs b/Software/Visual_Studio/Tango.Insights/InsightsListener.cs
new file mode 100644
index 000000000..0df5b63a1
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Insights/InsightsListener.cs
@@ -0,0 +1,121 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Timers;
+using Tango.Integration.Operation;
+using Tango.PMR.Diagnostics;
+using Tango.PMR.Insights;
+
+namespace Tango.Insights
+{
+ public class InsightsListener
+ {
+ private InsightsManager _manager;
+ private IMachineOperator _operator;
+ private Timer _timer;
+ private List<DiagnosticsMonitors> _diagnosticsQueue;
+ private int _timerCount;
+ private int _deleteTicks;
+ private bool _writing;
+
+ public bool IsStarted { get; private set; }
+ public TimeSpan WriteInterval { get; set; }
+ public TimeSpan DeleteInterval { get; set; }
+ public TimeSpan MaxFramesStorage { get; set; }
+
+ public InsightsListener(InsightsManager manager, IMachineOperator machineOperator)
+ {
+ _diagnosticsQueue = new List<DiagnosticsMonitors>();
+
+ WriteInterval = TimeSpan.FromMinutes(0.1);
+ DeleteInterval = TimeSpan.FromMinutes(60);
+ MaxFramesStorage = TimeSpan.FromDays(30);
+
+ _manager = manager;
+ _operator = machineOperator;
+
+ _operator.DiagnosticsDataAvailable += _operator_DiagnosticsDataAvailable;
+ }
+
+ public InsightsListener(IMachineOperator machineOperator) : this(InsightsManager.Default, machineOperator)
+ {
+
+ }
+
+ public void Start()
+ {
+ if (!IsStarted)
+ {
+ if (_timer == null)
+ {
+ _timer = new Timer();
+ _timer.Interval = WriteInterval.TotalMilliseconds;
+ }
+
+ _writing = false;
+ _timerCount = 0;
+ _deleteTicks = (int)(DeleteInterval.TotalMilliseconds / WriteInterval.TotalMilliseconds);
+
+ _diagnosticsQueue.Clear();
+ IsStarted = true;
+ _timer.Elapsed += _timer_Elapsed;
+ _timer.Start();
+ }
+ }
+
+ public void Stop()
+ {
+ if (IsStarted)
+ {
+ _timer.Stop();
+ _diagnosticsQueue.Clear();
+ }
+ }
+
+ private void _operator_DiagnosticsDataAvailable(object sender, PMR.Diagnostics.StartDiagnosticsResponse e)
+ {
+ if (IsStarted && e.Monitors != null)
+ {
+ _diagnosticsQueue.Add(e.Monitors);
+ }
+ }
+
+ private void _timer_Elapsed(object sender, ElapsedEventArgs e)
+ {
+ if (!IsStarted || _writing) return;
+
+ _writing = true;
+
+ InsightsFrame frame = null;
+
+ if (_diagnosticsQueue.Count > 0)
+ {
+ var queue = _diagnosticsQueue.ToList();
+ _diagnosticsQueue.Clear();
+
+ InsightsMonitors monitorsAvg = InsightsHelper.AverageMonitors(queue);
+ queue.Clear();
+
+ frame = InsightsFrame.FromInsightsMonitors(monitorsAvg, DateTime.UtcNow.Subtract(WriteInterval));
+ }
+ else
+ {
+ frame = InsightsFrame.CreateEmpty(DateTime.UtcNow.Subtract(WriteInterval));
+ }
+
+ _manager.InsertFrame(frame);
+
+ _timerCount++;
+
+ if (_timerCount >= _deleteTicks)
+ {
+ _timerCount = 0;
+ _manager.DeleteFrames(DateTime.UtcNow.Subtract(MaxFramesStorage));
+ }
+
+ _writing = false;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Insights/InsightsManager.cs b/Software/Visual_Studio/Tango.Insights/InsightsManager.cs
new file mode 100644
index 000000000..7597aabf4
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Insights/InsightsManager.cs
@@ -0,0 +1,81 @@
+using LiteDB;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.Insights
+{
+ public class InsightsManager : IDisposable
+ {
+ private const string INSIGHTS_COLLECTION = "Insights";
+
+ private static InsightsManager _instance;
+ public static InsightsManager Default
+ {
+ get
+ {
+ if (_instance == null)
+ {
+ _instance = new InsightsManager(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Twine", "Tango", "Insights", Path.GetFileNameWithoutExtension(AppDomain.CurrentDomain.FriendlyName) + ".insights"));
+ }
+
+ return _instance;
+ }
+ }
+
+ private LiteDatabase _database;
+
+ public String DatabasePath { get; private set; }
+
+ private InsightsManager(String databasePath)
+ {
+ DatabasePath = databasePath;
+ Directory.CreateDirectory(Path.GetDirectoryName(DatabasePath));
+ _database = new LiteDatabase($"Filename={DatabasePath}");
+ }
+
+ public virtual void Dispose()
+ {
+ if (_database != null)
+ {
+ try
+ {
+ _database.Dispose();
+ _database = null;
+ }
+ catch { }
+ }
+ }
+
+ ~InsightsManager()
+ {
+ Dispose();
+ }
+
+ private ILiteCollection<InsightsFrame> GetCollection()
+ {
+ return _database.GetCollection<InsightsFrame>(INSIGHTS_COLLECTION);
+ }
+
+ public virtual void InsertFrame(InsightsFrame frame)
+ {
+ var collection = GetCollection();
+ collection.Insert(frame);
+ }
+
+ public virtual List<InsightsFrame> GetFrames(DateTime startUTC, DateTime endUTC)
+ {
+ var collection = GetCollection();
+ return collection.Find(x => x.Time >= startUTC && x.Time <= endUTC).ToList();
+ }
+
+ public virtual int DeleteFrames(DateTime maxDateUTC)
+ {
+ var collection = GetCollection();
+ return collection.DeleteMany(x => x.Time < maxDateUTC);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Insights/Properties/AssemblyInfo.cs b/Software/Visual_Studio/Tango.Insights/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..2c2308493
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Insights/Properties/AssemblyInfo.cs
@@ -0,0 +1,7 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("Tango - Insights Library")]
+[assembly: AssemblyVersion("2.0.12.1737")]
+[assembly: ComVisible(false)] \ No newline at end of file
diff --git a/Software/Visual_Studio/Tango.Insights/Tango.Insights.csproj b/Software/Visual_Studio/Tango.Insights/Tango.Insights.csproj
new file mode 100644
index 000000000..0b9ecc641
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Insights/Tango.Insights.csproj
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{4A55C185-3F8D-41B0-8815-C15F6213A14A}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Tango.Insights</RootNamespace>
+ <AssemblyName>Tango.Insights</AssemblyName>
+ <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <Deterministic>true</Deterministic>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Versioning\GlobalVersionInfo.cs">
+ <Link>GlobalVersionInfo.cs</Link>
+ </Compile>
+ <Compile Include="InsightsHelper.cs" />
+ <Compile Include="InsightsFrame.cs" />
+ <Compile Include="InsightsListener.cs" />
+ <Compile Include="InsightsManager.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Tango.Core\Tango.Core.csproj">
+ <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project>
+ <Name>Tango.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Tango.Integration\Tango.Integration.csproj">
+ <Project>{4206ac58-3b57-4699-8835-90bf6db01a61}</Project>
+ <Name>Tango.Integration</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Tango.PMR\Tango.PMR.csproj">
+ <Project>{e4927038-348d-4295-aaf4-861c58cb3943}</Project>
+ <Name>Tango.PMR</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Tango.Transport\Tango.Transport.csproj">
+ <Project>{74e700b0-1156-4126-be40-ee450d3c3026}</Project>
+ <Name>Tango.Transport</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <PackageReference Include="Google.Protobuf">
+ <Version>3.4.1</Version>
+ </PackageReference>
+ <PackageReference Include="LiteDB">
+ <Version>5.0.4</Version>
+ </PackageReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeReceiver.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeReceiver.cs
index 08c397f5f..00ff78c29 100644
--- a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeReceiver.cs
+++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeReceiver.cs
@@ -83,7 +83,14 @@ namespace Tango.Integration.ExternalBridge
public bool IsLoggedIn { get; private set; }
public ExternalBridgeLoginIntent LoginIntent { get; private set; }
- public String UserName { get; set; }
+ public String UserName { get; private set; }
+
+ private ExternalBridgeLoginRequest _loginInfo;
+ public ExternalBridgeLoginRequest LoginInfo
+ {
+ get { return _loginInfo; }
+ set { _loginInfo = value; RaisePropertyChangedAuto(); }
+ }
public bool IsLoggedInAndRequiresDiagnostics
{
@@ -294,6 +301,7 @@ namespace Tango.Integration.ExternalBridge
IsLoggedIn = true;
LoginIntent = request.Message.Intent;
UserName = request.Message.UserName;
+ LoginInfo = request.Message;
var response = new ExternalBridgeLoginResponse();
response.Authenticated = true;
@@ -615,7 +623,7 @@ namespace Tango.Integration.ExternalBridge
{
var cloned = container.Clone();
cloned.Token = _applicationLogsToken;
- SendResponse(cloned);
+ SendResponse(cloned, new TransportResponseConfig() { Priority = QueuePriority.Low });
}
}
catch (Exception ex)
diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeService.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeService.cs
index 1cc4f6e2a..e1d23685a 100644
--- a/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeService.cs
+++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/ExternalBridgeService.cs
@@ -29,6 +29,7 @@ using Tango.Core.Threading;
using System.Diagnostics;
using System.Reflection;
using Newtonsoft.Json;
+using System.Collections.ObjectModel;
namespace Tango.Integration.ExternalBridge
{
@@ -80,6 +81,17 @@ namespace Tango.Integration.ExternalBridge
public static HashSet<MessageType> SafetyLevelOperations { get; private set; }
/// <summary>
+ /// Gets the collection of logged-in receivers.
+ /// </summary>
+ public List<ExternalBridgeReceiver> ActiveReceivers
+ {
+ get
+ {
+ return _receivers.Where(x => x.IsLoggedIn).ToList();
+ }
+ }
+
+ /// <summary>
/// Gets or sets the TCP transport adapter write mode when creating a TCP receiver.
/// </summary>
public TcpTransportAdapterWriteMode TcpTransportAdapterWriteMode { get; set; }
@@ -268,6 +280,7 @@ namespace Tango.Integration.ExternalBridge
receiver.ReceiverRequestReceived += Receiver_ReceiverRequestReceived;
_receivers.Add(receiver);
await receiver.Connect();
+ RaisePropertyChanged(nameof(ActiveReceivers));
}
private async void OnSignalRSessionCreated(String sessionID)
@@ -285,6 +298,7 @@ namespace Tango.Integration.ExternalBridge
receiver.ReceiverRequestReceived += Receiver_ReceiverRequestReceived;
_receivers.Add(receiver);
await receiver.Connect();
+ RaisePropertyChanged(nameof(ActiveReceivers));
}
catch (Exception ex)
{
@@ -359,6 +373,8 @@ namespace Tango.Integration.ExternalBridge
}
catch { } //Ignore exceptions on handler.
}
+
+ RaisePropertyChanged(nameof(ActiveReceivers));
}
private void Receiver_ColorProfileRequest(object sender, ColorProfileRequestEventArgs e)
@@ -394,6 +410,8 @@ namespace Tango.Integration.ExternalBridge
{
FullControlSessionReceiver = sender as ExternalBridgeReceiver;
}
+
+ RaisePropertyChanged(nameof(ActiveReceivers));
}, (reason) =>
{
//Declined
diff --git a/Software/Visual_Studio/Tango.Integration/ExternalBridge/IExternalBridgeService.cs b/Software/Visual_Studio/Tango.Integration/ExternalBridge/IExternalBridgeService.cs
index e2d7bea30..c7d2c8d5c 100644
--- a/Software/Visual_Studio/Tango.Integration/ExternalBridge/IExternalBridgeService.cs
+++ b/Software/Visual_Studio/Tango.Integration/ExternalBridge/IExternalBridgeService.cs
@@ -1,6 +1,7 @@
using Google.Protobuf;
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -16,6 +17,11 @@ namespace Tango.Integration.ExternalBridge
public interface IExternalBridgeService
{
/// <summary>
+ /// Gets the collection of logged-in receivers.
+ /// </summary>
+ List<ExternalBridgeReceiver> ActiveReceivers { get; }
+
+ /// <summary>
/// Occurs when a new client is waiting for authentication.
/// </summary>
event EventHandler<ExternalBridgeClientConnectedEventArgs> ConnectionRequest;
diff --git a/Software/Visual_Studio/Tango.Logging/GlobalExceptionTrapper.cs b/Software/Visual_Studio/Tango.Logging/GlobalExceptionTrapper.cs
index b5acb4b88..8bc3729f2 100644
--- a/Software/Visual_Studio/Tango.Logging/GlobalExceptionTrapper.cs
+++ b/Software/Visual_Studio/Tango.Logging/GlobalExceptionTrapper.cs
@@ -1,8 +1,12 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
using System.Linq;
+using System.Reflection;
using System.Runtime.ExceptionServices;
using System.Text;
+using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
@@ -90,19 +94,53 @@ namespace Tango.Logging
}
_lastGlobalExceptionTime = DateTime.Now;
- LogManager.Default.Log("Application Crashed", LogCategory.Critical);
- LogManager.Default.Log(exception, LogCategory.Critical);
ApplicationCrashedEventArgs e = new ApplicationCrashedEventArgs(exception);
ApplicationCrashed?.Invoke(this, e);
- if (e.TryRecover)
+ return e.TryRecover;
+ }
+
+ public Task<MessageLogItem> GetLastApplicationCrashEventLog(int maxMinutes = 10)
+ {
+ return Task.Factory.StartNew<MessageLogItem>(() =>
{
- LogManager.Default.Log("Trying application recovery. Ignoring exception...");
- }
+ MessageLogItem logItem = null;
- return e.TryRecover;
+ try
+ {
+ var applicationEvents = new EventLog("Application");
+ var events = applicationEvents.Entries.Cast<EventLogEntry>().Where(x => x.EntryType == EventLogEntryType.Error && x.Source == ".NET Runtime" && x.TimeWritten > DateTime.Now.AddMinutes(-maxMinutes)).OrderByDescending(x => x.TimeWritten).ToList();
+
+ Regex reg = new Regex("Application: (.+)");
+
+ foreach (var ev in events)
+ {
+ Match match = reg.Match(ev.Message);
+ if (match.Groups.Count > 1)
+ {
+ String exeName = match.Groups[1].Value;
+ String assemblyName = Path.GetFileNameWithoutExtension(exeName);
+
+ if (assemblyName == Assembly.GetEntryAssembly().GetName().Name)
+ {
+ logItem = new MessageLogItem();
+ logItem.Message = "Application terminated unexpectedly in the previous run!\n";
+ logItem.Message += "This crash report was retrieved from the windows event logs.\n";
+ logItem.Message += "---------------------------------------------------------------------------\n\n";
+ logItem.Message += ev.Message;
+ logItem.TimeStamp = DateTime.Now;
+ logItem.Category = LogCategory.Critical;
+ break;
+ }
+ }
+ }
+ }
+ catch { }
+
+ return logItem;
+ });
}
}
}
diff --git a/Software/Visual_Studio/Tango.Logging/LogManager.cs b/Software/Visual_Studio/Tango.Logging/LogManager.cs
index 55264164a..4148fa342 100644
--- a/Software/Visual_Studio/Tango.Logging/LogManager.cs
+++ b/Software/Visual_Studio/Tango.Logging/LogManager.cs
@@ -259,5 +259,14 @@ namespace Tango.Logging
NewLog?.Invoke(this, log);
}
}
+
+ /// <summary>
+ /// Creates a new log safe which can be used to keep logs and then be disposed.
+ /// </summary>
+ /// <returns></returns>
+ public LogSafe CreateLogSafe()
+ {
+ return new LogSafe(this);
+ }
}
}
diff --git a/Software/Visual_Studio/Tango.Logging/LogSafe.cs b/Software/Visual_Studio/Tango.Logging/LogSafe.cs
new file mode 100644
index 000000000..2da51e90c
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Logging/LogSafe.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.Logging
+{
+ public class LogSafe : IDisposable
+ {
+ private LogManager _logManager;
+ private List<LogItemBase> Logs { get; set; }
+
+ public LogSafe(LogManager logManager)
+ {
+ _logManager = logManager;
+ Logs = new List<LogItemBase>();
+ logManager.NewLog += LogManager_NewLog;
+ }
+
+ private void LogManager_NewLog(object sender, LogItemBase log)
+ {
+ Logs.Add(log);
+ }
+
+ public List<LogItemBase> EmptyAndDispose()
+ {
+ var list = Logs.ToList();
+ Dispose();
+ return list;
+ }
+
+ public void Dispose()
+ {
+ _logManager.NewLog -= LogManager_NewLog;
+ Logs.Clear();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Logging/Tango.Logging.csproj b/Software/Visual_Studio/Tango.Logging/Tango.Logging.csproj
index e2e2b1edd..d9a2e1139 100644
--- a/Software/Visual_Studio/Tango.Logging/Tango.Logging.csproj
+++ b/Software/Visual_Studio/Tango.Logging/Tango.Logging.csproj
@@ -63,6 +63,7 @@
<Compile Include="LogCategory.cs" />
<Compile Include="LogItemBase.cs" />
<Compile Include="LogManager.cs" />
+ <Compile Include="LogSafe.cs" />
<Compile Include="MessageLogItem.cs" />
<Compile Include="ApplicationLogFileParser.cs" />
<Compile Include="ILogFileParser.cs" />
@@ -82,7 +83,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.PMR/Common/ErrorCode.cs b/Software/Visual_Studio/Tango.PMR/Common/ErrorCode.cs
index eeac2edba..057820787 100644
--- a/Software/Visual_Studio/Tango.PMR/Common/ErrorCode.cs
+++ b/Software/Visual_Studio/Tango.PMR/Common/ErrorCode.cs
@@ -22,7 +22,7 @@ namespace Tango.PMR.Common {
static ErrorCodeReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
- "Cg9FcnJvckNvZGUucHJvdG8SEFRhbmdvLlBNUi5Db21tb24q+gsKCUVycm9y",
+ "Cg9FcnJvckNvZGUucHJvdG8SEFRhbmdvLlBNUi5Db21tb24qsgwKCUVycm9y",
"Q29kZRIICgROT05FEAASEQoNR0VORVJBTF9FUlJPUhABEgsKB0JBRF9DUkMQ",
"AhIeChpJTlZBTElEX0RJR0lUQUxfUElOX05VTUJFUhADEhsKF1VOQVVUSE9S",
"SVpFRF9DT05ORUNUSU9OEAQSHwobQ09OVElOVU9VU19SRVNQT05TRV9BQk9S",
@@ -51,13 +51,14 @@ namespace Tango.PMR.Common {
"UkVTU1VSRV9BTEFSTRDaDxIWChFKT0JfQ1VSUkVOVF9BTEFSTRDbDxIUCg9K",
"T0JfTU9UT1JfQUxBUk0Q3A8SEgoNSk9CX0xJRFNfT1BFThDdDxIYChNKT0Jf",
"QUJPUlRFRF9CWV9VU0VSEN4PEhUKEEpPQl9TQUZFVFlfQUxBUk0Q3w8SFgoR",
- "Sk9CX05PX0FMQVJNX0ZJTEUQ4A8SGQoUUE9XRVJfVVBfTk9fQ0ZHX0ZJTEUQ",
- "uBcSHgoZUE9XRVJfVVBfSFdfQ09ORklHX0ZBSUxFRBC5FxIdChhQT1dFUl9V",
- "UF9CVUlMVF9JTl9GQUlMRUQQuhcSIwoeUE9XRVJfVVBfSU5JVElBTF9CTE9X",
- "RVJfRkFJTEVEELsXEi8KKlBPV0VSX1VQX0RJU1BFTlNFUl9QUkVTU1VSRV9C",
- "VUlMRFVQX0ZBSUxFRBC8FxIgChtQT1dFUl9VUF9OT19USFJFQURfREVURUNU",
- "RUQQvRcSHwoaUE9XRVJfVVBfTk9fUFJPQ0VTU19QQVJBTVMQvhdCHAoaY29t",
- "LnR3aW5lLnRhbmdvLnBtci5jb21tb25iBnByb3RvMw=="));
+ "Sk9CX05PX0FMQVJNX0ZJTEUQ4A8SFQoQSk9CX0ZJTEVfUFJPQkxFTRDhDxIf",
+ "ChpKT0JfV0FTVEVfSEFORExJTkdfUFJPQkxFTRDiDxIZChRQT1dFUl9VUF9O",
+ "T19DRkdfRklMRRC4FxIeChlQT1dFUl9VUF9IV19DT05GSUdfRkFJTEVEELkX",
+ "Eh0KGFBPV0VSX1VQX0JVSUxUX0lOX0ZBSUxFRBC6FxIjCh5QT1dFUl9VUF9J",
+ "TklUSUFMX0JMT1dFUl9GQUlMRUQQuxcSLwoqUE9XRVJfVVBfRElTUEVOU0VS",
+ "X1BSRVNTVVJFX0JVSUxEVVBfRkFJTEVEELwXEiAKG1BPV0VSX1VQX05PX1RI",
+ "UkVBRF9ERVRFQ1RFRBC9FxIfChpQT1dFUl9VUF9OT19QUk9DRVNTX1BBUkFN",
+ "UxC+F0IcChpjb20udHdpbmUudGFuZ28ucG1yLmNvbW1vbmIGcHJvdG8z"));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Tango.PMR.Common.ErrorCode), }, null));
@@ -145,6 +146,8 @@ namespace Tango.PMR.Common {
[pbr::OriginalName("JOB_ABORTED_BY_USER")] JobAbortedByUser = 2014,
[pbr::OriginalName("JOB_SAFETY_ALARM")] JobSafetyAlarm = 2015,
[pbr::OriginalName("JOB_NO_ALARM_FILE")] JobNoAlarmFile = 2016,
+ [pbr::OriginalName("JOB_FILE_PROBLEM")] JobFileProblem = 2017,
+ [pbr::OriginalName("JOB_WASTE_HANDLING_PROBLEM")] JobWasteHandlingProblem = 2018,
/// <summary>
///power up
/// </summary>
diff --git a/Software/Visual_Studio/Tango.PMR/Insights/InsightsMonitors.cs b/Software/Visual_Studio/Tango.PMR/Insights/InsightsMonitors.cs
new file mode 100644
index 000000000..e5faefcc4
--- /dev/null
+++ b/Software/Visual_Studio/Tango.PMR/Insights/InsightsMonitors.cs
@@ -0,0 +1,2936 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: InsightsMonitors.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Tango.PMR.Insights {
+
+ /// <summary>Holder for reflection information generated from InsightsMonitors.proto</summary>
+ public static partial class InsightsMonitorsReflection {
+
+ #region Descriptor
+ /// <summary>File descriptor for InsightsMonitors.proto</summary>
+ public static pbr::FileDescriptor Descriptor {
+ get { return descriptor; }
+ }
+ private static pbr::FileDescriptor descriptor;
+
+ static InsightsMonitorsReflection() {
+ byte[] descriptorData = global::System.Convert.FromBase64String(
+ string.Concat(
+ "ChZJbnNpZ2h0c01vbml0b3JzLnByb3RvEhJUYW5nby5QTVIuSW5zaWdodHMi",
+ "lRQKEEluc2lnaHRzTW9uaXRvcnMSFAoMRGFuY2VyMUFuZ2xlGAEgASgBEhQK",
+ "DERhbmNlcjJBbmdsZRgCIAEoARIUCgxEYW5jZXIzQW5nbGUYAyABKAESHAoU",
+ "RmVlZGVyTW90b3JGcmVxdWVuY3kYBCABKAESEgoKRHJ5ZXJNb3RvchgFIAEo",
+ "ARITCgtQb2xsZXJNb3RvchgGIAEoARITCgtXaW5kZXJNb3RvchgHIAEoARIS",
+ "CgpTY3Jld01vdG9yGAggASgBEhMKC1RocmVhZFNwZWVkGAkgASgBEhgKEE1p",
+ "eGVyVGVtcGVyYXR1cmUYCiABKAESHAoUSGVhZFpvbmUxVGVtcGVyYXR1cmUY",
+ "CyABKAESHAoUSGVhZFpvbmUyVGVtcGVyYXR1cmUYDCABKAESHAoUSGVhZFpv",
+ "bmUzVGVtcGVyYXR1cmUYDSABKAESEwoLSGVhZEFpckZsb3cYDiABKAESFQoN",
+ "RmVlZGVyVGVuc2lvbhgPIAEoARIVCg1QdWxsZXJUZW5zaW9uGBAgASgBEh0K",
+ "FURyeWVyWm9uZTFUZW1wZXJhdHVyZRgRIAEoARIdChVEcnllclpvbmUyVGVt",
+ "cGVyYXR1cmUYEiABKAESHQoVRHJ5ZXJab25lM1RlbXBlcmF0dXJlGBMgASgB",
+ "EhQKDERyeWVyQWlyRmxvdxgUIAEoARIVCg1XaW5kZXJUZW5zaW9uGBUgASgB",
+ "EiEKGURpc3BlbnNlcnNNb3RvcnNGcmVxdWVuY3kYFiADKAESIQoZRGlzcGVu",
+ "c2Vyc0FuZ3VsYXJFbmNvZGVycxgXIAMoARIhChlEaXNwZW5zZXJzTGluZWFy",
+ "UG9zaXRpb25zGBggAygBEhoKEkRpc3BlbnNlcnNQcmVzc3VyZRgZIAMoARIb",
+ "ChNGaWx0ZXJEZWx0YVByZXNzdXJlGBogASgBEhoKEkNoaWxsZXJUZW1wZXJh",
+ "dHVyZRgbIAEoARIgChhEaXNwZW5zZXIxTW90b3JGcmVxdWVuY3kYHCABKAES",
+ "IAoYRGlzcGVuc2VyMk1vdG9yRnJlcXVlbmN5GB0gASgBEiAKGERpc3BlbnNl",
+ "cjNNb3RvckZyZXF1ZW5jeRgeIAEoARIgChhEaXNwZW5zZXI0TW90b3JGcmVx",
+ "dWVuY3kYHyABKAESIAoYRGlzcGVuc2VyNU1vdG9yRnJlcXVlbmN5GCAgASgB",
+ "EiAKGERpc3BlbnNlcjZNb3RvckZyZXF1ZW5jeRghIAEoARIgChhEaXNwZW5z",
+ "ZXI3TW90b3JGcmVxdWVuY3kYIiABKAESIAoYRGlzcGVuc2VyOE1vdG9yRnJl",
+ "cXVlbmN5GCMgASgBEhwKFEhlYWRab25lNFRlbXBlcmF0dXJlGCQgASgBEhwK",
+ "FEhlYWRab25lNVRlbXBlcmF0dXJlGCUgASgBEhwKFEhlYWRab25lNlRlbXBl",
+ "cmF0dXJlGCYgASgBEhUKDUJsb3dlclZvbHRhZ2UYJyABKAESGgoSRGlzcGVu",
+ "c2VyMVByZXNzdXJlGCggASgBEhoKEkRpc3BlbnNlcjJQcmVzc3VyZRgpIAEo",
+ "ARIaChJEaXNwZW5zZXIzUHJlc3N1cmUYKiABKAESGgoSRGlzcGVuc2VyNFBy",
+ "ZXNzdXJlGCsgASgBEhoKEkRpc3BlbnNlcjVQcmVzc3VyZRgsIAEoARIaChJE",
+ "aXNwZW5zZXI2UHJlc3N1cmUYLSABKAESGgoSRGlzcGVuc2VyN1ByZXNzdXJl",
+ "GC4gASgBEhoKEkRpc3BlbnNlcjhQcmVzc3VyZRgvIAEoARIVCg1NaWRUYW5r",
+ "MUxldmVsGDAgASgBEhUKDU1pZFRhbmsyTGV2ZWwYMSABKAESFQoNTWlkVGFu",
+ "azNMZXZlbBgyIAEoARIVCg1NaWRUYW5rNExldmVsGDMgASgBEhUKDU1pZFRh",
+ "bms1TGV2ZWwYNCABKAESFQoNTWlkVGFuazZMZXZlbBg1IAEoARIVCg1NaWRU",
+ "YW5rN0xldmVsGDYgASgBEhUKDU1pZFRhbms4TGV2ZWwYNyABKAESHwoXRHJp",
+ "ZXJab25lMUhlYXRlckN1cnJlbnQYOCABKAESHwoXRHJpZXJab25lMkhlYXRl",
+ "ckN1cnJlbnQYOSABKAESHgoWSGVhZFpvbmUxSGVhdGVyQ3VycmVudBg6IAEo",
+ "ARIeChZIZWFkWm9uZTJIZWF0ZXJDdXJyZW50GDsgASgBEh4KFkhlYWRab25l",
+ "M0hlYXRlckN1cnJlbnQYPCABKAESHgoWSGVhZFpvbmU0SGVhdGVyQ3VycmVu",
+ "dBg9IAEoARIgChhIZWFkWm9uZTVfNkhlYXRlckN1cnJlbnQYPiABKAESGwoT",
+ "TWl4ZXIxSGVhdGVyQ3VycmVudBg/IAEoARIaChJEaXNwZW5zZXJzSW5rTGV2",
+ "ZWwYQCADKAESGAoQTWlkVGFua3NJbmtMZXZlbBhBIAMoARIaChJPdmVyYWxs",
+ "VGVtcGVyYXR1cmUYQiABKAESHgoWSGVhZFpvbmU3SGVhdGVyQ3VycmVudBhD",
+ "IAEoARIcChRIZWFkWm9uZTdUZW1wZXJhdHVyZRhEIAEoARIeChZIZWFkWm9u",
+ "ZThIZWF0ZXJDdXJyZW50GEUgASgBEhwKFEhlYWRab25lOFRlbXBlcmF0dXJl",
+ "GEYgASgBEh4KFkhlYWRab25lOUhlYXRlckN1cnJlbnQYRyABKAESHAoUSGVh",
+ "ZFpvbmU5VGVtcGVyYXR1cmUYSCABKAESHwoXSGVhZFpvbmUxMEhlYXRlckN1",
+ "cnJlbnQYSSABKAESHQoVSGVhZFpvbmUxMFRlbXBlcmF0dXJlGEogASgBEh8K",
+ "F0hlYWRab25lMTFIZWF0ZXJDdXJyZW50GEsgASgBEh0KFUhlYWRab25lMTFU",
+ "ZW1wZXJhdHVyZRhMIAEoARIfChdIZWFkWm9uZTEySGVhdGVyQ3VycmVudBhN",
+ "IAEoARIdChVIZWFkWm9uZTEyVGVtcGVyYXR1cmUYTiABKAESGgoSSGVhZEJs",
+ "b3dlclZvbHRhZ2UxGE8gASgBEhoKEkhlYWRCbG93ZXJWb2x0YWdlMhhQIAEo",
+ "ARIfChdIZWFkQ292ZXJIZWF0ZXIxQ3VycmVudBhRIAEoARIjChtIZWFkQ292",
+ "ZXJIZWF0ZXIxVGVtcGVyYXR1cmUYUiABKAESHwoXSGVhZENvdmVySGVhdGVy",
+ "MkN1cnJlbnQYUyABKAESIwobSGVhZENvdmVySGVhdGVyMlRlbXBlcmF0dXJl",
+ "GFQgASgBEhkKEVdIU0Jsb3dlcjJWb2x0YWdlGFUgASgBEhEKCUdhc1NlbnNv",
+ "chhWIAEoARIXCg9JbmNvbWluZ1ZvbHRhZ2UYVyABKAESEgoKV2FzdGVMZXZl",
+ "bBhYIAEoARIaChJIZWFkQmxvd2VyMUFpckZsb3cYWSABKAESGgoSSGVhZEJs",
+ "b3dlcjJBaXJGbG93GFogASgBQh4KHGNvbS50d2luZS50YW5nby5wbXIuaW5z",
+ "aWdodHNiBnByb3RvMw=="));
+ descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+ new pbr::FileDescriptor[] { },
+ new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+ new pbr::GeneratedClrTypeInfo(typeof(global::Tango.PMR.Insights.InsightsMonitors), global::Tango.PMR.Insights.InsightsMonitors.Parser, new[]{ "Dancer1Angle", "Dancer2Angle", "Dancer3Angle", "FeederMotorFrequency", "DryerMotor", "PollerMotor", "WinderMotor", "ScrewMotor", "ThreadSpeed", "MixerTemperature", "HeadZone1Temperature", "HeadZone2Temperature", "HeadZone3Temperature", "HeadAirFlow", "FeederTension", "PullerTension", "DryerZone1Temperature", "DryerZone2Temperature", "DryerZone3Temperature", "DryerAirFlow", "WinderTension", "DispensersMotorsFrequency", "DispensersAngularEncoders", "DispensersLinearPositions", "DispensersPressure", "FilterDeltaPressure", "ChillerTemperature", "Dispenser1MotorFrequency", "Dispenser2MotorFrequency", "Dispenser3MotorFrequency", "Dispenser4MotorFrequency", "Dispenser5MotorFrequency", "Dispenser6MotorFrequency", "Dispenser7MotorFrequency", "Dispenser8MotorFrequency", "HeadZone4Temperature", "HeadZone5Temperature", "HeadZone6Temperature", "BlowerVoltage", "Dispenser1Pressure", "Dispenser2Pressure", "Dispenser3Pressure", "Dispenser4Pressure", "Dispenser5Pressure", "Dispenser6Pressure", "Dispenser7Pressure", "Dispenser8Pressure", "MidTank1Level", "MidTank2Level", "MidTank3Level", "MidTank4Level", "MidTank5Level", "MidTank6Level", "MidTank7Level", "MidTank8Level", "DrierZone1HeaterCurrent", "DrierZone2HeaterCurrent", "HeadZone1HeaterCurrent", "HeadZone2HeaterCurrent", "HeadZone3HeaterCurrent", "HeadZone4HeaterCurrent", "HeadZone56HeaterCurrent", "Mixer1HeaterCurrent", "DispensersInkLevel", "MidTanksInkLevel", "OverallTemperature", "HeadZone7HeaterCurrent", "HeadZone7Temperature", "HeadZone8HeaterCurrent", "HeadZone8Temperature", "HeadZone9HeaterCurrent", "HeadZone9Temperature", "HeadZone10HeaterCurrent", "HeadZone10Temperature", "HeadZone11HeaterCurrent", "HeadZone11Temperature", "HeadZone12HeaterCurrent", "HeadZone12Temperature", "HeadBlowerVoltage1", "HeadBlowerVoltage2", "HeadCoverHeater1Current", "HeadCoverHeater1Temperature", "HeadCoverHeater2Current", "HeadCoverHeater2Temperature", "WHSBlower2Voltage", "GasSensor", "IncomingVoltage", "WasteLevel", "HeadBlower1AirFlow", "HeadBlower2AirFlow" }, null, null, null)
+ }));
+ }
+ #endregion
+
+ }
+ #region Messages
+ public sealed partial class InsightsMonitors : pb::IMessage<InsightsMonitors> {
+ private static readonly pb::MessageParser<InsightsMonitors> _parser = new pb::MessageParser<InsightsMonitors>(() => new InsightsMonitors());
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static pb::MessageParser<InsightsMonitors> Parser { get { return _parser; } }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Tango.PMR.Insights.InsightsMonitorsReflection.Descriptor.MessageTypes[0]; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public InsightsMonitors() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public InsightsMonitors(InsightsMonitors other) : this() {
+ dancer1Angle_ = other.dancer1Angle_;
+ dancer2Angle_ = other.dancer2Angle_;
+ dancer3Angle_ = other.dancer3Angle_;
+ feederMotorFrequency_ = other.feederMotorFrequency_;
+ dryerMotor_ = other.dryerMotor_;
+ pollerMotor_ = other.pollerMotor_;
+ winderMotor_ = other.winderMotor_;
+ screwMotor_ = other.screwMotor_;
+ threadSpeed_ = other.threadSpeed_;
+ mixerTemperature_ = other.mixerTemperature_;
+ headZone1Temperature_ = other.headZone1Temperature_;
+ headZone2Temperature_ = other.headZone2Temperature_;
+ headZone3Temperature_ = other.headZone3Temperature_;
+ headAirFlow_ = other.headAirFlow_;
+ feederTension_ = other.feederTension_;
+ pullerTension_ = other.pullerTension_;
+ dryerZone1Temperature_ = other.dryerZone1Temperature_;
+ dryerZone2Temperature_ = other.dryerZone2Temperature_;
+ dryerZone3Temperature_ = other.dryerZone3Temperature_;
+ dryerAirFlow_ = other.dryerAirFlow_;
+ winderTension_ = other.winderTension_;
+ dispensersMotorsFrequency_ = other.dispensersMotorsFrequency_.Clone();
+ dispensersAngularEncoders_ = other.dispensersAngularEncoders_.Clone();
+ dispensersLinearPositions_ = other.dispensersLinearPositions_.Clone();
+ dispensersPressure_ = other.dispensersPressure_.Clone();
+ filterDeltaPressure_ = other.filterDeltaPressure_;
+ chillerTemperature_ = other.chillerTemperature_;
+ dispenser1MotorFrequency_ = other.dispenser1MotorFrequency_;
+ dispenser2MotorFrequency_ = other.dispenser2MotorFrequency_;
+ dispenser3MotorFrequency_ = other.dispenser3MotorFrequency_;
+ dispenser4MotorFrequency_ = other.dispenser4MotorFrequency_;
+ dispenser5MotorFrequency_ = other.dispenser5MotorFrequency_;
+ dispenser6MotorFrequency_ = other.dispenser6MotorFrequency_;
+ dispenser7MotorFrequency_ = other.dispenser7MotorFrequency_;
+ dispenser8MotorFrequency_ = other.dispenser8MotorFrequency_;
+ headZone4Temperature_ = other.headZone4Temperature_;
+ headZone5Temperature_ = other.headZone5Temperature_;
+ headZone6Temperature_ = other.headZone6Temperature_;
+ blowerVoltage_ = other.blowerVoltage_;
+ dispenser1Pressure_ = other.dispenser1Pressure_;
+ dispenser2Pressure_ = other.dispenser2Pressure_;
+ dispenser3Pressure_ = other.dispenser3Pressure_;
+ dispenser4Pressure_ = other.dispenser4Pressure_;
+ dispenser5Pressure_ = other.dispenser5Pressure_;
+ dispenser6Pressure_ = other.dispenser6Pressure_;
+ dispenser7Pressure_ = other.dispenser7Pressure_;
+ dispenser8Pressure_ = other.dispenser8Pressure_;
+ midTank1Level_ = other.midTank1Level_;
+ midTank2Level_ = other.midTank2Level_;
+ midTank3Level_ = other.midTank3Level_;
+ midTank4Level_ = other.midTank4Level_;
+ midTank5Level_ = other.midTank5Level_;
+ midTank6Level_ = other.midTank6Level_;
+ midTank7Level_ = other.midTank7Level_;
+ midTank8Level_ = other.midTank8Level_;
+ drierZone1HeaterCurrent_ = other.drierZone1HeaterCurrent_;
+ drierZone2HeaterCurrent_ = other.drierZone2HeaterCurrent_;
+ headZone1HeaterCurrent_ = other.headZone1HeaterCurrent_;
+ headZone2HeaterCurrent_ = other.headZone2HeaterCurrent_;
+ headZone3HeaterCurrent_ = other.headZone3HeaterCurrent_;
+ headZone4HeaterCurrent_ = other.headZone4HeaterCurrent_;
+ headZone56HeaterCurrent_ = other.headZone56HeaterCurrent_;
+ mixer1HeaterCurrent_ = other.mixer1HeaterCurrent_;
+ dispensersInkLevel_ = other.dispensersInkLevel_.Clone();
+ midTanksInkLevel_ = other.midTanksInkLevel_.Clone();
+ overallTemperature_ = other.overallTemperature_;
+ headZone7HeaterCurrent_ = other.headZone7HeaterCurrent_;
+ headZone7Temperature_ = other.headZone7Temperature_;
+ headZone8HeaterCurrent_ = other.headZone8HeaterCurrent_;
+ headZone8Temperature_ = other.headZone8Temperature_;
+ headZone9HeaterCurrent_ = other.headZone9HeaterCurrent_;
+ headZone9Temperature_ = other.headZone9Temperature_;
+ headZone10HeaterCurrent_ = other.headZone10HeaterCurrent_;
+ headZone10Temperature_ = other.headZone10Temperature_;
+ headZone11HeaterCurrent_ = other.headZone11HeaterCurrent_;
+ headZone11Temperature_ = other.headZone11Temperature_;
+ headZone12HeaterCurrent_ = other.headZone12HeaterCurrent_;
+ headZone12Temperature_ = other.headZone12Temperature_;
+ headBlowerVoltage1_ = other.headBlowerVoltage1_;
+ headBlowerVoltage2_ = other.headBlowerVoltage2_;
+ headCoverHeater1Current_ = other.headCoverHeater1Current_;
+ headCoverHeater1Temperature_ = other.headCoverHeater1Temperature_;
+ headCoverHeater2Current_ = other.headCoverHeater2Current_;
+ headCoverHeater2Temperature_ = other.headCoverHeater2Temperature_;
+ wHSBlower2Voltage_ = other.wHSBlower2Voltage_;
+ gasSensor_ = other.gasSensor_;
+ incomingVoltage_ = other.incomingVoltage_;
+ wasteLevel_ = other.wasteLevel_;
+ headBlower1AirFlow_ = other.headBlower1AirFlow_;
+ headBlower2AirFlow_ = other.headBlower2AirFlow_;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public InsightsMonitors Clone() {
+ return new InsightsMonitors(this);
+ }
+
+ /// <summary>Field number for the "Dancer1Angle" field.</summary>
+ public const int Dancer1AngleFieldNumber = 1;
+ private double dancer1Angle_;
+ /// <summary>
+ ///Left Dancer
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double Dancer1Angle {
+ get { return dancer1Angle_; }
+ set {
+ dancer1Angle_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "Dancer2Angle" field.</summary>
+ public const int Dancer2AngleFieldNumber = 2;
+ private double dancer2Angle_;
+ /// <summary>
+ ///Middle Dancer
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double Dancer2Angle {
+ get { return dancer2Angle_; }
+ set {
+ dancer2Angle_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "Dancer3Angle" field.</summary>
+ public const int Dancer3AngleFieldNumber = 3;
+ private double dancer3Angle_;
+ /// <summary>
+ ///Right Dancer
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double Dancer3Angle {
+ get { return dancer3Angle_; }
+ set {
+ dancer3Angle_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "FeederMotorFrequency" field.</summary>
+ public const int FeederMotorFrequencyFieldNumber = 4;
+ private double feederMotorFrequency_;
+ /// <summary>
+ ///Feeder Motor
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double FeederMotorFrequency {
+ get { return feederMotorFrequency_; }
+ set {
+ feederMotorFrequency_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "DryerMotor" field.</summary>
+ public const int DryerMotorFieldNumber = 5;
+ private double dryerMotor_;
+ /// <summary>
+ ///Dryer Motor
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double DryerMotor {
+ get { return dryerMotor_; }
+ set {
+ dryerMotor_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "PollerMotor" field.</summary>
+ public const int PollerMotorFieldNumber = 6;
+ private double pollerMotor_;
+ /// <summary>
+ ///Poller Motor
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double PollerMotor {
+ get { return pollerMotor_; }
+ set {
+ pollerMotor_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "WinderMotor" field.</summary>
+ public const int WinderMotorFieldNumber = 7;
+ private double winderMotor_;
+ /// <summary>
+ ///Winder Motor
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double WinderMotor {
+ get { return winderMotor_; }
+ set {
+ winderMotor_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "ScrewMotor" field.</summary>
+ public const int ScrewMotorFieldNumber = 8;
+ private double screwMotor_;
+ /// <summary>
+ ///Screw Motor
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double ScrewMotor {
+ get { return screwMotor_; }
+ set {
+ screwMotor_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "ThreadSpeed" field.</summary>
+ public const int ThreadSpeedFieldNumber = 9;
+ private double threadSpeed_;
+ /// <summary>
+ ///Thread Speed
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double ThreadSpeed {
+ get { return threadSpeed_; }
+ set {
+ threadSpeed_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "MixerTemperature" field.</summary>
+ public const int MixerTemperatureFieldNumber = 10;
+ private double mixerTemperature_;
+ /// <summary>
+ ///Mixer
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double MixerTemperature {
+ get { return mixerTemperature_; }
+ set {
+ mixerTemperature_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone1Temperature" field.</summary>
+ public const int HeadZone1TemperatureFieldNumber = 11;
+ private double headZone1Temperature_;
+ /// <summary>
+ ///Head Zone 1
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone1Temperature {
+ get { return headZone1Temperature_; }
+ set {
+ headZone1Temperature_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone2Temperature" field.</summary>
+ public const int HeadZone2TemperatureFieldNumber = 12;
+ private double headZone2Temperature_;
+ /// <summary>
+ ///Head Zone 2
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone2Temperature {
+ get { return headZone2Temperature_; }
+ set {
+ headZone2Temperature_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone3Temperature" field.</summary>
+ public const int HeadZone3TemperatureFieldNumber = 13;
+ private double headZone3Temperature_;
+ /// <summary>
+ ///Head Zone 3
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone3Temperature {
+ get { return headZone3Temperature_; }
+ set {
+ headZone3Temperature_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadAirFlow" field.</summary>
+ public const int HeadAirFlowFieldNumber = 14;
+ private double headAirFlow_;
+ /// <summary>
+ ///Head Air Flow
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadAirFlow {
+ get { return headAirFlow_; }
+ set {
+ headAirFlow_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "FeederTension" field.</summary>
+ public const int FeederTensionFieldNumber = 15;
+ private double feederTension_;
+ /// <summary>
+ ///Feeder Tension
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double FeederTension {
+ get { return feederTension_; }
+ set {
+ feederTension_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "PullerTension" field.</summary>
+ public const int PullerTensionFieldNumber = 16;
+ private double pullerTension_;
+ /// <summary>
+ ///Puller Tension
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double PullerTension {
+ get { return pullerTension_; }
+ set {
+ pullerTension_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "DryerZone1Temperature" field.</summary>
+ public const int DryerZone1TemperatureFieldNumber = 17;
+ private double dryerZone1Temperature_;
+ /// <summary>
+ ///Dryer Zone 1
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double DryerZone1Temperature {
+ get { return dryerZone1Temperature_; }
+ set {
+ dryerZone1Temperature_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "DryerZone2Temperature" field.</summary>
+ public const int DryerZone2TemperatureFieldNumber = 18;
+ private double dryerZone2Temperature_;
+ /// <summary>
+ ///Dryer Zone 2
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double DryerZone2Temperature {
+ get { return dryerZone2Temperature_; }
+ set {
+ dryerZone2Temperature_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "DryerZone3Temperature" field.</summary>
+ public const int DryerZone3TemperatureFieldNumber = 19;
+ private double dryerZone3Temperature_;
+ /// <summary>
+ ///Dryer Zone 3
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double DryerZone3Temperature {
+ get { return dryerZone3Temperature_; }
+ set {
+ dryerZone3Temperature_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "DryerAirFlow" field.</summary>
+ public const int DryerAirFlowFieldNumber = 20;
+ private double dryerAirFlow_;
+ /// <summary>
+ ///Dryer Air Flow
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double DryerAirFlow {
+ get { return dryerAirFlow_; }
+ set {
+ dryerAirFlow_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "WinderTension" field.</summary>
+ public const int WinderTensionFieldNumber = 21;
+ private double winderTension_;
+ /// <summary>
+ ///Winder Tension
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double WinderTension {
+ get { return winderTension_; }
+ set {
+ winderTension_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "DispensersMotorsFrequency" field.</summary>
+ public const int DispensersMotorsFrequencyFieldNumber = 22;
+ private static readonly pb::FieldCodec<double> _repeated_dispensersMotorsFrequency_codec
+ = pb::FieldCodec.ForDouble(178);
+ private readonly pbc::RepeatedField<double> dispensersMotorsFrequency_ = new pbc::RepeatedField<double>();
+ /// <summary>
+ ///Dispensers Motors
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public pbc::RepeatedField<double> DispensersMotorsFrequency {
+ get { return dispensersMotorsFrequency_; }
+ }
+
+ /// <summary>Field number for the "DispensersAngularEncoders" field.</summary>
+ public const int DispensersAngularEncodersFieldNumber = 23;
+ private static readonly pb::FieldCodec<double> _repeated_dispensersAngularEncoders_codec
+ = pb::FieldCodec.ForDouble(186);
+ private readonly pbc::RepeatedField<double> dispensersAngularEncoders_ = new pbc::RepeatedField<double>();
+ /// <summary>
+ ///Dispensers Angular Encoders
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public pbc::RepeatedField<double> DispensersAngularEncoders {
+ get { return dispensersAngularEncoders_; }
+ }
+
+ /// <summary>Field number for the "DispensersLinearPositions" field.</summary>
+ public const int DispensersLinearPositionsFieldNumber = 24;
+ private static readonly pb::FieldCodec<double> _repeated_dispensersLinearPositions_codec
+ = pb::FieldCodec.ForDouble(194);
+ private readonly pbc::RepeatedField<double> dispensersLinearPositions_ = new pbc::RepeatedField<double>();
+ /// <summary>
+ ///Dispensers Linear Positions
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public pbc::RepeatedField<double> DispensersLinearPositions {
+ get { return dispensersLinearPositions_; }
+ }
+
+ /// <summary>Field number for the "DispensersPressure" field.</summary>
+ public const int DispensersPressureFieldNumber = 25;
+ private static readonly pb::FieldCodec<double> _repeated_dispensersPressure_codec
+ = pb::FieldCodec.ForDouble(202);
+ private readonly pbc::RepeatedField<double> dispensersPressure_ = new pbc::RepeatedField<double>();
+ /// <summary>
+ ///Dispensers Pressure
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public pbc::RepeatedField<double> DispensersPressure {
+ get { return dispensersPressure_; }
+ }
+
+ /// <summary>Field number for the "FilterDeltaPressure" field.</summary>
+ public const int FilterDeltaPressureFieldNumber = 26;
+ private double filterDeltaPressure_;
+ /// <summary>
+ ///Filter Delta Pressure
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double FilterDeltaPressure {
+ get { return filterDeltaPressure_; }
+ set {
+ filterDeltaPressure_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "ChillerTemperature" field.</summary>
+ public const int ChillerTemperatureFieldNumber = 27;
+ private double chillerTemperature_;
+ /// <summary>
+ ///Chiller Temperature
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double ChillerTemperature {
+ get { return chillerTemperature_; }
+ set {
+ chillerTemperature_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "Dispenser1MotorFrequency" field.</summary>
+ public const int Dispenser1MotorFrequencyFieldNumber = 28;
+ private double dispenser1MotorFrequency_;
+ /// <summary>
+ ///Dispenser 1 Motor Frequency
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double Dispenser1MotorFrequency {
+ get { return dispenser1MotorFrequency_; }
+ set {
+ dispenser1MotorFrequency_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "Dispenser2MotorFrequency" field.</summary>
+ public const int Dispenser2MotorFrequencyFieldNumber = 29;
+ private double dispenser2MotorFrequency_;
+ /// <summary>
+ ///Dispenser 2 Motor Frequency
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double Dispenser2MotorFrequency {
+ get { return dispenser2MotorFrequency_; }
+ set {
+ dispenser2MotorFrequency_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "Dispenser3MotorFrequency" field.</summary>
+ public const int Dispenser3MotorFrequencyFieldNumber = 30;
+ private double dispenser3MotorFrequency_;
+ /// <summary>
+ ///Dispenser 3 Motor Frequency
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double Dispenser3MotorFrequency {
+ get { return dispenser3MotorFrequency_; }
+ set {
+ dispenser3MotorFrequency_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "Dispenser4MotorFrequency" field.</summary>
+ public const int Dispenser4MotorFrequencyFieldNumber = 31;
+ private double dispenser4MotorFrequency_;
+ /// <summary>
+ ///Dispenser 4 Motor Frequency
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double Dispenser4MotorFrequency {
+ get { return dispenser4MotorFrequency_; }
+ set {
+ dispenser4MotorFrequency_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "Dispenser5MotorFrequency" field.</summary>
+ public const int Dispenser5MotorFrequencyFieldNumber = 32;
+ private double dispenser5MotorFrequency_;
+ /// <summary>
+ ///Dispenser 5 Motor Frequency
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double Dispenser5MotorFrequency {
+ get { return dispenser5MotorFrequency_; }
+ set {
+ dispenser5MotorFrequency_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "Dispenser6MotorFrequency" field.</summary>
+ public const int Dispenser6MotorFrequencyFieldNumber = 33;
+ private double dispenser6MotorFrequency_;
+ /// <summary>
+ ///Dispenser 6 Motor Frequency
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double Dispenser6MotorFrequency {
+ get { return dispenser6MotorFrequency_; }
+ set {
+ dispenser6MotorFrequency_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "Dispenser7MotorFrequency" field.</summary>
+ public const int Dispenser7MotorFrequencyFieldNumber = 34;
+ private double dispenser7MotorFrequency_;
+ /// <summary>
+ ///Dispenser 7 Motor Frequency
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double Dispenser7MotorFrequency {
+ get { return dispenser7MotorFrequency_; }
+ set {
+ dispenser7MotorFrequency_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "Dispenser8MotorFrequency" field.</summary>
+ public const int Dispenser8MotorFrequencyFieldNumber = 35;
+ private double dispenser8MotorFrequency_;
+ /// <summary>
+ ///Dispenser 8 Motor Frequency
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double Dispenser8MotorFrequency {
+ get { return dispenser8MotorFrequency_; }
+ set {
+ dispenser8MotorFrequency_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone4Temperature" field.</summary>
+ public const int HeadZone4TemperatureFieldNumber = 36;
+ private double headZone4Temperature_;
+ /// <summary>
+ ///Head Zone 4
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone4Temperature {
+ get { return headZone4Temperature_; }
+ set {
+ headZone4Temperature_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone5Temperature" field.</summary>
+ public const int HeadZone5TemperatureFieldNumber = 37;
+ private double headZone5Temperature_;
+ /// <summary>
+ ///Head Zone 5
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone5Temperature {
+ get { return headZone5Temperature_; }
+ set {
+ headZone5Temperature_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone6Temperature" field.</summary>
+ public const int HeadZone6TemperatureFieldNumber = 38;
+ private double headZone6Temperature_;
+ /// <summary>
+ ///Head Zone 6
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone6Temperature {
+ get { return headZone6Temperature_; }
+ set {
+ headZone6Temperature_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "BlowerVoltage" field.</summary>
+ public const int BlowerVoltageFieldNumber = 39;
+ private double blowerVoltage_;
+ /// <summary>
+ ///Blower Voltage
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double BlowerVoltage {
+ get { return blowerVoltage_; }
+ set {
+ blowerVoltage_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "Dispenser1Pressure" field.</summary>
+ public const int Dispenser1PressureFieldNumber = 40;
+ private double dispenser1Pressure_;
+ /// <summary>
+ ///Dispenser 1 Pressure
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double Dispenser1Pressure {
+ get { return dispenser1Pressure_; }
+ set {
+ dispenser1Pressure_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "Dispenser2Pressure" field.</summary>
+ public const int Dispenser2PressureFieldNumber = 41;
+ private double dispenser2Pressure_;
+ /// <summary>
+ ///Dispenser 2 Pressure
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double Dispenser2Pressure {
+ get { return dispenser2Pressure_; }
+ set {
+ dispenser2Pressure_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "Dispenser3Pressure" field.</summary>
+ public const int Dispenser3PressureFieldNumber = 42;
+ private double dispenser3Pressure_;
+ /// <summary>
+ ///Dispenser 3 Pressure
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double Dispenser3Pressure {
+ get { return dispenser3Pressure_; }
+ set {
+ dispenser3Pressure_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "Dispenser4Pressure" field.</summary>
+ public const int Dispenser4PressureFieldNumber = 43;
+ private double dispenser4Pressure_;
+ /// <summary>
+ ///Dispenser 4 Pressure
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double Dispenser4Pressure {
+ get { return dispenser4Pressure_; }
+ set {
+ dispenser4Pressure_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "Dispenser5Pressure" field.</summary>
+ public const int Dispenser5PressureFieldNumber = 44;
+ private double dispenser5Pressure_;
+ /// <summary>
+ ///Dispenser 5 Pressure
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double Dispenser5Pressure {
+ get { return dispenser5Pressure_; }
+ set {
+ dispenser5Pressure_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "Dispenser6Pressure" field.</summary>
+ public const int Dispenser6PressureFieldNumber = 45;
+ private double dispenser6Pressure_;
+ /// <summary>
+ ///Dispenser 6 Pressure
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double Dispenser6Pressure {
+ get { return dispenser6Pressure_; }
+ set {
+ dispenser6Pressure_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "Dispenser7Pressure" field.</summary>
+ public const int Dispenser7PressureFieldNumber = 46;
+ private double dispenser7Pressure_;
+ /// <summary>
+ ///Dispenser 7 Pressure
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double Dispenser7Pressure {
+ get { return dispenser7Pressure_; }
+ set {
+ dispenser7Pressure_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "Dispenser8Pressure" field.</summary>
+ public const int Dispenser8PressureFieldNumber = 47;
+ private double dispenser8Pressure_;
+ /// <summary>
+ ///Dispenser 8 Pressure
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double Dispenser8Pressure {
+ get { return dispenser8Pressure_; }
+ set {
+ dispenser8Pressure_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "MidTank1Level" field.</summary>
+ public const int MidTank1LevelFieldNumber = 48;
+ private double midTank1Level_;
+ /// <summary>
+ ///Mid Tank 1 Level
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double MidTank1Level {
+ get { return midTank1Level_; }
+ set {
+ midTank1Level_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "MidTank2Level" field.</summary>
+ public const int MidTank2LevelFieldNumber = 49;
+ private double midTank2Level_;
+ /// <summary>
+ ///Mid Tank 2 Level
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double MidTank2Level {
+ get { return midTank2Level_; }
+ set {
+ midTank2Level_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "MidTank3Level" field.</summary>
+ public const int MidTank3LevelFieldNumber = 50;
+ private double midTank3Level_;
+ /// <summary>
+ ///Mid Tank 3 Level
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double MidTank3Level {
+ get { return midTank3Level_; }
+ set {
+ midTank3Level_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "MidTank4Level" field.</summary>
+ public const int MidTank4LevelFieldNumber = 51;
+ private double midTank4Level_;
+ /// <summary>
+ ///Mid Tank 4 Level
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double MidTank4Level {
+ get { return midTank4Level_; }
+ set {
+ midTank4Level_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "MidTank5Level" field.</summary>
+ public const int MidTank5LevelFieldNumber = 52;
+ private double midTank5Level_;
+ /// <summary>
+ ///Mid Tank 5 Level
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double MidTank5Level {
+ get { return midTank5Level_; }
+ set {
+ midTank5Level_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "MidTank6Level" field.</summary>
+ public const int MidTank6LevelFieldNumber = 53;
+ private double midTank6Level_;
+ /// <summary>
+ ///Mid Tank 6 Level
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double MidTank6Level {
+ get { return midTank6Level_; }
+ set {
+ midTank6Level_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "MidTank7Level" field.</summary>
+ public const int MidTank7LevelFieldNumber = 54;
+ private double midTank7Level_;
+ /// <summary>
+ ///Mid Tank 7 Level
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double MidTank7Level {
+ get { return midTank7Level_; }
+ set {
+ midTank7Level_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "MidTank8Level" field.</summary>
+ public const int MidTank8LevelFieldNumber = 55;
+ private double midTank8Level_;
+ /// <summary>
+ ///Mid Tank 8 Level
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double MidTank8Level {
+ get { return midTank8Level_; }
+ set {
+ midTank8Level_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "DrierZone1HeaterCurrent" field.</summary>
+ public const int DrierZone1HeaterCurrentFieldNumber = 56;
+ private double drierZone1HeaterCurrent_;
+ /// <summary>
+ ///Drier Zone1 Heater Current
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double DrierZone1HeaterCurrent {
+ get { return drierZone1HeaterCurrent_; }
+ set {
+ drierZone1HeaterCurrent_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "DrierZone2HeaterCurrent" field.</summary>
+ public const int DrierZone2HeaterCurrentFieldNumber = 57;
+ private double drierZone2HeaterCurrent_;
+ /// <summary>
+ ///Drier Zone 2 Heater Current
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double DrierZone2HeaterCurrent {
+ get { return drierZone2HeaterCurrent_; }
+ set {
+ drierZone2HeaterCurrent_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone1HeaterCurrent" field.</summary>
+ public const int HeadZone1HeaterCurrentFieldNumber = 58;
+ private double headZone1HeaterCurrent_;
+ /// <summary>
+ ///Head Zone 1 Heater Current
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone1HeaterCurrent {
+ get { return headZone1HeaterCurrent_; }
+ set {
+ headZone1HeaterCurrent_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone2HeaterCurrent" field.</summary>
+ public const int HeadZone2HeaterCurrentFieldNumber = 59;
+ private double headZone2HeaterCurrent_;
+ /// <summary>
+ ///Head Zone 2 Heater Current
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone2HeaterCurrent {
+ get { return headZone2HeaterCurrent_; }
+ set {
+ headZone2HeaterCurrent_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone3HeaterCurrent" field.</summary>
+ public const int HeadZone3HeaterCurrentFieldNumber = 60;
+ private double headZone3HeaterCurrent_;
+ /// <summary>
+ ///Head Zone 3 Heater Current
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone3HeaterCurrent {
+ get { return headZone3HeaterCurrent_; }
+ set {
+ headZone3HeaterCurrent_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone4HeaterCurrent" field.</summary>
+ public const int HeadZone4HeaterCurrentFieldNumber = 61;
+ private double headZone4HeaterCurrent_;
+ /// <summary>
+ ///Head Zone 4 Heater Current
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone4HeaterCurrent {
+ get { return headZone4HeaterCurrent_; }
+ set {
+ headZone4HeaterCurrent_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone5_6HeaterCurrent" field.</summary>
+ public const int HeadZone56HeaterCurrentFieldNumber = 62;
+ private double headZone56HeaterCurrent_;
+ /// <summary>
+ ///Head Zone 5-6 Heater Current
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone56HeaterCurrent {
+ get { return headZone56HeaterCurrent_; }
+ set {
+ headZone56HeaterCurrent_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "Mixer1HeaterCurrent" field.</summary>
+ public const int Mixer1HeaterCurrentFieldNumber = 63;
+ private double mixer1HeaterCurrent_;
+ /// <summary>
+ ///Mixer 1 Heater Current
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double Mixer1HeaterCurrent {
+ get { return mixer1HeaterCurrent_; }
+ set {
+ mixer1HeaterCurrent_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "DispensersInkLevel" field.</summary>
+ public const int DispensersInkLevelFieldNumber = 64;
+ private static readonly pb::FieldCodec<double> _repeated_dispensersInkLevel_codec
+ = pb::FieldCodec.ForDouble(514);
+ private readonly pbc::RepeatedField<double> dispensersInkLevel_ = new pbc::RepeatedField<double>();
+ /// <summary>
+ ///Dispensers Ink Level
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public pbc::RepeatedField<double> DispensersInkLevel {
+ get { return dispensersInkLevel_; }
+ }
+
+ /// <summary>Field number for the "MidTanksInkLevel" field.</summary>
+ public const int MidTanksInkLevelFieldNumber = 65;
+ private static readonly pb::FieldCodec<double> _repeated_midTanksInkLevel_codec
+ = pb::FieldCodec.ForDouble(522);
+ private readonly pbc::RepeatedField<double> midTanksInkLevel_ = new pbc::RepeatedField<double>();
+ /// <summary>
+ ///Mid Tanks Ink Level
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public pbc::RepeatedField<double> MidTanksInkLevel {
+ get { return midTanksInkLevel_; }
+ }
+
+ /// <summary>Field number for the "OverallTemperature" field.</summary>
+ public const int OverallTemperatureFieldNumber = 66;
+ private double overallTemperature_;
+ /// <summary>
+ ///Overall Temperature
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double OverallTemperature {
+ get { return overallTemperature_; }
+ set {
+ overallTemperature_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone7HeaterCurrent" field.</summary>
+ public const int HeadZone7HeaterCurrentFieldNumber = 67;
+ private double headZone7HeaterCurrent_;
+ /// <summary>
+ ///Head Zone 7 Heater Current
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone7HeaterCurrent {
+ get { return headZone7HeaterCurrent_; }
+ set {
+ headZone7HeaterCurrent_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone7Temperature" field.</summary>
+ public const int HeadZone7TemperatureFieldNumber = 68;
+ private double headZone7Temperature_;
+ /// <summary>
+ ///Head Zone 7
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone7Temperature {
+ get { return headZone7Temperature_; }
+ set {
+ headZone7Temperature_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone8HeaterCurrent" field.</summary>
+ public const int HeadZone8HeaterCurrentFieldNumber = 69;
+ private double headZone8HeaterCurrent_;
+ /// <summary>
+ ///Head Zone 8 Heater Current
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone8HeaterCurrent {
+ get { return headZone8HeaterCurrent_; }
+ set {
+ headZone8HeaterCurrent_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone8Temperature" field.</summary>
+ public const int HeadZone8TemperatureFieldNumber = 70;
+ private double headZone8Temperature_;
+ /// <summary>
+ ///Head Zone 8
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone8Temperature {
+ get { return headZone8Temperature_; }
+ set {
+ headZone8Temperature_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone9HeaterCurrent" field.</summary>
+ public const int HeadZone9HeaterCurrentFieldNumber = 71;
+ private double headZone9HeaterCurrent_;
+ /// <summary>
+ ///Head Zone 9 Heater Current
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone9HeaterCurrent {
+ get { return headZone9HeaterCurrent_; }
+ set {
+ headZone9HeaterCurrent_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone9Temperature" field.</summary>
+ public const int HeadZone9TemperatureFieldNumber = 72;
+ private double headZone9Temperature_;
+ /// <summary>
+ ///Head Zone 9
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone9Temperature {
+ get { return headZone9Temperature_; }
+ set {
+ headZone9Temperature_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone10HeaterCurrent" field.</summary>
+ public const int HeadZone10HeaterCurrentFieldNumber = 73;
+ private double headZone10HeaterCurrent_;
+ /// <summary>
+ ///Head Zone 10 Heater Current
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone10HeaterCurrent {
+ get { return headZone10HeaterCurrent_; }
+ set {
+ headZone10HeaterCurrent_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone10Temperature" field.</summary>
+ public const int HeadZone10TemperatureFieldNumber = 74;
+ private double headZone10Temperature_;
+ /// <summary>
+ ///Head Zone 10
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone10Temperature {
+ get { return headZone10Temperature_; }
+ set {
+ headZone10Temperature_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone11HeaterCurrent" field.</summary>
+ public const int HeadZone11HeaterCurrentFieldNumber = 75;
+ private double headZone11HeaterCurrent_;
+ /// <summary>
+ ///Head Zone 11 Heater Current
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone11HeaterCurrent {
+ get { return headZone11HeaterCurrent_; }
+ set {
+ headZone11HeaterCurrent_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone11Temperature" field.</summary>
+ public const int HeadZone11TemperatureFieldNumber = 76;
+ private double headZone11Temperature_;
+ /// <summary>
+ ///Head Zone 11
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone11Temperature {
+ get { return headZone11Temperature_; }
+ set {
+ headZone11Temperature_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone12HeaterCurrent" field.</summary>
+ public const int HeadZone12HeaterCurrentFieldNumber = 77;
+ private double headZone12HeaterCurrent_;
+ /// <summary>
+ ///Head Zone 12 Heater Current
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone12HeaterCurrent {
+ get { return headZone12HeaterCurrent_; }
+ set {
+ headZone12HeaterCurrent_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadZone12Temperature" field.</summary>
+ public const int HeadZone12TemperatureFieldNumber = 78;
+ private double headZone12Temperature_;
+ /// <summary>
+ ///Head Zone 12
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadZone12Temperature {
+ get { return headZone12Temperature_; }
+ set {
+ headZone12Temperature_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadBlowerVoltage1" field.</summary>
+ public const int HeadBlowerVoltage1FieldNumber = 79;
+ private double headBlowerVoltage1_;
+ /// <summary>
+ ///Head Blower Voltage 1
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadBlowerVoltage1 {
+ get { return headBlowerVoltage1_; }
+ set {
+ headBlowerVoltage1_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadBlowerVoltage2" field.</summary>
+ public const int HeadBlowerVoltage2FieldNumber = 80;
+ private double headBlowerVoltage2_;
+ /// <summary>
+ ///Head Blower Voltage 2
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadBlowerVoltage2 {
+ get { return headBlowerVoltage2_; }
+ set {
+ headBlowerVoltage2_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadCoverHeater1Current" field.</summary>
+ public const int HeadCoverHeater1CurrentFieldNumber = 81;
+ private double headCoverHeater1Current_;
+ /// <summary>
+ ///Head Cover Heater 1 Current
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadCoverHeater1Current {
+ get { return headCoverHeater1Current_; }
+ set {
+ headCoverHeater1Current_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadCoverHeater1Temperature" field.</summary>
+ public const int HeadCoverHeater1TemperatureFieldNumber = 82;
+ private double headCoverHeater1Temperature_;
+ /// <summary>
+ ///Head Cover Heater 1 Temperature
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadCoverHeater1Temperature {
+ get { return headCoverHeater1Temperature_; }
+ set {
+ headCoverHeater1Temperature_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadCoverHeater2Current" field.</summary>
+ public const int HeadCoverHeater2CurrentFieldNumber = 83;
+ private double headCoverHeater2Current_;
+ /// <summary>
+ ///Head Cover Heater 2 Current
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadCoverHeater2Current {
+ get { return headCoverHeater2Current_; }
+ set {
+ headCoverHeater2Current_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadCoverHeater2Temperature" field.</summary>
+ public const int HeadCoverHeater2TemperatureFieldNumber = 84;
+ private double headCoverHeater2Temperature_;
+ /// <summary>
+ ///Head Cover Heater 2 Temperature
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadCoverHeater2Temperature {
+ get { return headCoverHeater2Temperature_; }
+ set {
+ headCoverHeater2Temperature_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "WHSBlower2Voltage" field.</summary>
+ public const int WHSBlower2VoltageFieldNumber = 85;
+ private double wHSBlower2Voltage_;
+ /// <summary>
+ ///WHS Blower 2 Voltage
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double WHSBlower2Voltage {
+ get { return wHSBlower2Voltage_; }
+ set {
+ wHSBlower2Voltage_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "GasSensor" field.</summary>
+ public const int GasSensorFieldNumber = 86;
+ private double gasSensor_;
+ /// <summary>
+ ///Gas Sensor (VOC Sensor)
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double GasSensor {
+ get { return gasSensor_; }
+ set {
+ gasSensor_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "IncomingVoltage" field.</summary>
+ public const int IncomingVoltageFieldNumber = 87;
+ private double incomingVoltage_;
+ /// <summary>
+ ///Incoming Voltage (VAC Sensor)
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double IncomingVoltage {
+ get { return incomingVoltage_; }
+ set {
+ incomingVoltage_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "WasteLevel" field.</summary>
+ public const int WasteLevelFieldNumber = 88;
+ private double wasteLevel_;
+ /// <summary>
+ ///Waste Level
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double WasteLevel {
+ get { return wasteLevel_; }
+ set {
+ wasteLevel_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadBlower1AirFlow" field.</summary>
+ public const int HeadBlower1AirFlowFieldNumber = 89;
+ private double headBlower1AirFlow_;
+ /// <summary>
+ ///Head Blower 1 Air Flow
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadBlower1AirFlow {
+ get { return headBlower1AirFlow_; }
+ set {
+ headBlower1AirFlow_ = value;
+ }
+ }
+
+ /// <summary>Field number for the "HeadBlower2AirFlow" field.</summary>
+ public const int HeadBlower2AirFlowFieldNumber = 90;
+ private double headBlower2AirFlow_;
+ /// <summary>
+ ///Head Blower 2 Air Flow
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public double HeadBlower2AirFlow {
+ get { return headBlower2AirFlow_; }
+ set {
+ headBlower2AirFlow_ = value;
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override bool Equals(object other) {
+ return Equals(other as InsightsMonitors);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public bool Equals(InsightsMonitors other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (Dancer1Angle != other.Dancer1Angle) return false;
+ if (Dancer2Angle != other.Dancer2Angle) return false;
+ if (Dancer3Angle != other.Dancer3Angle) return false;
+ if (FeederMotorFrequency != other.FeederMotorFrequency) return false;
+ if (DryerMotor != other.DryerMotor) return false;
+ if (PollerMotor != other.PollerMotor) return false;
+ if (WinderMotor != other.WinderMotor) return false;
+ if (ScrewMotor != other.ScrewMotor) return false;
+ if (ThreadSpeed != other.ThreadSpeed) return false;
+ if (MixerTemperature != other.MixerTemperature) return false;
+ if (HeadZone1Temperature != other.HeadZone1Temperature) return false;
+ if (HeadZone2Temperature != other.HeadZone2Temperature) return false;
+ if (HeadZone3Temperature != other.HeadZone3Temperature) return false;
+ if (HeadAirFlow != other.HeadAirFlow) return false;
+ if (FeederTension != other.FeederTension) return false;
+ if (PullerTension != other.PullerTension) return false;
+ if (DryerZone1Temperature != other.DryerZone1Temperature) return false;
+ if (DryerZone2Temperature != other.DryerZone2Temperature) return false;
+ if (DryerZone3Temperature != other.DryerZone3Temperature) return false;
+ if (DryerAirFlow != other.DryerAirFlow) return false;
+ if (WinderTension != other.WinderTension) return false;
+ if(!dispensersMotorsFrequency_.Equals(other.dispensersMotorsFrequency_)) return false;
+ if(!dispensersAngularEncoders_.Equals(other.dispensersAngularEncoders_)) return false;
+ if(!dispensersLinearPositions_.Equals(other.dispensersLinearPositions_)) return false;
+ if(!dispensersPressure_.Equals(other.dispensersPressure_)) return false;
+ if (FilterDeltaPressure != other.FilterDeltaPressure) return false;
+ if (ChillerTemperature != other.ChillerTemperature) return false;
+ if (Dispenser1MotorFrequency != other.Dispenser1MotorFrequency) return false;
+ if (Dispenser2MotorFrequency != other.Dispenser2MotorFrequency) return false;
+ if (Dispenser3MotorFrequency != other.Dispenser3MotorFrequency) return false;
+ if (Dispenser4MotorFrequency != other.Dispenser4MotorFrequency) return false;
+ if (Dispenser5MotorFrequency != other.Dispenser5MotorFrequency) return false;
+ if (Dispenser6MotorFrequency != other.Dispenser6MotorFrequency) return false;
+ if (Dispenser7MotorFrequency != other.Dispenser7MotorFrequency) return false;
+ if (Dispenser8MotorFrequency != other.Dispenser8MotorFrequency) return false;
+ if (HeadZone4Temperature != other.HeadZone4Temperature) return false;
+ if (HeadZone5Temperature != other.HeadZone5Temperature) return false;
+ if (HeadZone6Temperature != other.HeadZone6Temperature) return false;
+ if (BlowerVoltage != other.BlowerVoltage) return false;
+ if (Dispenser1Pressure != other.Dispenser1Pressure) return false;
+ if (Dispenser2Pressure != other.Dispenser2Pressure) return false;
+ if (Dispenser3Pressure != other.Dispenser3Pressure) return false;
+ if (Dispenser4Pressure != other.Dispenser4Pressure) return false;
+ if (Dispenser5Pressure != other.Dispenser5Pressure) return false;
+ if (Dispenser6Pressure != other.Dispenser6Pressure) return false;
+ if (Dispenser7Pressure != other.Dispenser7Pressure) return false;
+ if (Dispenser8Pressure != other.Dispenser8Pressure) return false;
+ if (MidTank1Level != other.MidTank1Level) return false;
+ if (MidTank2Level != other.MidTank2Level) return false;
+ if (MidTank3Level != other.MidTank3Level) return false;
+ if (MidTank4Level != other.MidTank4Level) return false;
+ if (MidTank5Level != other.MidTank5Level) return false;
+ if (MidTank6Level != other.MidTank6Level) return false;
+ if (MidTank7Level != other.MidTank7Level) return false;
+ if (MidTank8Level != other.MidTank8Level) return false;
+ if (DrierZone1HeaterCurrent != other.DrierZone1HeaterCurrent) return false;
+ if (DrierZone2HeaterCurrent != other.DrierZone2HeaterCurrent) return false;
+ if (HeadZone1HeaterCurrent != other.HeadZone1HeaterCurrent) return false;
+ if (HeadZone2HeaterCurrent != other.HeadZone2HeaterCurrent) return false;
+ if (HeadZone3HeaterCurrent != other.HeadZone3HeaterCurrent) return false;
+ if (HeadZone4HeaterCurrent != other.HeadZone4HeaterCurrent) return false;
+ if (HeadZone56HeaterCurrent != other.HeadZone56HeaterCurrent) return false;
+ if (Mixer1HeaterCurrent != other.Mixer1HeaterCurrent) return false;
+ if(!dispensersInkLevel_.Equals(other.dispensersInkLevel_)) return false;
+ if(!midTanksInkLevel_.Equals(other.midTanksInkLevel_)) return false;
+ if (OverallTemperature != other.OverallTemperature) return false;
+ if (HeadZone7HeaterCurrent != other.HeadZone7HeaterCurrent) return false;
+ if (HeadZone7Temperature != other.HeadZone7Temperature) return false;
+ if (HeadZone8HeaterCurrent != other.HeadZone8HeaterCurrent) return false;
+ if (HeadZone8Temperature != other.HeadZone8Temperature) return false;
+ if (HeadZone9HeaterCurrent != other.HeadZone9HeaterCurrent) return false;
+ if (HeadZone9Temperature != other.HeadZone9Temperature) return false;
+ if (HeadZone10HeaterCurrent != other.HeadZone10HeaterCurrent) return false;
+ if (HeadZone10Temperature != other.HeadZone10Temperature) return false;
+ if (HeadZone11HeaterCurrent != other.HeadZone11HeaterCurrent) return false;
+ if (HeadZone11Temperature != other.HeadZone11Temperature) return false;
+ if (HeadZone12HeaterCurrent != other.HeadZone12HeaterCurrent) return false;
+ if (HeadZone12Temperature != other.HeadZone12Temperature) return false;
+ if (HeadBlowerVoltage1 != other.HeadBlowerVoltage1) return false;
+ if (HeadBlowerVoltage2 != other.HeadBlowerVoltage2) return false;
+ if (HeadCoverHeater1Current != other.HeadCoverHeater1Current) return false;
+ if (HeadCoverHeater1Temperature != other.HeadCoverHeater1Temperature) return false;
+ if (HeadCoverHeater2Current != other.HeadCoverHeater2Current) return false;
+ if (HeadCoverHeater2Temperature != other.HeadCoverHeater2Temperature) return false;
+ if (WHSBlower2Voltage != other.WHSBlower2Voltage) return false;
+ if (GasSensor != other.GasSensor) return false;
+ if (IncomingVoltage != other.IncomingVoltage) return false;
+ if (WasteLevel != other.WasteLevel) return false;
+ if (HeadBlower1AirFlow != other.HeadBlower1AirFlow) return false;
+ if (HeadBlower2AirFlow != other.HeadBlower2AirFlow) return false;
+ return true;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override int GetHashCode() {
+ int hash = 1;
+ if (Dancer1Angle != 0D) hash ^= Dancer1Angle.GetHashCode();
+ if (Dancer2Angle != 0D) hash ^= Dancer2Angle.GetHashCode();
+ if (Dancer3Angle != 0D) hash ^= Dancer3Angle.GetHashCode();
+ if (FeederMotorFrequency != 0D) hash ^= FeederMotorFrequency.GetHashCode();
+ if (DryerMotor != 0D) hash ^= DryerMotor.GetHashCode();
+ if (PollerMotor != 0D) hash ^= PollerMotor.GetHashCode();
+ if (WinderMotor != 0D) hash ^= WinderMotor.GetHashCode();
+ if (ScrewMotor != 0D) hash ^= ScrewMotor.GetHashCode();
+ if (ThreadSpeed != 0D) hash ^= ThreadSpeed.GetHashCode();
+ if (MixerTemperature != 0D) hash ^= MixerTemperature.GetHashCode();
+ if (HeadZone1Temperature != 0D) hash ^= HeadZone1Temperature.GetHashCode();
+ if (HeadZone2Temperature != 0D) hash ^= HeadZone2Temperature.GetHashCode();
+ if (HeadZone3Temperature != 0D) hash ^= HeadZone3Temperature.GetHashCode();
+ if (HeadAirFlow != 0D) hash ^= HeadAirFlow.GetHashCode();
+ if (FeederTension != 0D) hash ^= FeederTension.GetHashCode();
+ if (PullerTension != 0D) hash ^= PullerTension.GetHashCode();
+ if (DryerZone1Temperature != 0D) hash ^= DryerZone1Temperature.GetHashCode();
+ if (DryerZone2Temperature != 0D) hash ^= DryerZone2Temperature.GetHashCode();
+ if (DryerZone3Temperature != 0D) hash ^= DryerZone3Temperature.GetHashCode();
+ if (DryerAirFlow != 0D) hash ^= DryerAirFlow.GetHashCode();
+ if (WinderTension != 0D) hash ^= WinderTension.GetHashCode();
+ hash ^= dispensersMotorsFrequency_.GetHashCode();
+ hash ^= dispensersAngularEncoders_.GetHashCode();
+ hash ^= dispensersLinearPositions_.GetHashCode();
+ hash ^= dispensersPressure_.GetHashCode();
+ if (FilterDeltaPressure != 0D) hash ^= FilterDeltaPressure.GetHashCode();
+ if (ChillerTemperature != 0D) hash ^= ChillerTemperature.GetHashCode();
+ if (Dispenser1MotorFrequency != 0D) hash ^= Dispenser1MotorFrequency.GetHashCode();
+ if (Dispenser2MotorFrequency != 0D) hash ^= Dispenser2MotorFrequency.GetHashCode();
+ if (Dispenser3MotorFrequency != 0D) hash ^= Dispenser3MotorFrequency.GetHashCode();
+ if (Dispenser4MotorFrequency != 0D) hash ^= Dispenser4MotorFrequency.GetHashCode();
+ if (Dispenser5MotorFrequency != 0D) hash ^= Dispenser5MotorFrequency.GetHashCode();
+ if (Dispenser6MotorFrequency != 0D) hash ^= Dispenser6MotorFrequency.GetHashCode();
+ if (Dispenser7MotorFrequency != 0D) hash ^= Dispenser7MotorFrequency.GetHashCode();
+ if (Dispenser8MotorFrequency != 0D) hash ^= Dispenser8MotorFrequency.GetHashCode();
+ if (HeadZone4Temperature != 0D) hash ^= HeadZone4Temperature.GetHashCode();
+ if (HeadZone5Temperature != 0D) hash ^= HeadZone5Temperature.GetHashCode();
+ if (HeadZone6Temperature != 0D) hash ^= HeadZone6Temperature.GetHashCode();
+ if (BlowerVoltage != 0D) hash ^= BlowerVoltage.GetHashCode();
+ if (Dispenser1Pressure != 0D) hash ^= Dispenser1Pressure.GetHashCode();
+ if (Dispenser2Pressure != 0D) hash ^= Dispenser2Pressure.GetHashCode();
+ if (Dispenser3Pressure != 0D) hash ^= Dispenser3Pressure.GetHashCode();
+ if (Dispenser4Pressure != 0D) hash ^= Dispenser4Pressure.GetHashCode();
+ if (Dispenser5Pressure != 0D) hash ^= Dispenser5Pressure.GetHashCode();
+ if (Dispenser6Pressure != 0D) hash ^= Dispenser6Pressure.GetHashCode();
+ if (Dispenser7Pressure != 0D) hash ^= Dispenser7Pressure.GetHashCode();
+ if (Dispenser8Pressure != 0D) hash ^= Dispenser8Pressure.GetHashCode();
+ if (MidTank1Level != 0D) hash ^= MidTank1Level.GetHashCode();
+ if (MidTank2Level != 0D) hash ^= MidTank2Level.GetHashCode();
+ if (MidTank3Level != 0D) hash ^= MidTank3Level.GetHashCode();
+ if (MidTank4Level != 0D) hash ^= MidTank4Level.GetHashCode();
+ if (MidTank5Level != 0D) hash ^= MidTank5Level.GetHashCode();
+ if (MidTank6Level != 0D) hash ^= MidTank6Level.GetHashCode();
+ if (MidTank7Level != 0D) hash ^= MidTank7Level.GetHashCode();
+ if (MidTank8Level != 0D) hash ^= MidTank8Level.GetHashCode();
+ if (DrierZone1HeaterCurrent != 0D) hash ^= DrierZone1HeaterCurrent.GetHashCode();
+ if (DrierZone2HeaterCurrent != 0D) hash ^= DrierZone2HeaterCurrent.GetHashCode();
+ if (HeadZone1HeaterCurrent != 0D) hash ^= HeadZone1HeaterCurrent.GetHashCode();
+ if (HeadZone2HeaterCurrent != 0D) hash ^= HeadZone2HeaterCurrent.GetHashCode();
+ if (HeadZone3HeaterCurrent != 0D) hash ^= HeadZone3HeaterCurrent.GetHashCode();
+ if (HeadZone4HeaterCurrent != 0D) hash ^= HeadZone4HeaterCurrent.GetHashCode();
+ if (HeadZone56HeaterCurrent != 0D) hash ^= HeadZone56HeaterCurrent.GetHashCode();
+ if (Mixer1HeaterCurrent != 0D) hash ^= Mixer1HeaterCurrent.GetHashCode();
+ hash ^= dispensersInkLevel_.GetHashCode();
+ hash ^= midTanksInkLevel_.GetHashCode();
+ if (OverallTemperature != 0D) hash ^= OverallTemperature.GetHashCode();
+ if (HeadZone7HeaterCurrent != 0D) hash ^= HeadZone7HeaterCurrent.GetHashCode();
+ if (HeadZone7Temperature != 0D) hash ^= HeadZone7Temperature.GetHashCode();
+ if (HeadZone8HeaterCurrent != 0D) hash ^= HeadZone8HeaterCurrent.GetHashCode();
+ if (HeadZone8Temperature != 0D) hash ^= HeadZone8Temperature.GetHashCode();
+ if (HeadZone9HeaterCurrent != 0D) hash ^= HeadZone9HeaterCurrent.GetHashCode();
+ if (HeadZone9Temperature != 0D) hash ^= HeadZone9Temperature.GetHashCode();
+ if (HeadZone10HeaterCurrent != 0D) hash ^= HeadZone10HeaterCurrent.GetHashCode();
+ if (HeadZone10Temperature != 0D) hash ^= HeadZone10Temperature.GetHashCode();
+ if (HeadZone11HeaterCurrent != 0D) hash ^= HeadZone11HeaterCurrent.GetHashCode();
+ if (HeadZone11Temperature != 0D) hash ^= HeadZone11Temperature.GetHashCode();
+ if (HeadZone12HeaterCurrent != 0D) hash ^= HeadZone12HeaterCurrent.GetHashCode();
+ if (HeadZone12Temperature != 0D) hash ^= HeadZone12Temperature.GetHashCode();
+ if (HeadBlowerVoltage1 != 0D) hash ^= HeadBlowerVoltage1.GetHashCode();
+ if (HeadBlowerVoltage2 != 0D) hash ^= HeadBlowerVoltage2.GetHashCode();
+ if (HeadCoverHeater1Current != 0D) hash ^= HeadCoverHeater1Current.GetHashCode();
+ if (HeadCoverHeater1Temperature != 0D) hash ^= HeadCoverHeater1Temperature.GetHashCode();
+ if (HeadCoverHeater2Current != 0D) hash ^= HeadCoverHeater2Current.GetHashCode();
+ if (HeadCoverHeater2Temperature != 0D) hash ^= HeadCoverHeater2Temperature.GetHashCode();
+ if (WHSBlower2Voltage != 0D) hash ^= WHSBlower2Voltage.GetHashCode();
+ if (GasSensor != 0D) hash ^= GasSensor.GetHashCode();
+ if (IncomingVoltage != 0D) hash ^= IncomingVoltage.GetHashCode();
+ if (WasteLevel != 0D) hash ^= WasteLevel.GetHashCode();
+ if (HeadBlower1AirFlow != 0D) hash ^= HeadBlower1AirFlow.GetHashCode();
+ if (HeadBlower2AirFlow != 0D) hash ^= HeadBlower2AirFlow.GetHashCode();
+ return hash;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override string ToString() {
+ return pb::JsonFormatter.ToDiagnosticString(this);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (Dancer1Angle != 0D) {
+ output.WriteRawTag(9);
+ output.WriteDouble(Dancer1Angle);
+ }
+ if (Dancer2Angle != 0D) {
+ output.WriteRawTag(17);
+ output.WriteDouble(Dancer2Angle);
+ }
+ if (Dancer3Angle != 0D) {
+ output.WriteRawTag(25);
+ output.WriteDouble(Dancer3Angle);
+ }
+ if (FeederMotorFrequency != 0D) {
+ output.WriteRawTag(33);
+ output.WriteDouble(FeederMotorFrequency);
+ }
+ if (DryerMotor != 0D) {
+ output.WriteRawTag(41);
+ output.WriteDouble(DryerMotor);
+ }
+ if (PollerMotor != 0D) {
+ output.WriteRawTag(49);
+ output.WriteDouble(PollerMotor);
+ }
+ if (WinderMotor != 0D) {
+ output.WriteRawTag(57);
+ output.WriteDouble(WinderMotor);
+ }
+ if (ScrewMotor != 0D) {
+ output.WriteRawTag(65);
+ output.WriteDouble(ScrewMotor);
+ }
+ if (ThreadSpeed != 0D) {
+ output.WriteRawTag(73);
+ output.WriteDouble(ThreadSpeed);
+ }
+ if (MixerTemperature != 0D) {
+ output.WriteRawTag(81);
+ output.WriteDouble(MixerTemperature);
+ }
+ if (HeadZone1Temperature != 0D) {
+ output.WriteRawTag(89);
+ output.WriteDouble(HeadZone1Temperature);
+ }
+ if (HeadZone2Temperature != 0D) {
+ output.WriteRawTag(97);
+ output.WriteDouble(HeadZone2Temperature);
+ }
+ if (HeadZone3Temperature != 0D) {
+ output.WriteRawTag(105);
+ output.WriteDouble(HeadZone3Temperature);
+ }
+ if (HeadAirFlow != 0D) {
+ output.WriteRawTag(113);
+ output.WriteDouble(HeadAirFlow);
+ }
+ if (FeederTension != 0D) {
+ output.WriteRawTag(121);
+ output.WriteDouble(FeederTension);
+ }
+ if (PullerTension != 0D) {
+ output.WriteRawTag(129, 1);
+ output.WriteDouble(PullerTension);
+ }
+ if (DryerZone1Temperature != 0D) {
+ output.WriteRawTag(137, 1);
+ output.WriteDouble(DryerZone1Temperature);
+ }
+ if (DryerZone2Temperature != 0D) {
+ output.WriteRawTag(145, 1);
+ output.WriteDouble(DryerZone2Temperature);
+ }
+ if (DryerZone3Temperature != 0D) {
+ output.WriteRawTag(153, 1);
+ output.WriteDouble(DryerZone3Temperature);
+ }
+ if (DryerAirFlow != 0D) {
+ output.WriteRawTag(161, 1);
+ output.WriteDouble(DryerAirFlow);
+ }
+ if (WinderTension != 0D) {
+ output.WriteRawTag(169, 1);
+ output.WriteDouble(WinderTension);
+ }
+ dispensersMotorsFrequency_.WriteTo(output, _repeated_dispensersMotorsFrequency_codec);
+ dispensersAngularEncoders_.WriteTo(output, _repeated_dispensersAngularEncoders_codec);
+ dispensersLinearPositions_.WriteTo(output, _repeated_dispensersLinearPositions_codec);
+ dispensersPressure_.WriteTo(output, _repeated_dispensersPressure_codec);
+ if (FilterDeltaPressure != 0D) {
+ output.WriteRawTag(209, 1);
+ output.WriteDouble(FilterDeltaPressure);
+ }
+ if (ChillerTemperature != 0D) {
+ output.WriteRawTag(217, 1);
+ output.WriteDouble(ChillerTemperature);
+ }
+ if (Dispenser1MotorFrequency != 0D) {
+ output.WriteRawTag(225, 1);
+ output.WriteDouble(Dispenser1MotorFrequency);
+ }
+ if (Dispenser2MotorFrequency != 0D) {
+ output.WriteRawTag(233, 1);
+ output.WriteDouble(Dispenser2MotorFrequency);
+ }
+ if (Dispenser3MotorFrequency != 0D) {
+ output.WriteRawTag(241, 1);
+ output.WriteDouble(Dispenser3MotorFrequency);
+ }
+ if (Dispenser4MotorFrequency != 0D) {
+ output.WriteRawTag(249, 1);
+ output.WriteDouble(Dispenser4MotorFrequency);
+ }
+ if (Dispenser5MotorFrequency != 0D) {
+ output.WriteRawTag(129, 2);
+ output.WriteDouble(Dispenser5MotorFrequency);
+ }
+ if (Dispenser6MotorFrequency != 0D) {
+ output.WriteRawTag(137, 2);
+ output.WriteDouble(Dispenser6MotorFrequency);
+ }
+ if (Dispenser7MotorFrequency != 0D) {
+ output.WriteRawTag(145, 2);
+ output.WriteDouble(Dispenser7MotorFrequency);
+ }
+ if (Dispenser8MotorFrequency != 0D) {
+ output.WriteRawTag(153, 2);
+ output.WriteDouble(Dispenser8MotorFrequency);
+ }
+ if (HeadZone4Temperature != 0D) {
+ output.WriteRawTag(161, 2);
+ output.WriteDouble(HeadZone4Temperature);
+ }
+ if (HeadZone5Temperature != 0D) {
+ output.WriteRawTag(169, 2);
+ output.WriteDouble(HeadZone5Temperature);
+ }
+ if (HeadZone6Temperature != 0D) {
+ output.WriteRawTag(177, 2);
+ output.WriteDouble(HeadZone6Temperature);
+ }
+ if (BlowerVoltage != 0D) {
+ output.WriteRawTag(185, 2);
+ output.WriteDouble(BlowerVoltage);
+ }
+ if (Dispenser1Pressure != 0D) {
+ output.WriteRawTag(193, 2);
+ output.WriteDouble(Dispenser1Pressure);
+ }
+ if (Dispenser2Pressure != 0D) {
+ output.WriteRawTag(201, 2);
+ output.WriteDouble(Dispenser2Pressure);
+ }
+ if (Dispenser3Pressure != 0D) {
+ output.WriteRawTag(209, 2);
+ output.WriteDouble(Dispenser3Pressure);
+ }
+ if (Dispenser4Pressure != 0D) {
+ output.WriteRawTag(217, 2);
+ output.WriteDouble(Dispenser4Pressure);
+ }
+ if (Dispenser5Pressure != 0D) {
+ output.WriteRawTag(225, 2);
+ output.WriteDouble(Dispenser5Pressure);
+ }
+ if (Dispenser6Pressure != 0D) {
+ output.WriteRawTag(233, 2);
+ output.WriteDouble(Dispenser6Pressure);
+ }
+ if (Dispenser7Pressure != 0D) {
+ output.WriteRawTag(241, 2);
+ output.WriteDouble(Dispenser7Pressure);
+ }
+ if (Dispenser8Pressure != 0D) {
+ output.WriteRawTag(249, 2);
+ output.WriteDouble(Dispenser8Pressure);
+ }
+ if (MidTank1Level != 0D) {
+ output.WriteRawTag(129, 3);
+ output.WriteDouble(MidTank1Level);
+ }
+ if (MidTank2Level != 0D) {
+ output.WriteRawTag(137, 3);
+ output.WriteDouble(MidTank2Level);
+ }
+ if (MidTank3Level != 0D) {
+ output.WriteRawTag(145, 3);
+ output.WriteDouble(MidTank3Level);
+ }
+ if (MidTank4Level != 0D) {
+ output.WriteRawTag(153, 3);
+ output.WriteDouble(MidTank4Level);
+ }
+ if (MidTank5Level != 0D) {
+ output.WriteRawTag(161, 3);
+ output.WriteDouble(MidTank5Level);
+ }
+ if (MidTank6Level != 0D) {
+ output.WriteRawTag(169, 3);
+ output.WriteDouble(MidTank6Level);
+ }
+ if (MidTank7Level != 0D) {
+ output.WriteRawTag(177, 3);
+ output.WriteDouble(MidTank7Level);
+ }
+ if (MidTank8Level != 0D) {
+ output.WriteRawTag(185, 3);
+ output.WriteDouble(MidTank8Level);
+ }
+ if (DrierZone1HeaterCurrent != 0D) {
+ output.WriteRawTag(193, 3);
+ output.WriteDouble(DrierZone1HeaterCurrent);
+ }
+ if (DrierZone2HeaterCurrent != 0D) {
+ output.WriteRawTag(201, 3);
+ output.WriteDouble(DrierZone2HeaterCurrent);
+ }
+ if (HeadZone1HeaterCurrent != 0D) {
+ output.WriteRawTag(209, 3);
+ output.WriteDouble(HeadZone1HeaterCurrent);
+ }
+ if (HeadZone2HeaterCurrent != 0D) {
+ output.WriteRawTag(217, 3);
+ output.WriteDouble(HeadZone2HeaterCurrent);
+ }
+ if (HeadZone3HeaterCurrent != 0D) {
+ output.WriteRawTag(225, 3);
+ output.WriteDouble(HeadZone3HeaterCurrent);
+ }
+ if (HeadZone4HeaterCurrent != 0D) {
+ output.WriteRawTag(233, 3);
+ output.WriteDouble(HeadZone4HeaterCurrent);
+ }
+ if (HeadZone56HeaterCurrent != 0D) {
+ output.WriteRawTag(241, 3);
+ output.WriteDouble(HeadZone56HeaterCurrent);
+ }
+ if (Mixer1HeaterCurrent != 0D) {
+ output.WriteRawTag(249, 3);
+ output.WriteDouble(Mixer1HeaterCurrent);
+ }
+ dispensersInkLevel_.WriteTo(output, _repeated_dispensersInkLevel_codec);
+ midTanksInkLevel_.WriteTo(output, _repeated_midTanksInkLevel_codec);
+ if (OverallTemperature != 0D) {
+ output.WriteRawTag(145, 4);
+ output.WriteDouble(OverallTemperature);
+ }
+ if (HeadZone7HeaterCurrent != 0D) {
+ output.WriteRawTag(153, 4);
+ output.WriteDouble(HeadZone7HeaterCurrent);
+ }
+ if (HeadZone7Temperature != 0D) {
+ output.WriteRawTag(161, 4);
+ output.WriteDouble(HeadZone7Temperature);
+ }
+ if (HeadZone8HeaterCurrent != 0D) {
+ output.WriteRawTag(169, 4);
+ output.WriteDouble(HeadZone8HeaterCurrent);
+ }
+ if (HeadZone8Temperature != 0D) {
+ output.WriteRawTag(177, 4);
+ output.WriteDouble(HeadZone8Temperature);
+ }
+ if (HeadZone9HeaterCurrent != 0D) {
+ output.WriteRawTag(185, 4);
+ output.WriteDouble(HeadZone9HeaterCurrent);
+ }
+ if (HeadZone9Temperature != 0D) {
+ output.WriteRawTag(193, 4);
+ output.WriteDouble(HeadZone9Temperature);
+ }
+ if (HeadZone10HeaterCurrent != 0D) {
+ output.WriteRawTag(201, 4);
+ output.WriteDouble(HeadZone10HeaterCurrent);
+ }
+ if (HeadZone10Temperature != 0D) {
+ output.WriteRawTag(209, 4);
+ output.WriteDouble(HeadZone10Temperature);
+ }
+ if (HeadZone11HeaterCurrent != 0D) {
+ output.WriteRawTag(217, 4);
+ output.WriteDouble(HeadZone11HeaterCurrent);
+ }
+ if (HeadZone11Temperature != 0D) {
+ output.WriteRawTag(225, 4);
+ output.WriteDouble(HeadZone11Temperature);
+ }
+ if (HeadZone12HeaterCurrent != 0D) {
+ output.WriteRawTag(233, 4);
+ output.WriteDouble(HeadZone12HeaterCurrent);
+ }
+ if (HeadZone12Temperature != 0D) {
+ output.WriteRawTag(241, 4);
+ output.WriteDouble(HeadZone12Temperature);
+ }
+ if (HeadBlowerVoltage1 != 0D) {
+ output.WriteRawTag(249, 4);
+ output.WriteDouble(HeadBlowerVoltage1);
+ }
+ if (HeadBlowerVoltage2 != 0D) {
+ output.WriteRawTag(129, 5);
+ output.WriteDouble(HeadBlowerVoltage2);
+ }
+ if (HeadCoverHeater1Current != 0D) {
+ output.WriteRawTag(137, 5);
+ output.WriteDouble(HeadCoverHeater1Current);
+ }
+ if (HeadCoverHeater1Temperature != 0D) {
+ output.WriteRawTag(145, 5);
+ output.WriteDouble(HeadCoverHeater1Temperature);
+ }
+ if (HeadCoverHeater2Current != 0D) {
+ output.WriteRawTag(153, 5);
+ output.WriteDouble(HeadCoverHeater2Current);
+ }
+ if (HeadCoverHeater2Temperature != 0D) {
+ output.WriteRawTag(161, 5);
+ output.WriteDouble(HeadCoverHeater2Temperature);
+ }
+ if (WHSBlower2Voltage != 0D) {
+ output.WriteRawTag(169, 5);
+ output.WriteDouble(WHSBlower2Voltage);
+ }
+ if (GasSensor != 0D) {
+ output.WriteRawTag(177, 5);
+ output.WriteDouble(GasSensor);
+ }
+ if (IncomingVoltage != 0D) {
+ output.WriteRawTag(185, 5);
+ output.WriteDouble(IncomingVoltage);
+ }
+ if (WasteLevel != 0D) {
+ output.WriteRawTag(193, 5);
+ output.WriteDouble(WasteLevel);
+ }
+ if (HeadBlower1AirFlow != 0D) {
+ output.WriteRawTag(201, 5);
+ output.WriteDouble(HeadBlower1AirFlow);
+ }
+ if (HeadBlower2AirFlow != 0D) {
+ output.WriteRawTag(209, 5);
+ output.WriteDouble(HeadBlower2AirFlow);
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public int CalculateSize() {
+ int size = 0;
+ if (Dancer1Angle != 0D) {
+ size += 1 + 8;
+ }
+ if (Dancer2Angle != 0D) {
+ size += 1 + 8;
+ }
+ if (Dancer3Angle != 0D) {
+ size += 1 + 8;
+ }
+ if (FeederMotorFrequency != 0D) {
+ size += 1 + 8;
+ }
+ if (DryerMotor != 0D) {
+ size += 1 + 8;
+ }
+ if (PollerMotor != 0D) {
+ size += 1 + 8;
+ }
+ if (WinderMotor != 0D) {
+ size += 1 + 8;
+ }
+ if (ScrewMotor != 0D) {
+ size += 1 + 8;
+ }
+ if (ThreadSpeed != 0D) {
+ size += 1 + 8;
+ }
+ if (MixerTemperature != 0D) {
+ size += 1 + 8;
+ }
+ if (HeadZone1Temperature != 0D) {
+ size += 1 + 8;
+ }
+ if (HeadZone2Temperature != 0D) {
+ size += 1 + 8;
+ }
+ if (HeadZone3Temperature != 0D) {
+ size += 1 + 8;
+ }
+ if (HeadAirFlow != 0D) {
+ size += 1 + 8;
+ }
+ if (FeederTension != 0D) {
+ size += 1 + 8;
+ }
+ if (PullerTension != 0D) {
+ size += 2 + 8;
+ }
+ if (DryerZone1Temperature != 0D) {
+ size += 2 + 8;
+ }
+ if (DryerZone2Temperature != 0D) {
+ size += 2 + 8;
+ }
+ if (DryerZone3Temperature != 0D) {
+ size += 2 + 8;
+ }
+ if (DryerAirFlow != 0D) {
+ size += 2 + 8;
+ }
+ if (WinderTension != 0D) {
+ size += 2 + 8;
+ }
+ size += dispensersMotorsFrequency_.CalculateSize(_repeated_dispensersMotorsFrequency_codec);
+ size += dispensersAngularEncoders_.CalculateSize(_repeated_dispensersAngularEncoders_codec);
+ size += dispensersLinearPositions_.CalculateSize(_repeated_dispensersLinearPositions_codec);
+ size += dispensersPressure_.CalculateSize(_repeated_dispensersPressure_codec);
+ if (FilterDeltaPressure != 0D) {
+ size += 2 + 8;
+ }
+ if (ChillerTemperature != 0D) {
+ size += 2 + 8;
+ }
+ if (Dispenser1MotorFrequency != 0D) {
+ size += 2 + 8;
+ }
+ if (Dispenser2MotorFrequency != 0D) {
+ size += 2 + 8;
+ }
+ if (Dispenser3MotorFrequency != 0D) {
+ size += 2 + 8;
+ }
+ if (Dispenser4MotorFrequency != 0D) {
+ size += 2 + 8;
+ }
+ if (Dispenser5MotorFrequency != 0D) {
+ size += 2 + 8;
+ }
+ if (Dispenser6MotorFrequency != 0D) {
+ size += 2 + 8;
+ }
+ if (Dispenser7MotorFrequency != 0D) {
+ size += 2 + 8;
+ }
+ if (Dispenser8MotorFrequency != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadZone4Temperature != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadZone5Temperature != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadZone6Temperature != 0D) {
+ size += 2 + 8;
+ }
+ if (BlowerVoltage != 0D) {
+ size += 2 + 8;
+ }
+ if (Dispenser1Pressure != 0D) {
+ size += 2 + 8;
+ }
+ if (Dispenser2Pressure != 0D) {
+ size += 2 + 8;
+ }
+ if (Dispenser3Pressure != 0D) {
+ size += 2 + 8;
+ }
+ if (Dispenser4Pressure != 0D) {
+ size += 2 + 8;
+ }
+ if (Dispenser5Pressure != 0D) {
+ size += 2 + 8;
+ }
+ if (Dispenser6Pressure != 0D) {
+ size += 2 + 8;
+ }
+ if (Dispenser7Pressure != 0D) {
+ size += 2 + 8;
+ }
+ if (Dispenser8Pressure != 0D) {
+ size += 2 + 8;
+ }
+ if (MidTank1Level != 0D) {
+ size += 2 + 8;
+ }
+ if (MidTank2Level != 0D) {
+ size += 2 + 8;
+ }
+ if (MidTank3Level != 0D) {
+ size += 2 + 8;
+ }
+ if (MidTank4Level != 0D) {
+ size += 2 + 8;
+ }
+ if (MidTank5Level != 0D) {
+ size += 2 + 8;
+ }
+ if (MidTank6Level != 0D) {
+ size += 2 + 8;
+ }
+ if (MidTank7Level != 0D) {
+ size += 2 + 8;
+ }
+ if (MidTank8Level != 0D) {
+ size += 2 + 8;
+ }
+ if (DrierZone1HeaterCurrent != 0D) {
+ size += 2 + 8;
+ }
+ if (DrierZone2HeaterCurrent != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadZone1HeaterCurrent != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadZone2HeaterCurrent != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadZone3HeaterCurrent != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadZone4HeaterCurrent != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadZone56HeaterCurrent != 0D) {
+ size += 2 + 8;
+ }
+ if (Mixer1HeaterCurrent != 0D) {
+ size += 2 + 8;
+ }
+ size += dispensersInkLevel_.CalculateSize(_repeated_dispensersInkLevel_codec);
+ size += midTanksInkLevel_.CalculateSize(_repeated_midTanksInkLevel_codec);
+ if (OverallTemperature != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadZone7HeaterCurrent != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadZone7Temperature != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadZone8HeaterCurrent != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadZone8Temperature != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadZone9HeaterCurrent != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadZone9Temperature != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadZone10HeaterCurrent != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadZone10Temperature != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadZone11HeaterCurrent != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadZone11Temperature != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadZone12HeaterCurrent != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadZone12Temperature != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadBlowerVoltage1 != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadBlowerVoltage2 != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadCoverHeater1Current != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadCoverHeater1Temperature != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadCoverHeater2Current != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadCoverHeater2Temperature != 0D) {
+ size += 2 + 8;
+ }
+ if (WHSBlower2Voltage != 0D) {
+ size += 2 + 8;
+ }
+ if (GasSensor != 0D) {
+ size += 2 + 8;
+ }
+ if (IncomingVoltage != 0D) {
+ size += 2 + 8;
+ }
+ if (WasteLevel != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadBlower1AirFlow != 0D) {
+ size += 2 + 8;
+ }
+ if (HeadBlower2AirFlow != 0D) {
+ size += 2 + 8;
+ }
+ return size;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void MergeFrom(InsightsMonitors other) {
+ if (other == null) {
+ return;
+ }
+ if (other.Dancer1Angle != 0D) {
+ Dancer1Angle = other.Dancer1Angle;
+ }
+ if (other.Dancer2Angle != 0D) {
+ Dancer2Angle = other.Dancer2Angle;
+ }
+ if (other.Dancer3Angle != 0D) {
+ Dancer3Angle = other.Dancer3Angle;
+ }
+ if (other.FeederMotorFrequency != 0D) {
+ FeederMotorFrequency = other.FeederMotorFrequency;
+ }
+ if (other.DryerMotor != 0D) {
+ DryerMotor = other.DryerMotor;
+ }
+ if (other.PollerMotor != 0D) {
+ PollerMotor = other.PollerMotor;
+ }
+ if (other.WinderMotor != 0D) {
+ WinderMotor = other.WinderMotor;
+ }
+ if (other.ScrewMotor != 0D) {
+ ScrewMotor = other.ScrewMotor;
+ }
+ if (other.ThreadSpeed != 0D) {
+ ThreadSpeed = other.ThreadSpeed;
+ }
+ if (other.MixerTemperature != 0D) {
+ MixerTemperature = other.MixerTemperature;
+ }
+ if (other.HeadZone1Temperature != 0D) {
+ HeadZone1Temperature = other.HeadZone1Temperature;
+ }
+ if (other.HeadZone2Temperature != 0D) {
+ HeadZone2Temperature = other.HeadZone2Temperature;
+ }
+ if (other.HeadZone3Temperature != 0D) {
+ HeadZone3Temperature = other.HeadZone3Temperature;
+ }
+ if (other.HeadAirFlow != 0D) {
+ HeadAirFlow = other.HeadAirFlow;
+ }
+ if (other.FeederTension != 0D) {
+ FeederTension = other.FeederTension;
+ }
+ if (other.PullerTension != 0D) {
+ PullerTension = other.PullerTension;
+ }
+ if (other.DryerZone1Temperature != 0D) {
+ DryerZone1Temperature = other.DryerZone1Temperature;
+ }
+ if (other.DryerZone2Temperature != 0D) {
+ DryerZone2Temperature = other.DryerZone2Temperature;
+ }
+ if (other.DryerZone3Temperature != 0D) {
+ DryerZone3Temperature = other.DryerZone3Temperature;
+ }
+ if (other.DryerAirFlow != 0D) {
+ DryerAirFlow = other.DryerAirFlow;
+ }
+ if (other.WinderTension != 0D) {
+ WinderTension = other.WinderTension;
+ }
+ dispensersMotorsFrequency_.Add(other.dispensersMotorsFrequency_);
+ dispensersAngularEncoders_.Add(other.dispensersAngularEncoders_);
+ dispensersLinearPositions_.Add(other.dispensersLinearPositions_);
+ dispensersPressure_.Add(other.dispensersPressure_);
+ if (other.FilterDeltaPressure != 0D) {
+ FilterDeltaPressure = other.FilterDeltaPressure;
+ }
+ if (other.ChillerTemperature != 0D) {
+ ChillerTemperature = other.ChillerTemperature;
+ }
+ if (other.Dispenser1MotorFrequency != 0D) {
+ Dispenser1MotorFrequency = other.Dispenser1MotorFrequency;
+ }
+ if (other.Dispenser2MotorFrequency != 0D) {
+ Dispenser2MotorFrequency = other.Dispenser2MotorFrequency;
+ }
+ if (other.Dispenser3MotorFrequency != 0D) {
+ Dispenser3MotorFrequency = other.Dispenser3MotorFrequency;
+ }
+ if (other.Dispenser4MotorFrequency != 0D) {
+ Dispenser4MotorFrequency = other.Dispenser4MotorFrequency;
+ }
+ if (other.Dispenser5MotorFrequency != 0D) {
+ Dispenser5MotorFrequency = other.Dispenser5MotorFrequency;
+ }
+ if (other.Dispenser6MotorFrequency != 0D) {
+ Dispenser6MotorFrequency = other.Dispenser6MotorFrequency;
+ }
+ if (other.Dispenser7MotorFrequency != 0D) {
+ Dispenser7MotorFrequency = other.Dispenser7MotorFrequency;
+ }
+ if (other.Dispenser8MotorFrequency != 0D) {
+ Dispenser8MotorFrequency = other.Dispenser8MotorFrequency;
+ }
+ if (other.HeadZone4Temperature != 0D) {
+ HeadZone4Temperature = other.HeadZone4Temperature;
+ }
+ if (other.HeadZone5Temperature != 0D) {
+ HeadZone5Temperature = other.HeadZone5Temperature;
+ }
+ if (other.HeadZone6Temperature != 0D) {
+ HeadZone6Temperature = other.HeadZone6Temperature;
+ }
+ if (other.BlowerVoltage != 0D) {
+ BlowerVoltage = other.BlowerVoltage;
+ }
+ if (other.Dispenser1Pressure != 0D) {
+ Dispenser1Pressure = other.Dispenser1Pressure;
+ }
+ if (other.Dispenser2Pressure != 0D) {
+ Dispenser2Pressure = other.Dispenser2Pressure;
+ }
+ if (other.Dispenser3Pressure != 0D) {
+ Dispenser3Pressure = other.Dispenser3Pressure;
+ }
+ if (other.Dispenser4Pressure != 0D) {
+ Dispenser4Pressure = other.Dispenser4Pressure;
+ }
+ if (other.Dispenser5Pressure != 0D) {
+ Dispenser5Pressure = other.Dispenser5Pressure;
+ }
+ if (other.Dispenser6Pressure != 0D) {
+ Dispenser6Pressure = other.Dispenser6Pressure;
+ }
+ if (other.Dispenser7Pressure != 0D) {
+ Dispenser7Pressure = other.Dispenser7Pressure;
+ }
+ if (other.Dispenser8Pressure != 0D) {
+ Dispenser8Pressure = other.Dispenser8Pressure;
+ }
+ if (other.MidTank1Level != 0D) {
+ MidTank1Level = other.MidTank1Level;
+ }
+ if (other.MidTank2Level != 0D) {
+ MidTank2Level = other.MidTank2Level;
+ }
+ if (other.MidTank3Level != 0D) {
+ MidTank3Level = other.MidTank3Level;
+ }
+ if (other.MidTank4Level != 0D) {
+ MidTank4Level = other.MidTank4Level;
+ }
+ if (other.MidTank5Level != 0D) {
+ MidTank5Level = other.MidTank5Level;
+ }
+ if (other.MidTank6Level != 0D) {
+ MidTank6Level = other.MidTank6Level;
+ }
+ if (other.MidTank7Level != 0D) {
+ MidTank7Level = other.MidTank7Level;
+ }
+ if (other.MidTank8Level != 0D) {
+ MidTank8Level = other.MidTank8Level;
+ }
+ if (other.DrierZone1HeaterCurrent != 0D) {
+ DrierZone1HeaterCurrent = other.DrierZone1HeaterCurrent;
+ }
+ if (other.DrierZone2HeaterCurrent != 0D) {
+ DrierZone2HeaterCurrent = other.DrierZone2HeaterCurrent;
+ }
+ if (other.HeadZone1HeaterCurrent != 0D) {
+ HeadZone1HeaterCurrent = other.HeadZone1HeaterCurrent;
+ }
+ if (other.HeadZone2HeaterCurrent != 0D) {
+ HeadZone2HeaterCurrent = other.HeadZone2HeaterCurrent;
+ }
+ if (other.HeadZone3HeaterCurrent != 0D) {
+ HeadZone3HeaterCurrent = other.HeadZone3HeaterCurrent;
+ }
+ if (other.HeadZone4HeaterCurrent != 0D) {
+ HeadZone4HeaterCurrent = other.HeadZone4HeaterCurrent;
+ }
+ if (other.HeadZone56HeaterCurrent != 0D) {
+ HeadZone56HeaterCurrent = other.HeadZone56HeaterCurrent;
+ }
+ if (other.Mixer1HeaterCurrent != 0D) {
+ Mixer1HeaterCurrent = other.Mixer1HeaterCurrent;
+ }
+ dispensersInkLevel_.Add(other.dispensersInkLevel_);
+ midTanksInkLevel_.Add(other.midTanksInkLevel_);
+ if (other.OverallTemperature != 0D) {
+ OverallTemperature = other.OverallTemperature;
+ }
+ if (other.HeadZone7HeaterCurrent != 0D) {
+ HeadZone7HeaterCurrent = other.HeadZone7HeaterCurrent;
+ }
+ if (other.HeadZone7Temperature != 0D) {
+ HeadZone7Temperature = other.HeadZone7Temperature;
+ }
+ if (other.HeadZone8HeaterCurrent != 0D) {
+ HeadZone8HeaterCurrent = other.HeadZone8HeaterCurrent;
+ }
+ if (other.HeadZone8Temperature != 0D) {
+ HeadZone8Temperature = other.HeadZone8Temperature;
+ }
+ if (other.HeadZone9HeaterCurrent != 0D) {
+ HeadZone9HeaterCurrent = other.HeadZone9HeaterCurrent;
+ }
+ if (other.HeadZone9Temperature != 0D) {
+ HeadZone9Temperature = other.HeadZone9Temperature;
+ }
+ if (other.HeadZone10HeaterCurrent != 0D) {
+ HeadZone10HeaterCurrent = other.HeadZone10HeaterCurrent;
+ }
+ if (other.HeadZone10Temperature != 0D) {
+ HeadZone10Temperature = other.HeadZone10Temperature;
+ }
+ if (other.HeadZone11HeaterCurrent != 0D) {
+ HeadZone11HeaterCurrent = other.HeadZone11HeaterCurrent;
+ }
+ if (other.HeadZone11Temperature != 0D) {
+ HeadZone11Temperature = other.HeadZone11Temperature;
+ }
+ if (other.HeadZone12HeaterCurrent != 0D) {
+ HeadZone12HeaterCurrent = other.HeadZone12HeaterCurrent;
+ }
+ if (other.HeadZone12Temperature != 0D) {
+ HeadZone12Temperature = other.HeadZone12Temperature;
+ }
+ if (other.HeadBlowerVoltage1 != 0D) {
+ HeadBlowerVoltage1 = other.HeadBlowerVoltage1;
+ }
+ if (other.HeadBlowerVoltage2 != 0D) {
+ HeadBlowerVoltage2 = other.HeadBlowerVoltage2;
+ }
+ if (other.HeadCoverHeater1Current != 0D) {
+ HeadCoverHeater1Current = other.HeadCoverHeater1Current;
+ }
+ if (other.HeadCoverHeater1Temperature != 0D) {
+ HeadCoverHeater1Temperature = other.HeadCoverHeater1Temperature;
+ }
+ if (other.HeadCoverHeater2Current != 0D) {
+ HeadCoverHeater2Current = other.HeadCoverHeater2Current;
+ }
+ if (other.HeadCoverHeater2Temperature != 0D) {
+ HeadCoverHeater2Temperature = other.HeadCoverHeater2Temperature;
+ }
+ if (other.WHSBlower2Voltage != 0D) {
+ WHSBlower2Voltage = other.WHSBlower2Voltage;
+ }
+ if (other.GasSensor != 0D) {
+ GasSensor = other.GasSensor;
+ }
+ if (other.IncomingVoltage != 0D) {
+ IncomingVoltage = other.IncomingVoltage;
+ }
+ if (other.WasteLevel != 0D) {
+ WasteLevel = other.WasteLevel;
+ }
+ if (other.HeadBlower1AirFlow != 0D) {
+ HeadBlower1AirFlow = other.HeadBlower1AirFlow;
+ }
+ if (other.HeadBlower2AirFlow != 0D) {
+ HeadBlower2AirFlow = other.HeadBlower2AirFlow;
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 9: {
+ Dancer1Angle = input.ReadDouble();
+ break;
+ }
+ case 17: {
+ Dancer2Angle = input.ReadDouble();
+ break;
+ }
+ case 25: {
+ Dancer3Angle = input.ReadDouble();
+ break;
+ }
+ case 33: {
+ FeederMotorFrequency = input.ReadDouble();
+ break;
+ }
+ case 41: {
+ DryerMotor = input.ReadDouble();
+ break;
+ }
+ case 49: {
+ PollerMotor = input.ReadDouble();
+ break;
+ }
+ case 57: {
+ WinderMotor = input.ReadDouble();
+ break;
+ }
+ case 65: {
+ ScrewMotor = input.ReadDouble();
+ break;
+ }
+ case 73: {
+ ThreadSpeed = input.ReadDouble();
+ break;
+ }
+ case 81: {
+ MixerTemperature = input.ReadDouble();
+ break;
+ }
+ case 89: {
+ HeadZone1Temperature = input.ReadDouble();
+ break;
+ }
+ case 97: {
+ HeadZone2Temperature = input.ReadDouble();
+ break;
+ }
+ case 105: {
+ HeadZone3Temperature = input.ReadDouble();
+ break;
+ }
+ case 113: {
+ HeadAirFlow = input.ReadDouble();
+ break;
+ }
+ case 121: {
+ FeederTension = input.ReadDouble();
+ break;
+ }
+ case 129: {
+ PullerTension = input.ReadDouble();
+ break;
+ }
+ case 137: {
+ DryerZone1Temperature = input.ReadDouble();
+ break;
+ }
+ case 145: {
+ DryerZone2Temperature = input.ReadDouble();
+ break;
+ }
+ case 153: {
+ DryerZone3Temperature = input.ReadDouble();
+ break;
+ }
+ case 161: {
+ DryerAirFlow = input.ReadDouble();
+ break;
+ }
+ case 169: {
+ WinderTension = input.ReadDouble();
+ break;
+ }
+ case 178:
+ case 177: {
+ dispensersMotorsFrequency_.AddEntriesFrom(input, _repeated_dispensersMotorsFrequency_codec);
+ break;
+ }
+ case 186:
+ case 185: {
+ dispensersAngularEncoders_.AddEntriesFrom(input, _repeated_dispensersAngularEncoders_codec);
+ break;
+ }
+ case 194:
+ case 193: {
+ dispensersLinearPositions_.AddEntriesFrom(input, _repeated_dispensersLinearPositions_codec);
+ break;
+ }
+ case 202:
+ case 201: {
+ dispensersPressure_.AddEntriesFrom(input, _repeated_dispensersPressure_codec);
+ break;
+ }
+ case 209: {
+ FilterDeltaPressure = input.ReadDouble();
+ break;
+ }
+ case 217: {
+ ChillerTemperature = input.ReadDouble();
+ break;
+ }
+ case 225: {
+ Dispenser1MotorFrequency = input.ReadDouble();
+ break;
+ }
+ case 233: {
+ Dispenser2MotorFrequency = input.ReadDouble();
+ break;
+ }
+ case 241: {
+ Dispenser3MotorFrequency = input.ReadDouble();
+ break;
+ }
+ case 249: {
+ Dispenser4MotorFrequency = input.ReadDouble();
+ break;
+ }
+ case 257: {
+ Dispenser5MotorFrequency = input.ReadDouble();
+ break;
+ }
+ case 265: {
+ Dispenser6MotorFrequency = input.ReadDouble();
+ break;
+ }
+ case 273: {
+ Dispenser7MotorFrequency = input.ReadDouble();
+ break;
+ }
+ case 281: {
+ Dispenser8MotorFrequency = input.ReadDouble();
+ break;
+ }
+ case 289: {
+ HeadZone4Temperature = input.ReadDouble();
+ break;
+ }
+ case 297: {
+ HeadZone5Temperature = input.ReadDouble();
+ break;
+ }
+ case 305: {
+ HeadZone6Temperature = input.ReadDouble();
+ break;
+ }
+ case 313: {
+ BlowerVoltage = input.ReadDouble();
+ break;
+ }
+ case 321: {
+ Dispenser1Pressure = input.ReadDouble();
+ break;
+ }
+ case 329: {
+ Dispenser2Pressure = input.ReadDouble();
+ break;
+ }
+ case 337: {
+ Dispenser3Pressure = input.ReadDouble();
+ break;
+ }
+ case 345: {
+ Dispenser4Pressure = input.ReadDouble();
+ break;
+ }
+ case 353: {
+ Dispenser5Pressure = input.ReadDouble();
+ break;
+ }
+ case 361: {
+ Dispenser6Pressure = input.ReadDouble();
+ break;
+ }
+ case 369: {
+ Dispenser7Pressure = input.ReadDouble();
+ break;
+ }
+ case 377: {
+ Dispenser8Pressure = input.ReadDouble();
+ break;
+ }
+ case 385: {
+ MidTank1Level = input.ReadDouble();
+ break;
+ }
+ case 393: {
+ MidTank2Level = input.ReadDouble();
+ break;
+ }
+ case 401: {
+ MidTank3Level = input.ReadDouble();
+ break;
+ }
+ case 409: {
+ MidTank4Level = input.ReadDouble();
+ break;
+ }
+ case 417: {
+ MidTank5Level = input.ReadDouble();
+ break;
+ }
+ case 425: {
+ MidTank6Level = input.ReadDouble();
+ break;
+ }
+ case 433: {
+ MidTank7Level = input.ReadDouble();
+ break;
+ }
+ case 441: {
+ MidTank8Level = input.ReadDouble();
+ break;
+ }
+ case 449: {
+ DrierZone1HeaterCurrent = input.ReadDouble();
+ break;
+ }
+ case 457: {
+ DrierZone2HeaterCurrent = input.ReadDouble();
+ break;
+ }
+ case 465: {
+ HeadZone1HeaterCurrent = input.ReadDouble();
+ break;
+ }
+ case 473: {
+ HeadZone2HeaterCurrent = input.ReadDouble();
+ break;
+ }
+ case 481: {
+ HeadZone3HeaterCurrent = input.ReadDouble();
+ break;
+ }
+ case 489: {
+ HeadZone4HeaterCurrent = input.ReadDouble();
+ break;
+ }
+ case 497: {
+ HeadZone56HeaterCurrent = input.ReadDouble();
+ break;
+ }
+ case 505: {
+ Mixer1HeaterCurrent = input.ReadDouble();
+ break;
+ }
+ case 514:
+ case 513: {
+ dispensersInkLevel_.AddEntriesFrom(input, _repeated_dispensersInkLevel_codec);
+ break;
+ }
+ case 522:
+ case 521: {
+ midTanksInkLevel_.AddEntriesFrom(input, _repeated_midTanksInkLevel_codec);
+ break;
+ }
+ case 529: {
+ OverallTemperature = input.ReadDouble();
+ break;
+ }
+ case 537: {
+ HeadZone7HeaterCurrent = input.ReadDouble();
+ break;
+ }
+ case 545: {
+ HeadZone7Temperature = input.ReadDouble();
+ break;
+ }
+ case 553: {
+ HeadZone8HeaterCurrent = input.ReadDouble();
+ break;
+ }
+ case 561: {
+ HeadZone8Temperature = input.ReadDouble();
+ break;
+ }
+ case 569: {
+ HeadZone9HeaterCurrent = input.ReadDouble();
+ break;
+ }
+ case 577: {
+ HeadZone9Temperature = input.ReadDouble();
+ break;
+ }
+ case 585: {
+ HeadZone10HeaterCurrent = input.ReadDouble();
+ break;
+ }
+ case 593: {
+ HeadZone10Temperature = input.ReadDouble();
+ break;
+ }
+ case 601: {
+ HeadZone11HeaterCurrent = input.ReadDouble();
+ break;
+ }
+ case 609: {
+ HeadZone11Temperature = input.ReadDouble();
+ break;
+ }
+ case 617: {
+ HeadZone12HeaterCurrent = input.ReadDouble();
+ break;
+ }
+ case 625: {
+ HeadZone12Temperature = input.ReadDouble();
+ break;
+ }
+ case 633: {
+ HeadBlowerVoltage1 = input.ReadDouble();
+ break;
+ }
+ case 641: {
+ HeadBlowerVoltage2 = input.ReadDouble();
+ break;
+ }
+ case 649: {
+ HeadCoverHeater1Current = input.ReadDouble();
+ break;
+ }
+ case 657: {
+ HeadCoverHeater1Temperature = input.ReadDouble();
+ break;
+ }
+ case 665: {
+ HeadCoverHeater2Current = input.ReadDouble();
+ break;
+ }
+ case 673: {
+ HeadCoverHeater2Temperature = input.ReadDouble();
+ break;
+ }
+ case 681: {
+ WHSBlower2Voltage = input.ReadDouble();
+ break;
+ }
+ case 689: {
+ GasSensor = input.ReadDouble();
+ break;
+ }
+ case 697: {
+ IncomingVoltage = input.ReadDouble();
+ break;
+ }
+ case 705: {
+ WasteLevel = input.ReadDouble();
+ break;
+ }
+ case 713: {
+ HeadBlower1AirFlow = input.ReadDouble();
+ break;
+ }
+ case 721: {
+ HeadBlower2AirFlow = input.ReadDouble();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/Software/Visual_Studio/Tango.PMR/Tango.PMR.csproj b/Software/Visual_Studio/Tango.PMR/Tango.PMR.csproj
index 66c84cb0d..4ad2e6612 100644
--- a/Software/Visual_Studio/Tango.PMR/Tango.PMR.csproj
+++ b/Software/Visual_Studio/Tango.PMR/Tango.PMR.csproj
@@ -216,6 +216,7 @@
<Compile Include="Hardware\SystemResetResponse.cs" />
<Compile Include="Hardware\UploadHardwareConfigurationRequest.cs" />
<Compile Include="Hardware\UploadHardwareConfigurationResponse.cs" />
+ <Compile Include="Insights\InsightsMonitors.cs" />
<Compile Include="Integration\ApplicationInformation.cs" />
<Compile Include="Integration\ColorProfileRequest.cs" />
<Compile Include="Integration\ColorProfileResponse.cs" />
@@ -464,7 +465,7 @@
</PropertyGroup>
<ProjectExtensions>
<VisualStudio>
- <UserProperties BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UseGlobalSettings="False" BuildVersion_StartDate="2000/1/1" />
+ <UserProperties BuildVersion_StartDate="2000/1/1" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" />
</VisualStudio>
</ProjectExtensions>
</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/Tango.SharedUI/Components/SelectedObject.cs b/Software/Visual_Studio/Tango.SharedUI/Components/SelectedObject.cs
index f91e93b5a..d85777292 100644
--- a/Software/Visual_Studio/Tango.SharedUI/Components/SelectedObject.cs
+++ b/Software/Visual_Studio/Tango.SharedUI/Components/SelectedObject.cs
@@ -7,18 +7,20 @@ using Tango.Core;
namespace Tango.SharedUI.Components
{
- public class SelectedObject<T> : ExtendedObject
+ public class SelectedObject : ExtendedObject
{
public event EventHandler IsSelectedChanged;
private bool _isSelected;
-
public bool IsSelected
{
get { return _isSelected; }
set { _isSelected = value; RaisePropertyChangedAuto(); IsSelectedChanged?.Invoke(this, new EventArgs()); }
}
+ }
+ public class SelectedObject<T> : SelectedObject
+ {
private T _data;
public T Data
diff --git a/Software/Visual_Studio/Tango.SharedUI/Controls/AllSelectedCheckboxList.cs b/Software/Visual_Studio/Tango.SharedUI/Controls/AllSelectedCheckboxList.cs
new file mode 100644
index 000000000..6e3cb862f
--- /dev/null
+++ b/Software/Visual_Studio/Tango.SharedUI/Controls/AllSelectedCheckboxList.cs
@@ -0,0 +1,144 @@
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using Tango.Core.Commands;
+//using System.Collections;
+using System.Linq;
+using System.Collections;
+
+namespace Tango.SharedUI.Controls
+{
+ public class AllSelectedCheckboxList : ListBox
+ {
+ #region Properties
+
+ private ItemsControl _itemsControl;
+
+ public ItemsControl ItemsControl
+ {
+ get { return _itemsControl; }
+ set { _itemsControl = value; }
+ }
+
+ public bool? AllSelected
+ {
+ get { return (bool?)GetValue(AllSelectedProperty); }
+ set
+ {
+ SetValue(AllSelectedProperty, value);
+ }
+ }
+
+ public static readonly DependencyProperty AllSelectedProperty =
+ DependencyProperty.Register("AllSelected", typeof(bool?), typeof(AllSelectedCheckboxList), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnAllSelectedChanged)));
+
+
+ private static void OnAllSelectedChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
+ {
+ AllSelectedCheckboxList l = o as AllSelectedCheckboxList;
+ var nv = e.NewValue;
+ l.AllSelectedChanged((bool?)nv);
+ }
+
+ public static DependencyProperty ClickCheckBoxCommandProperty = DependencyProperty.Register("ClickCheckBoxCommand", typeof(RelayCommand<object>), typeof(AllSelectedCheckboxList));
+ public RelayCommand<object> ClickCheckBoxCommand
+ {
+ get { return (RelayCommand<object>)GetValue(ClickCheckBoxCommandProperty); }
+ private set { SetValue(ClickCheckBoxCommandProperty, value); }
+ }
+
+ #endregion
+
+ #region "Constructors"
+
+ static AllSelectedCheckboxList()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(AllSelectedCheckboxList), new FrameworkPropertyMetadata(typeof(AllSelectedCheckboxList)));
+
+ }
+ public AllSelectedCheckboxList() : base()
+ {
+ ClickCheckBoxCommand = new RelayCommand<object>(ClickCheckBox);
+ }
+
+ /// <summary>
+ /// Clicks the CheckBox.Update Selection ListBoxitem.
+ /// </summary>
+ /// <param name="obj">The object.</param>
+ private void ClickCheckBox(object obj)
+ {
+ if (obj is ListBoxItem)
+ {
+ ListBoxItem lbItem = obj as ListBoxItem;
+ CheckBox checkBox = lbItem.FindVisualChildren<CheckBox>().FirstOrDefault();
+ if (checkBox != null)
+ {
+ bool? check = checkBox.IsChecked;
+ if (check != null)
+ {
+ lbItem.IsSelected = (bool)check;
+ }
+ }
+ }
+
+ if (SelectedItems.Count == 0)
+ {
+ AllSelected = false;
+ }
+ else if (Items.Count > 0 && SelectedItems.Count == Items.Count)
+ {
+ AllSelected = true;
+ }
+ else
+ {
+ AllSelected = null;
+ }
+ }
+
+ #endregion
+
+ #region Override
+
+ /// <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();
+ AllSelectedChanged(AllSelected);
+
+
+
+ }
+
+ protected override void OnSelectionChanged(SelectionChangedEventArgs e)
+ {
+ base.OnSelectionChanged(e);
+ foreach(var addItem in e.AddedItems.OfType<Components.SelectedObject>())
+ {
+ addItem.IsSelected = true;
+ }
+ foreach (var removeItem in e.RemovedItems.OfType<Components.SelectedObject>())
+ {
+ removeItem.IsSelected = false;
+ }
+ }
+
+ #endregion
+
+ private void AllSelectedChanged(bool? value)
+ {
+ if (value == null)
+ return;
+ SelectionMode = SelectionMode.Multiple;
+ if (value == true)
+ {
+ SelectAll();
+ }
+ else
+ {
+ UnselectAll();
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.SharedUI/Controls/PopupWithKeyboardFocus.cs b/Software/Visual_Studio/Tango.SharedUI/Controls/PopupWithKeyboardFocus.cs
deleted file mode 100644
index 9426b95cf..000000000
--- a/Software/Visual_Studio/Tango.SharedUI/Controls/PopupWithKeyboardFocus.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using MaterialDesignThemes.Wpf;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.InteropServices;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Controls.Primitives;
-using System.Windows.Input;
-using System.Windows.Interop;
-
-namespace Tango.SharedUI.Controls
-{
- public class PopupWithKeyboardFocus: ComboBoxPopup
- {
- [DllImport("user32.dll")]
- static extern IntPtr SetActiveWindow(IntPtr hWnd);
-
- static PopupWithKeyboardFocus()
- {
- EventManager.RegisterClassHandler(
- typeof(PopupWithKeyboardFocus),
- Popup.PreviewGotKeyboardFocusEvent,
- new KeyboardFocusChangedEventHandler(OnPreviewGotKeyboardFocus),
- true);
- }
-
- private static void OnPreviewGotKeyboardFocus(Object sender, KeyboardFocusChangedEventArgs e)
- {
- var textBox = e.NewFocus as TextBoxBase;
- if (textBox != null)
- {
- var hwndSource = PresentationSource.FromVisual(textBox) as HwndSource;
- if (hwndSource != null)
- {
- SetActiveWindow(hwndSource.Handle);
- }
- }
- }
- }
-}
diff --git a/Software/Visual_Studio/Tango.SharedUI/Controls/SearchComboBox.cs b/Software/Visual_Studio/Tango.SharedUI/Controls/SearchComboBox.cs
index f9d65bd2b..8fc6483e9 100644
--- a/Software/Visual_Studio/Tango.SharedUI/Controls/SearchComboBox.cs
+++ b/Software/Visual_Studio/Tango.SharedUI/Controls/SearchComboBox.cs
@@ -1,104 +1,63 @@
using System;
+using System.Collections;
using System.Collections.ObjectModel;
+using System.ComponentModel;
using System.Diagnostics;
+using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
+using System.Linq;
using System.Windows.Media;
using System.Windows.Threading;
namespace Tango.SharedUI.Controls
{
[TemplatePart(Name = SearchComboBox.PartEditor, Type = typeof(System.Windows.Controls.TextBox))]
- [TemplatePart(Name = SearchComboBox.PartPopup, Type = typeof(Popup))]
public class SearchComboBox : ComboBox
{
public const string PartEditor = "Search";
- public const string PartPopup = "PART_Popup";
- private int _savedSelectedIndex = -1;
- private bool _editorMouseLeaveFlag = false;
- #region Properties
-
- private TextBox _editor;
-
- public TextBox Editor
- {
- get { return _editor; }
- set { _editor = value; }
- }
-
-
- private Popup _popup;
-
- public Popup Popup
- {
- get { return _popup; }
- set { _popup = value; }
- }
-
- private DispatcherTimer _fetchTimer;
-
- public DispatcherTimer FetchTimer
- {
- get { return _fetchTimer; }
- set { _fetchTimer = value; }
- }
-
+ private TextBox _textBox;
+ private ListBox _listBox;
+ private ICollectionView _view;
- private string _searchText = "";
- /// <summary>
- /// Gets or sets the search text of TextBox.
- /// </summary>
- public string SearchText
+ #region Properties
+ public bool IsOpened
{
- get { return _searchText; }
- set
- {
- if(_searchText != value && value != null)
- {
- _searchText = value;
- }
-
- }
+ get { return (bool)GetValue(IsOpenedProperty); }
+ set { SetValue(IsOpenedProperty, value); }
}
+ public static readonly DependencyProperty IsOpenedProperty =
+ DependencyProperty.Register("IsOpened", typeof(bool), typeof(SearchComboBox), new PropertyMetadata(false, (d, e) => (d as SearchComboBox).OnIsOpenedChanged()));
- public ListCollectionView SearchItemsList
+ public String SearchProperty
{
- get { return (ListCollectionView)GetValue(SearchItemsListProperty); }
- set { SetValue(SearchItemsListProperty, value); }
+ get { return (String)GetValue(SearchPropertyProperty); }
+ set { SetValue(SearchPropertyProperty, value); }
}
- /// <summary>
- /// The search items list property for popup items list
- /// </summary>
- public static readonly DependencyProperty SearchItemsListProperty =
- DependencyProperty.Register("SearchItemsList", typeof(ListCollectionView), typeof(SearchComboBox), new PropertyMetadata(default(ObservableCollection<string>)));
-
+ public static readonly DependencyProperty SearchPropertyProperty =
+ DependencyProperty.Register("SearchProperty", typeof(String), typeof(SearchComboBox), new PropertyMetadata(null));
- public string SearchParam
+ public String SearchFilter
{
- get { return (string)GetValue(SearchParamProperty); }
- set { SetValue(SearchParamProperty, value); }
+ get { return (String)GetValue(SearchFilterProperty); }
+ set { SetValue(SearchFilterProperty, value); }
}
+ public static readonly DependencyProperty SearchFilterProperty =
+ DependencyProperty.Register("SearchFilter", typeof(String), typeof(SearchComboBox), new PropertyMetadata(null, (d, e) => (d as SearchComboBox).OnFilterChanged()));
- public static readonly DependencyProperty SearchParamProperty =
- DependencyProperty.Register("SearchParam", typeof(string), typeof(SearchComboBox), new FrameworkPropertyMetadata(""));
-
- public System.Collections.IList SourceItems
+ public IEnumerable ListItemsSource
{
- get { return (System.Collections.IList)GetValue(SourceItemsProperty); }
- set { SetValue(SourceItemsProperty, value); }
+ get { return (IEnumerable)GetValue(ListItemsSourceProperty); }
+ set { SetValue(ListItemsSourceProperty, value); }
}
-
- public static readonly DependencyProperty SourceItemsProperty =
- DependencyProperty.Register("SourceItems", typeof(System.Collections.IList), typeof(SearchComboBox), new PropertyMetadata(default(System.Collections.IList)));
-
+ public static readonly DependencyProperty ListItemsSourceProperty =
+ DependencyProperty.Register("ListItemsSource", typeof(IEnumerable), typeof(SearchComboBox), new PropertyMetadata(null));
#endregion
-
-
#region Constructors
static SearchComboBox()
@@ -106,203 +65,117 @@ namespace Tango.SharedUI.Controls
DefaultStyleKeyProperty.OverrideMetadata(typeof(SearchComboBox), new FrameworkPropertyMetadata(typeof(SearchComboBox)));
}
- public SearchComboBox()
- {
-
- }
-
#endregion //Constructors
-
- #region override
- protected override void OnLostMouseCapture(MouseEventArgs e)
- {
- if (Mouse.Captured == null)
- {
- if (e.OriginalSource == this)
- {
- //SetPopupState();
- }
- else if (IsDropDownOpen)
- {
- Mouse.Capture(this, CaptureMode.SubTree);
- }
- }
-
- base.OnLostMouseCapture(e);
- }
-
- /// <summary>
- /// Responds to a <see cref="T:System.Windows.Controls.ComboBox" /> selection change by raising a <see cref="E:System.Windows.Controls.Primitives.Selector.SelectionChanged" /> event.
- /// Change selection only on click on item
- /// </summary>
- /// <param name="e">Provides data for <see cref="T:System.Windows.Controls.SelectionChangedEventArgs" />.</param>
- protected override void OnSelectionChanged(SelectionChangedEventArgs e)
- {
- if (Editor == null || !Editor.IsKeyboardFocused || ( Editor.IsKeyboardFocused && _editorMouseLeaveFlag ) )
- {
- base.OnSelectionChanged(e);
- if (e.AddedItems.Count != 0 && SelectedIndex != this.SourceItems.IndexOf(e.AddedItems[0]))
- {
- SelectedValue = e.AddedItems[0];
- }
- }
- e.Handled = true;
- }
-
-
- #endregion
-
#region Initialization
-
- void InitSelectedList()
- {
- if (SearchItemsList == null)
- {
- SearchItemsList = new ListCollectionView(this.SourceItems);
- if (String.IsNullOrEmpty(SearchParam))
- SearchItemsList.Filter = null;
- else
- {
- SearchItemsList.Filter = (ob) =>
- {
- var prop = ob.GetType().GetProperty(SearchParam);
- if (prop == null)
- {
- return true;
- }
- string value = prop.GetValue(ob, null) as string;
- return value != null && (String.IsNullOrEmpty(SearchText) || value.ToLower().Contains(SearchText.ToLower()));
- };
- }
- Binding mbinding = new Binding("SearchItems");
- mbinding.Mode = BindingMode.Default;
- mbinding.Source = this;
- mbinding.Path = new PropertyPath("SearchItemsList");
-
- SetBinding(ComboBox.ItemsSourceProperty, mbinding);
- }
- }
+
/// <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();
-
- var binding1 = BindingOperations.GetBinding(this, ComboBox.ItemsSourceProperty);
- SetBinding(SearchComboBox.SourceItemsProperty, binding1);
- Popup = Template.FindName(PartPopup, this) as Popup;
-
- if (Popup != null)
+
+ _textBox = GetTemplateChild(PartEditor) as TextBox;
+ if(_textBox != null)
{
- Popup.StaysOpen = false;
- Popup.Opened += OnPopupOpened;
- Popup.Closed += OnPopupClosed;
-
+ _textBox.PreviewKeyDown += _textBox_KeyDown;
}
- Editor = Template.FindName(PartEditor, this) as TextBox;
- if(Editor != null)
+ _listBox = GetTemplateChild("list") as ListBox;
+ if(_listBox != null)
{
- Editor.TextChanged += OnEditorTextChanged;
- Editor.MouseLeave += Editor_MouseLeave;
- Editor.MouseEnter += Editor_MouseEnter;
+ _listBox.PreviewKeyDown += _listBox_PreviewKeyDown;
+ _listBox.PreviewMouseLeftButtonUp += _listBox_PreviewMouseLeftButtonUp;
}
}
#endregion
- #region EventHandlers
-
- private void Popup_KeyDown(object sender, KeyEventArgs e)
+ #region Event Handlers
+ private void _listBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
- if (Editor != null )
+ if (e.Key == Key.Return)
{
- Editor.Focus();
- Keyboard.Focus(Editor);
+ IsOpened = false;
+ SelectedItem = _listBox.SelectedItem;
}
}
- private void OnPopupOpened(object sender, EventArgs e)
+ private void _textBox_KeyDown(object sender, KeyEventArgs e)
{
- SearchText = "";
- InitSelectedList();
- if (Editor != null )
+ if (e.Key == Key.Down)
{
- Editor.Text = "";
- Editor.Focus();
- Editor.SelectionStart = 0;
- Keyboard.Focus(Editor);
+ _listBox.SelectedIndex = 0;
+ _listBox.Focus();
+ Keyboard.Focus(_listBox);
}
- _savedSelectedIndex = SelectedIndex;
}
- /// <summary>
- /// Called when [popup closed].
- /// Selection Index/Value will be set according to unfiltered whole list
- /// </summary>
- /// <param name="sender">The sender.</param>
- /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
- private void OnPopupClosed(object sender, EventArgs e)
+ private void _listBox_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
- if(SelectedIndex == -1 && _savedSelectedIndex >=0)// selection item was set to null for filtering but not selected, return to prev value
- {
- SearchText = "";
- SearchItemsList.Refresh();
- SelectedValue = SearchItemsList.GetItemAt(_savedSelectedIndex);
- }
- if(this.SourceItems.Count != SearchItemsList.Count)//selection was changed on filtered list - replace to real selection index
+ if (!(e.OriginalSource is Thumb))
{
- var selvalue = SelectedValue;
- SearchText = "";
- SearchItemsList.Refresh();
- SelectedValue = selvalue;
+ IsOpened = false;
+ SelectedItem = _listBox.SelectedItem;
}
- _savedSelectedIndex = -1;
}
- private void OnEditorTextChanged(object sender, TextChangedEventArgs e)
+ private async void OnIsOpenedChanged()
{
- if (FetchTimer == null)
+ if (IsOpened)
{
- FetchTimer = new DispatcherTimer();
- FetchTimer.Interval = TimeSpan.FromMilliseconds(100);
- FetchTimer.Tick += OnFetchTimerTick;
+ _listBox.SelectedItem = SelectedItem;
+ SearchFilter = "";
+ await Task.Delay(100);
+ _textBox.Focus();
+
+ Keyboard.Focus(_textBox);
}
-
- FetchTimer.IsEnabled = true;
- FetchTimer.Start();
- }
-
- private void Editor_MouseEnter(object sender, MouseEventArgs e)
- {
- _editorMouseLeaveFlag = false;
}
- private void Editor_MouseLeave(object sender, MouseEventArgs e)
- {
- _editorMouseLeaveFlag = true;
- }
-
- private void OnFetchTimerTick(object sender, EventArgs e)
+ private void OnFilterChanged()
{
- FetchTimer.IsEnabled = false;
- FetchTimer.Stop();
- SearchText = Editor.Text;
- OnTextChanged();
+ _view?.Refresh();
}
- public virtual void OnTextChanged()
+ #endregion
+ #region Override
+
+ protected override void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)
{
- if (SearchItemsList != null)
- {
- SearchItemsList.Refresh();
- }
- if(SearchItemsList.Count > 0 && SelectedIndex != -1)
+ base.OnItemsSourceChanged(oldValue, newValue);
+
+ if (ItemsSource != null)
{
- SelectedIndex = -1;// trick: all filtered items are displayed only with SelectedIndex = -1 , otherwise it is displayed 1 less
+ ListItemsSource = ItemsSource.Cast<Object>().ToList();
+
+ _view = CollectionViewSource.GetDefaultView(ListItemsSource);
+ _view.Filter = (x) =>
+ {
+ if (String.IsNullOrWhiteSpace(SearchFilter) || SearchFilter == null) return true;
+
+ if (x != null)
+ {
+ var prop = x.GetType().GetProperty(SearchProperty);
+
+ // var prop = x.GetType().GetProperty(SearchProperty, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly);
+ if (prop != null)
+ {
+ String propValue = prop.GetValue(x).ToString();
+ return propValue.ToLower().Contains(SearchFilter.ToLower());
+ }
+ }
+
+ return false;
+ };
}
}
+ protected override void OnSelectionChanged(SelectionChangedEventArgs e)
+ {
+ base.OnSelectionChanged(e);
+ }
+
#endregion
+
}
}
diff --git a/Software/Visual_Studio/Tango.SharedUI/Tango.SharedUI.csproj b/Software/Visual_Studio/Tango.SharedUI/Tango.SharedUI.csproj
index edbb21a77..af809d25c 100644
--- a/Software/Visual_Studio/Tango.SharedUI/Tango.SharedUI.csproj
+++ b/Software/Visual_Studio/Tango.SharedUI/Tango.SharedUI.csproj
@@ -72,6 +72,7 @@
<Compile Include="Components\SelectedObjectCollection.cs" />
<Compile Include="Components\TextController.cs" />
<Compile Include="Controls\AdornerContentPresenter.cs" />
+ <Compile Include="Controls\AllSelectedCheckboxList.cs" />
<Compile Include="Controls\DoubleClickDataGrid.cs" />
<Compile Include="Controls\FastTextBlock.cs" />
<Compile Include="Controls\HexagonControl.cs" />
@@ -86,7 +87,6 @@
<DependentUpon>MultiTransitionControl.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\NavigationControl.cs" />
- <Compile Include="Controls\PopupWithKeyboardFocus.cs" />
<Compile Include="Controls\SearchComboBox.cs" />
<Compile Include="Controls\SpannedUniformGrid.cs" />
<Compile Include="Controls\TableGrid.cs" />
diff --git a/Software/Visual_Studio/Tango.sln b/Software/Visual_Studio/Tango.sln
index c28ad8850..8a35deaf7 100644
--- a/Software/Visual_Studio/Tango.sln
+++ b/Software/Visual_Studio/Tango.sln
@@ -403,6 +403,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.FSE.Procedures", "FSE
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.FSE.Publisher.UI", "FSE\Tango.FSE.Publisher.UI\Tango.FSE.Publisher.UI.csproj", "{4C045668-9E5A-447A-A3B8-106C872C1039}"
EndProject
+Project("{7CF6DF6D-3B04-46F8-A40B-537D21BCA0B4}") = "Tango.FSE.Procedures.Documentation", "FSE\Modules\Tango.FSE.Procedures.Documentation\Tango.FSE.Procedures.Documentation.shfbproj", "{12EC97A5-C3C2-40CB-B658-EC4018B89269}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.Insights", "Tango.Insights\Tango.Insights.csproj", "{4A55C185-3F8D-41B0-8815-C15F6213A14A}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -3770,6 +3774,46 @@ Global
{4C045668-9E5A-447A-A3B8-106C872C1039}.Release|x64.Build.0 = Release|Any CPU
{4C045668-9E5A-447A-A3B8-106C872C1039}.Release|x86.ActiveCfg = Release|Any CPU
{4C045668-9E5A-447A-A3B8-106C872C1039}.Release|x86.Build.0 = Release|Any CPU
+ {12EC97A5-C3C2-40CB-B658-EC4018B89269}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {12EC97A5-C3C2-40CB-B658-EC4018B89269}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {12EC97A5-C3C2-40CB-B658-EC4018B89269}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {12EC97A5-C3C2-40CB-B658-EC4018B89269}.Debug|ARM.Build.0 = Debug|Any CPU
+ {12EC97A5-C3C2-40CB-B658-EC4018B89269}.Debug|ARM64.ActiveCfg = Debug|Any CPU
+ {12EC97A5-C3C2-40CB-B658-EC4018B89269}.Debug|ARM64.Build.0 = Debug|Any CPU
+ {12EC97A5-C3C2-40CB-B658-EC4018B89269}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {12EC97A5-C3C2-40CB-B658-EC4018B89269}.Debug|x64.Build.0 = Debug|Any CPU
+ {12EC97A5-C3C2-40CB-B658-EC4018B89269}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {12EC97A5-C3C2-40CB-B658-EC4018B89269}.Debug|x86.Build.0 = Debug|Any CPU
+ {12EC97A5-C3C2-40CB-B658-EC4018B89269}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {12EC97A5-C3C2-40CB-B658-EC4018B89269}.Release|Any CPU.Build.0 = Release|Any CPU
+ {12EC97A5-C3C2-40CB-B658-EC4018B89269}.Release|ARM.ActiveCfg = Release|Any CPU
+ {12EC97A5-C3C2-40CB-B658-EC4018B89269}.Release|ARM.Build.0 = Release|Any CPU
+ {12EC97A5-C3C2-40CB-B658-EC4018B89269}.Release|ARM64.ActiveCfg = Release|Any CPU
+ {12EC97A5-C3C2-40CB-B658-EC4018B89269}.Release|ARM64.Build.0 = Release|Any CPU
+ {12EC97A5-C3C2-40CB-B658-EC4018B89269}.Release|x64.ActiveCfg = Release|Any CPU
+ {12EC97A5-C3C2-40CB-B658-EC4018B89269}.Release|x64.Build.0 = Release|Any CPU
+ {12EC97A5-C3C2-40CB-B658-EC4018B89269}.Release|x86.ActiveCfg = Release|Any CPU
+ {12EC97A5-C3C2-40CB-B658-EC4018B89269}.Release|x86.Build.0 = Release|Any CPU
+ {4A55C185-3F8D-41B0-8815-C15F6213A14A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4A55C185-3F8D-41B0-8815-C15F6213A14A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4A55C185-3F8D-41B0-8815-C15F6213A14A}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {4A55C185-3F8D-41B0-8815-C15F6213A14A}.Debug|ARM.Build.0 = Debug|Any CPU
+ {4A55C185-3F8D-41B0-8815-C15F6213A14A}.Debug|ARM64.ActiveCfg = Debug|Any CPU
+ {4A55C185-3F8D-41B0-8815-C15F6213A14A}.Debug|ARM64.Build.0 = Debug|Any CPU
+ {4A55C185-3F8D-41B0-8815-C15F6213A14A}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4A55C185-3F8D-41B0-8815-C15F6213A14A}.Debug|x64.Build.0 = Debug|Any CPU
+ {4A55C185-3F8D-41B0-8815-C15F6213A14A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4A55C185-3F8D-41B0-8815-C15F6213A14A}.Debug|x86.Build.0 = Debug|Any CPU
+ {4A55C185-3F8D-41B0-8815-C15F6213A14A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4A55C185-3F8D-41B0-8815-C15F6213A14A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4A55C185-3F8D-41B0-8815-C15F6213A14A}.Release|ARM.ActiveCfg = Release|Any CPU
+ {4A55C185-3F8D-41B0-8815-C15F6213A14A}.Release|ARM.Build.0 = Release|Any CPU
+ {4A55C185-3F8D-41B0-8815-C15F6213A14A}.Release|ARM64.ActiveCfg = Release|Any CPU
+ {4A55C185-3F8D-41B0-8815-C15F6213A14A}.Release|ARM64.Build.0 = Release|Any CPU
+ {4A55C185-3F8D-41B0-8815-C15F6213A14A}.Release|x64.ActiveCfg = Release|Any CPU
+ {4A55C185-3F8D-41B0-8815-C15F6213A14A}.Release|x64.Build.0 = Release|Any CPU
+ {4A55C185-3F8D-41B0-8815-C15F6213A14A}.Release|x86.ActiveCfg = Release|Any CPU
+ {4A55C185-3F8D-41B0-8815-C15F6213A14A}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -3907,6 +3951,7 @@ Global
{982C6FAC-2864-484E-82AE-5A36658C4DB1} = {8336A702-9C49-4C9E-ADCC-1886A666D3BD}
{1754F846-4763-4000-807F-C7BFAA145DB2} = {4EE6DBA1-71BC-49E2-8DC7-266487E61050}
{4C045668-9E5A-447A-A3B8-106C872C1039} = {004337EB-0761-4D30-B9F5-AE6E1CFC6013}
+ {12EC97A5-C3C2-40CB-B658-EC4018B89269} = {4EE6DBA1-71BC-49E2-8DC7-266487E61050}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
BuildVersion_UseGlobalSettings = False
diff --git a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analysis/AnalyzerResultBase.cs b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analysis/AnalyzerResultBase.cs
index fcbda73e2..d3d217409 100644
--- a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analysis/AnalyzerResultBase.cs
+++ b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analysis/AnalyzerResultBase.cs
@@ -55,6 +55,7 @@ namespace Tango.DispenserAnalyzer.UI.Analysis
public bool IsShowPlotResult { get; set; }
public AnalyzerResultPlotData RangeToCountChart { get; set; }
public AnalyzerResultPlotData RangeToTimeChart { get; set; }
+ public bool BackgroundMode { get; set; }
public AnalyzerResultBase()
{
@@ -63,6 +64,7 @@ namespace Tango.DispenserAnalyzer.UI.Analysis
IsShowPlotResult = false;
RangeToCountChart = new AnalyzerResultPlotData();
RangeToTimeChart = new AnalyzerResultPlotData();
+ BackgroundMode = false;
}
}
}
diff --git a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analysis/IAnalyzer.cs b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analysis/IAnalyzer.cs
index 6a07e3a42..6d522da82 100644
--- a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analysis/IAnalyzer.cs
+++ b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analysis/IAnalyzer.cs
@@ -10,6 +10,6 @@ namespace Tango.DispenserAnalyzer.UI.Analysis
[Analyzer("INTERFACE")]
public interface IAnalyzer
{
- Task<List<IAnalyzerResult>> Process(List<DispenserSample> csvRows);
+ Task<List<IAnalyzerResult>> Process(List<DispenserSample> csvRows, bool backgroundMode);
}
}
diff --git a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analysis/IAnalyzerResult.cs b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analysis/IAnalyzerResult.cs
index 6b404d2a5..60f7fcb36 100644
--- a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analysis/IAnalyzerResult.cs
+++ b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analysis/IAnalyzerResult.cs
@@ -56,8 +56,10 @@ namespace Tango.DispenserAnalyzer.UI.Analysis
public interface IAnalyzerResult
{
AnalyzerResultValue Result { get; set; }
+
+ bool BackgroundMode { get; set; }
List<AnalysisPlotValue> PlotValues { get; set; }
- // ObservableCollection<DataPoint> Points { get; set; }
+
AnalyzerResultPlotData RangeToCountChart { get; set; }
AnalyzerResultPlotData RangeToTimeChart { get; set; }
}
diff --git a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/DynamicSealingAnalyzer.cs b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/DynamicSealingAnalyzer.cs
index 2cf38fdd6..8acd1651c 100644
--- a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/DynamicSealingAnalyzer.cs
+++ b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/DynamicSealingAnalyzer.cs
@@ -12,7 +12,7 @@ namespace Tango.DispenserAnalyzer.UI.Analyzers
[Analyzer("dynamic")]
public class DynamicSealingAnalzyer : IAnalyzer
{
- public Task<List<IAnalyzerResult>> Process(List<DispenserSample> csvRows)
+ public Task<List<IAnalyzerResult>> Process(List<DispenserSample> csvRows, bool backgroundMode)
{
return Task.Factory.StartNew<List<IAnalyzerResult>>(() =>
{
diff --git a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/FlowAnalyser.cs b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/FlowAnalyser.cs
index 41b7983a7..492fb3e6a 100644
--- a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/FlowAnalyser.cs
+++ b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/FlowAnalyser.cs
@@ -21,7 +21,7 @@ namespace Tango.DispenserAnalyzer.UI.Analyzers
public class FlowAnalyser : IAnalyzer
{
- public Task<List<IAnalyzerResult>> Process(List<DispenserSample> csvRows)
+ public Task<List<IAnalyzerResult>> Process(List<DispenserSample> csvRows, bool backgroundMode)
{
return Task.Factory.StartNew<List<IAnalyzerResult>>(() =>
{
@@ -74,11 +74,13 @@ namespace Tango.DispenserAnalyzer.UI.Analyzers
differenceMaxMinToLocationArr.Add(++location_index);
}
FlowAverageAnalyzerResult averageResult = new FlowAverageAnalyzerResult();
+ averageResult.BackgroundMode = backgroundMode;
averageResult.AverageValue = filteredValues.Average(t => t.Pressure);
averageResult.Result = (averageResult.AverageValue <= Settings.GetValueByName(AnalyzerSettingsEnum.AvgMaxValue) && averageResult.AverageValue >= Settings.GetValueByName(AnalyzerSettingsEnum.AvgMinValue)) ? AnalyzerResultValue.Passed : AnalyzerResultValue.Failed;
results.Add(averageResult);
FlowAnalyzerResult result = new FlowAnalyzerResult(++flowtestNumber);
+ result.BackgroundMode = backgroundMode;
result.AverageValue = averageResult.AverageValue;
result.SetLocalErrors(differenceMaxMin, differenceMaxMinToLocationArr);
results.Add(result);
@@ -86,6 +88,7 @@ namespace Tango.DispenserAnalyzer.UI.Analyzers
else//testing PBU
{
PrimingAnalyzerResult result = new PrimingAnalyzerResult();
+ result.BackgroundMode = backgroundMode;
int avgMinIndex = rangeTestValues.Select(x => x.Index).Min();
int avgMaxIndex = rangeTestValues.Select(x => x.Index).Max();
double totalsec = TimeSpan.FromMilliseconds((avgMaxIndex - avgMinIndex) * 100).TotalSeconds;
@@ -138,27 +141,34 @@ namespace Tango.DispenserAnalyzer.UI.Analyzers
{
// int count = differenceMaxMin.Where(x => x > 25 ).Count();
int max_key = FindMaxErrorObject(differenceMaxMin);
- var points = RangeToCountChart.Points;
- points.Clear();
- for (int i = 0; i <= max_key; i++)
+ if (!BackgroundMode)
{
- int val = differenceMaxMin.Count(x => x == i);
- if(val > 0 || points.Count > 0)
+ var points = RangeToCountChart.Points;
+ points.Clear();
+ for (int i = 0; i <= max_key; i++)
{
- points.Add(new DataPoint(i, val));
+ int val = differenceMaxMin.Count(x => x == i);
+ if(val > 0 || points.Count > 0)
+ {
+ points.Add(new DataPoint(i, val));
+ }
}
+ this.IsShowPlotResult = true;
+ RangeToCountChart.Title = $"Flow Range To Count {TestNumber}";
+ RangeToCountChart.UpdateData();
}
- this.IsShowPlotResult = true;
- RangeToCountChart.Title = $"Flow Range To Count {TestNumber}";
- RangeToCountChart.UpdateData();
var rangeToTimePoints = RangeToTimeChart.Points;
rangeToTimePoints.Clear();
for(int y = 0; y < differenceMaxMinToLocationArr.Count && y < differenceMaxMin.Count; y++)
{
rangeToTimePoints.Add(new DataPoint(differenceMaxMinToLocationArr.ElementAt(y), differenceMaxMin.ElementAt(y)));
}
- RangeToTimeChart.Title = $"Flow Time Location To Range {TestNumber}";
- RangeToTimeChart.UpdateData();
+ if (!BackgroundMode)
+ {
+ RangeToTimeChart.Title = $"Flow Time Location To Range {TestNumber}";
+ RangeToTimeChart.UpdateData();
+ }
+
string filename = FileHelper.GetFileToSaveFlowRangeToTimeData(TestNumber);
if(filename.IsNotNullOrEmpty() && rangeToTimePoints.Count > 0)
{
diff --git a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/PressureBuildUpAnalyser.cs b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/PressureBuildUpAnalyser.cs
index c4c5f6c65..79b643294 100644
--- a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/PressureBuildUpAnalyser.cs
+++ b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/PressureBuildUpAnalyser.cs
@@ -11,7 +11,7 @@ namespace Tango.DispenserAnalyzer.UI.Analyzers
[Analyzer("pressure build up")]
public class PressureBuildUpAnalyser : IAnalyzer
{
- public Task<List<IAnalyzerResult>> Process(List<DispenserSample> csvRows)
+ public Task<List<IAnalyzerResult>> Process(List<DispenserSample> csvRows, bool backgroundMode)
{
return Task.Factory.StartNew<List<IAnalyzerResult>>(() =>
{
diff --git a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/PrimingAnalyzer.cs b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/PrimingAnalyzer.cs
index 0a0e35371..cfd4a7b55 100644
--- a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/PrimingAnalyzer.cs
+++ b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/PrimingAnalyzer.cs
@@ -13,7 +13,7 @@ namespace Tango.DispenserAnalyzer.UI.Analyzers
[Analyzer("priming")]
public class PrimingAnalyzer : IAnalyzer
{
- public Task<List<IAnalyzerResult>> Process(List<DispenserSample> csvRows)
+ public Task<List<IAnalyzerResult>> Process(List<DispenserSample> csvRows, bool backgroundMode)
{
return Task.Factory.StartNew<List<IAnalyzerResult>>(() =>
{
diff --git a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/SealingAnalyzer.cs b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/SealingAnalyzer.cs
index e725ee25d..e1fe232c3 100644
--- a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/SealingAnalyzer.cs
+++ b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Analyzers/SealingAnalyzer.cs
@@ -12,7 +12,7 @@ namespace Tango.DispenserAnalyzer.UI.Analyzers
[Analyzer("sealtest")]
public class SealingAnalyzer : IAnalyzer
{
- public Task<List<IAnalyzerResult>> Process(List<DispenserSample> csvRows)
+ public Task<List<IAnalyzerResult>> Process(List<DispenserSample> csvRows, bool backgroundMode)
{
return Task.Factory.StartNew<List<IAnalyzerResult>>(() =>
{
diff --git a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/App.xaml.cs b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/App.xaml.cs
index c1876d806..d70c2e7a8 100644
--- a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/App.xaml.cs
+++ b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/App.xaml.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
+using System.Threading;
using System.Threading.Tasks;
using System.Windows;
@@ -16,9 +17,15 @@ namespace Tango.DispenserAnalyzer.UI
private void Application_Startup(object sender, StartupEventArgs e)
{
MainWindow wnd = new MainWindow();
- if (e.Args.Length >= 1)
- wnd.SetOpenFileFromArgument(e.Args[0]);
- wnd.Show();
+ if (e.Args.Length > 0)
+ {
+ wnd.GenerateResultsInBackground(e.Args);
+ //Current.Shutdown();
+ }
+ else
+ {
+ wnd.Show();
+ }
}
}
}
diff --git a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/MainWindow.xaml.cs b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/MainWindow.xaml.cs
index 43a573a7d..d328ea8a5 100644
--- a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/MainWindow.xaml.cs
+++ b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/MainWindow.xaml.cs
@@ -1,20 +1,8 @@
using OxyPlot;
using OxyPlot.Axes;
using System;
-using System.Collections.Generic;
-using System.IO;
-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.DispenserAnalyzer.UI.ViewModels;
namespace Tango.DispenserAnalyzer.UI
@@ -48,13 +36,17 @@ namespace Tango.DispenserAnalyzer.UI
ax.Maximum = ax.Minimum = Double.NaN;
}
- public void SetOpenFileFromArgument( string openFilePath)
+ public async void GenerateResultsInBackground( string[] filePathArr)
{
if(_vm != null)
{
- _vm.OpenFilePath = openFilePath;
- _vm.Generate();
+ for (int index = 0; index < filePathArr.Length; index++)
+ {
+ await _vm.GenerateInBackground(filePathArr[index]);
+ }
}
+ await Task.Delay(500);
+ Application.Current.Shutdown();
}
private void TextBlock_PreviewDrop(object sender, DragEventArgs e)
diff --git a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Tango.DispenserAnalyzer.UI.csproj b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Tango.DispenserAnalyzer.UI.csproj
index 3e85dc80b..b7db85ef8 100644
--- a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Tango.DispenserAnalyzer.UI.csproj
+++ b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/Tango.DispenserAnalyzer.UI.csproj
@@ -29,7 +29,7 @@
<ProductName>Dispenser Analyser</ProductName>
<PublisherName>Twine</PublisherName>
<OpenBrowserOnPublish>false</OpenBrowserOnPublish>
- <ApplicationRevision>3</ApplicationRevision>
+ <ApplicationRevision>4</ApplicationRevision>
<ApplicationVersion>2.1.1.%2a</ApplicationVersion>
<UseApplicationTrust>true</UseApplicationTrust>
<CreateDesktopShortcut>true</CreateDesktopShortcut>
diff --git a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/ViewModels/MainWindowVM.cs b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/ViewModels/MainWindowVM.cs
index 70034b6e7..38f8dee81 100644
--- a/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/ViewModels/MainWindowVM.cs
+++ b/Software/Visual_Studio/Utilities/Tango.DispenserAnalyzer.UI/ViewModels/MainWindowVM.cs
@@ -28,6 +28,8 @@ using PdfSharp;
using OxyPlot.Reporting;
using System.Threading;
using Tango.DispenserAnalyzer.UI.View;
+using Tango.Core.Helpers;
+using Tango.Documents;
namespace Tango.DispenserAnalyzer.UI.ViewModels
{
@@ -134,6 +136,7 @@ namespace Tango.DispenserAnalyzer.UI.ViewModels
get { return _isRunning; }
set { _isRunning = value; RaisePropertyChangedAuto(); }
}
+
private ObservableCollection<IAnalyzerResult> _analyzerResults;
public ObservableCollection<IAnalyzerResult> AnalyzerResults
{
@@ -233,13 +236,18 @@ namespace Tango.DispenserAnalyzer.UI.ViewModels
#endregion
#region Generate
+
public bool CanGenerate()
{
return (OpenFilePath!= null && OpenFilePath.Length != 0 && File.Exists(OpenFilePath));
}
+
+ /// <summary>
+ /// Generates all results.
+ /// </summary>
public async void Generate()
{
- if (false == File.Exists(OpenFilePath) || IsFileLocked(OpenFilePath) )
+ if (false == File.Exists(OpenFilePath) || IsFileLocked(OpenFilePath))
return;
ResetSettings();
@@ -248,17 +256,18 @@ namespace Tango.DispenserAnalyzer.UI.ViewModels
return;
IsRunning = true;
- AnalyzerAttribute attribute = (AnalyzerAttribute)analyzer.GetType().GetCustomAttributes(typeof(AnalyzerAttribute),true).FirstOrDefault();
-
+ AnalyzerAttribute attribute = (AnalyzerAttribute)analyzer.GetType().GetCustomAttributes(typeof(AnalyzerAttribute), true).FirstOrDefault();
+
TestName = attribute.Name;
- List<DispenserCsvRow> data = CsvFile.Read<DispenserCsvRow>(new CsvSource(OpenFilePath)).ToList();
+ List<DispenserCsvRow> data = CsvFile.Read<DispenserCsvRow>(new CsvSource(OpenFilePath)).ToList();
List<DispenserSample> samples = new List<DispenserSample>();
To = 0;
From = 0;
int index = 0;
int last_labelIndex = 0;
-
+
+
foreach (var item in data)
{
double pressure = 0;
@@ -269,6 +278,7 @@ namespace Tango.DispenserAnalyzer.UI.ViewModels
if (last_labelIndex == 0 || last_labelIndex < (index + 5))
{
last_labelIndex = index;
+
OxyPlot.Wpf.LineAnnotation _line = new OxyPlot.Wpf.LineAnnotation()
{
StrokeThickness = 1,
@@ -278,11 +288,13 @@ namespace Tango.DispenserAnalyzer.UI.ViewModels
X = index,
};
PlotControl.Annotations.Add(_line);
+
}
}
if (double.TryParse(item.Pressure, out pressure) || !String.IsNullOrWhiteSpace(item.Command))
{
- samples.Add(new DispenserSample(){
+ samples.Add(new DispenserSample()
+ {
Pressure = pressure,
Command = String.IsNullOrWhiteSpace(item.Command) ? null : item.Command,
Index = index
@@ -290,27 +302,84 @@ namespace Tango.DispenserAnalyzer.UI.ViewModels
index++;
}
}
- List<IAnalyzerResult> res = await analyzer.Process(samples);
+ List<IAnalyzerResult> res = await analyzer.Process(samples, false);
AnalyzerResults = new ObservableCollection<IAnalyzerResult>(res);
-
- samples.ForEach(x => { if (x.Pressure != 0.0)
+
+ samples.ForEach(x =>
+ {
+ if (x.Pressure != 0.0)
{ Points.Add(new DataPoint(x.Index, x.Pressure)); }
});
- _to = Points.Max(x=>x.Y);
- _from = TestName.Contains("sealtest") ? Points.FirstOrDefault(x=>x.X == 0).Y : Points.Min(x => x.Y);
+ _to = Points.Max(x => x.Y);
+ _from = TestName.Contains("sealtest") ? Points.FirstOrDefault(x => x.X == 0).Y : Points.Min(x => x.Y);
data.Clear();
_to += 100;
RaisePropertyChanged("To");
- if(_from != 0)
+ if (_from != 0)
_from -= 100;
RaisePropertyChanged("From");
XStep = (int)(Points.Count / 5);
-
+
IsRunning = false;
PlotControl.InvalidatePlot(true);
-
+
await PrintToXpsFile();
+
+ }
+
+ /// <summary>
+ /// Generates all results from command line and close application.
+ /// </summary>
+ public async Task GenerateInBackground(string openFilePath)
+ {
+ OpenFilePath = openFilePath;
+
+ if (false == File.Exists(OpenFilePath) || IsFileLocked(OpenFilePath))
+ return;
+
+ IAnalyzer analyzer = AnalysisService.GetAnalyzer(OpenFilePath);
+ if (analyzer == null)
+ return;
+
+ AnalyzerAttribute attribute = (AnalyzerAttribute)analyzer.GetType().GetCustomAttributes(typeof(AnalyzerAttribute), true).FirstOrDefault();
+
+ TestName = attribute.Name;
+ List<DispenserCsvRow> data = CsvFile.Read<DispenserCsvRow>(new CsvSource(OpenFilePath)).ToList();
+ List<DispenserSample> samples = new List<DispenserSample>();
+
+ int index = 0;
+ int last_labelIndex = 0;
+
+
+ foreach (var item in data)
+ {
+ double pressure = 0;
+ if (item.Label == "Label")
+ {
+ item.Pressure = "0";
+ item.Command = "Label";
+ if (last_labelIndex == 0 || last_labelIndex < (index + 5))
+ {
+ last_labelIndex = index;
+ }
+ }
+ if (double.TryParse(item.Pressure, out pressure) || !String.IsNullOrWhiteSpace(item.Command))
+ {
+ samples.Add(new DispenserSample()
+ {
+ Pressure = pressure,
+ Command = String.IsNullOrWhiteSpace(item.Command) ? null : item.Command,
+ Index = index
+ });
+ index++;
+ }
+ }
+
+ List<IAnalyzerResult> res = await analyzer.Process(samples, true);
+ AnalyzerResults = new ObservableCollection<IAnalyzerResult>(res);
+
+ await ExportResultsToTextFile();
}
#endregion
@@ -487,5 +556,54 @@ namespace Tango.DispenserAnalyzer.UI.ViewModels
}
#endregion
+
+ #region ExportToExel
+
+ public async Task ExportResultsToTextFile()
+ {
+ var resultFile = FileHelper.GetResultFilePath();
+ var dir = Path.GetDirectoryName(resultFile);
+ var name = Path.GetFileNameWithoutExtension(resultFile);
+ string fileNameWithoutExtension = Path.Combine(dir, name);
+ String sourceFile = String.Format($"{fileNameWithoutExtension}s.txt");
+ File.Delete(sourceFile);
+
+ await Task.Factory.StartNew(() =>
+ {
+ try
+ {
+ List<IAnalyzerResult> results = AnalyzerResults.ToList();
+
+ using (StreamWriter outputFile = new StreamWriter(sourceFile))
+ {
+ outputFile.WriteLine(String.Format($" {TestName.ToUpper()} RESULTS: "));
+ outputFile.WriteLine("");
+ outputFile.WriteLine("");
+ foreach (var res in results)
+ {
+ if (res.GetType().IsSubclassOf(typeof(AnalyzerResultBase)))
+ {
+ List<AnalyzerResultProperty> properties = (res as AnalyzerResultBase).Properties;
+ foreach (var prop in properties)
+ {
+ outputFile.WriteLine(String.Format($" {prop.Name} : {prop.Value}"));
+ }
+ string resV = String.Format($" RESULT = {res.Result.ToString()}");
+ outputFile.WriteLine(resV);
+ outputFile.WriteLine("");
+ }
+ }
+ outputFile.Flush();
+ }
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine(ex);
+ }
+ });
+
+ }
+ #endregion
+
}
}
diff --git a/Software/Visual_Studio/Utilities/Tango.PMRGenerator.CLI/Program.cs b/Software/Visual_Studio/Utilities/Tango.PMRGenerator.CLI/Program.cs
index c4c16b416..a86454e26 100644
--- a/Software/Visual_Studio/Utilities/Tango.PMRGenerator.CLI/Program.cs
+++ b/Software/Visual_Studio/Utilities/Tango.PMRGenerator.CLI/Program.cs
@@ -56,6 +56,7 @@ namespace Tango.PMRGenerator.CLI
GenerateColorLabLiquidTypes(db, pmrFolder);
GenerateDiagnosticsValueComponents(db, pmrFolder);
GenerateDiagnosticsMonitors(db, pmrFolder);
+ GenerateInsightsMonitors(db, pmrFolder);
GenerateEventTypes(db, pmrFolder);
GenerateInterfaceIOs(db, pmrFolder);
}
@@ -641,7 +642,7 @@ namespace Tango.PMRGenerator.CLI
private static void GenerateDiagnosticsMonitors(ObservablesContext db, String pmrFolder)
{
- Console.WriteLine("Generating Monitors...");
+ Console.WriteLine("Generating Diagnostics Monitors...");
ProtoMessageFile messageFile = new ProtoMessageFile();
messageFile.Name = "DiagnosticsMonitors";
@@ -674,6 +675,34 @@ namespace Tango.PMRGenerator.CLI
File.WriteAllText(Path.Combine(pmrFolder, "Diagnostics", messageFile.Name + ".proto"), messageString);
}
+ private static void GenerateInsightsMonitors(ObservablesContext db, string pmrFolder)
+ {
+ Console.WriteLine("Generating Insights Monitors...");
+
+ ProtoMessageFile messageFile = new ProtoMessageFile();
+ messageFile.Name = "InsightsMonitors";
+ messageFile.Package = "Tango.PMR.Insights";
+
+ foreach (var monitor in db.TechMonitors.ToList().OrderBy(x => x.Code))
+ {
+ var prop = new ProtoProperty();
+ prop.Name = monitor.Name.Replace(" ", "");
+ prop.Description = monitor.Description;
+ prop.Type = "double";
+
+ if (monitor.MultiChannel)
+ {
+ prop.Repeated = true;
+ }
+
+ messageFile.Properties.Add(prop);
+ }
+
+ String messageString = messageFile.GenerateCode();
+
+ File.WriteAllText(Path.Combine(pmrFolder, "Insights", messageFile.Name + ".proto"), messageString);
+ }
+
private static void GenerateInterfaceIOs(ObservablesContext db, String pmrFolder)
{
Console.WriteLine("Generating Interface IOs...");
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs
index 387430f89..b9dacfcf9 100644
--- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs
@@ -200,7 +200,7 @@ namespace Tango.MachineService.Controllers
String comments = String.Join(Environment.NewLine, versions.OrderBy(x => Version.Parse(x.Version)).Where(x => Version.Parse(x.Version) > currentVersion).Select(x => x.Comments));
- if (latestVersion != null && Version.Parse(latestVersion.Version) != currentVersion)
+ if (latestVersion != null && Version.Parse(latestVersion.Version) > currentVersion)
{
var manager = new BlobStorageManager();
var container = manager.GetContainer(MachineServiceConfig.FSE_VERSIONS_CONTAINER);
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs
index 10af2f725..22feb29c1 100644
--- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs
@@ -788,10 +788,13 @@ namespace Tango.MachineService.Controllers
return new LatestVersionResponse()
{
Version = "0.0.0.0",
+ FirmwareVersion = "0.0.0.0"
};
}
- response.Version = versions.OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault().Version;
+ var latestTangoVersion = versions.OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault();
+ response.Version = latestTangoVersion.Version;
+ response.FirmwareVersion = latestTangoVersion.FirmwareVersion;
}
return response;
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Properties/AssemblyInfo.cs b/Software/Visual_Studio/Web/Tango.MachineService/Properties/AssemblyInfo.cs
index 386a7c4b8..704da0c08 100644
--- a/Software/Visual_Studio/Web/Tango.MachineService/Properties/AssemblyInfo.cs
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Properties/AssemblyInfo.cs
@@ -24,4 +24,4 @@ using System.Runtime.InteropServices;
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
-[assembly: AssemblyVersion("3.0.0.0")]
+[assembly: AssemblyVersion("3.0.2.0")]