|
3 | 3 | using System.Reactive.Disposables; |
4 | 4 | using System.Reactive.Subjects; |
5 | 5 | using System.Text; |
| 6 | +using System.Threading.Tasks; |
6 | 7 | using System.Xml.Serialization; |
7 | 8 | using Bonsai; |
8 | 9 | using Newtonsoft.Json; |
@@ -44,7 +45,7 @@ public ConfigureRhs2116Trigger(ConfigureRhs2116Trigger rhs2116Trigger) |
44 | 45 | DeviceAddress = rhs2116Trigger.DeviceAddress; |
45 | 46 | DeviceName = rhs2116Trigger.DeviceName; |
46 | 47 | TriggerSource = rhs2116Trigger.TriggerSource; |
47 | | - ProbeGroup = rhs2116Trigger.ProbeGroup; |
| 48 | + ProbeGroup = rhs2116Trigger.ProbeGroup.Clone(); |
48 | 49 | Armed = rhs2116Trigger.Armed; |
49 | 50 | StimulusSequence = new(rhs2116Trigger.StimulusSequence); |
50 | 51 | } |
@@ -76,13 +77,116 @@ public ConfigureRhs2116Trigger(ConfigureRhs2116Trigger rhs2116Trigger) |
76 | 77 | [Description("Specifies whether the trigger source is local or external.")] |
77 | 78 | public Rhs2116TriggerSource TriggerSource { get; set; } = Rhs2116TriggerSource.Local; |
78 | 79 |
|
| 80 | + Task<Rhs2116ProbeGroup> probeGroupTask = null; |
| 81 | + |
| 82 | + Rhs2116ProbeGroup probeGroup = null; |
| 83 | + |
79 | 84 | /// <summary> |
80 | 85 | /// Gets or sets the <see cref="Rhs2116ProbeGroup"/> channel configuration. |
81 | 86 | /// </summary> |
82 | 87 | [XmlIgnore] |
83 | 88 | [Category(ConfigurationCategory)] |
84 | 89 | [Description("Defines the channel configuration")] |
85 | | - public Rhs2116ProbeGroup ProbeGroup { get; set; } = new(); |
| 90 | + [Browsable(false)] |
| 91 | + [Externalizable(false)] |
| 92 | + public Rhs2116ProbeGroup ProbeGroup |
| 93 | + { |
| 94 | + get |
| 95 | + { |
| 96 | + if (probeGroup == null) |
| 97 | + { |
| 98 | + try |
| 99 | + { |
| 100 | + probeGroup = probeGroupTask?.Result ?? new Rhs2116ProbeGroup(); |
| 101 | + } |
| 102 | + catch (AggregateException ae) |
| 103 | + { |
| 104 | + probeGroup = new(); |
| 105 | + throw new InvalidOperationException($"There was an error loading the ProbeInterface file, loading the default configuration instead.\n\nError: {ae.InnerException.Message}", ae.InnerException); |
| 106 | + } |
| 107 | + } |
| 108 | + |
| 109 | + return probeGroup; |
| 110 | + } |
| 111 | + set => probeGroup = value; |
| 112 | + } |
| 113 | + |
| 114 | + string probeInterfaceFileName; |
| 115 | + |
| 116 | + /// <summary> |
| 117 | + /// Gets or sets the file path where the ProbeInterface configuration will be saved. |
| 118 | + /// </summary> |
| 119 | + /// <remarks> |
| 120 | + /// If left empty, the ProbeInterface configuration will not be saved. |
| 121 | + /// </remarks> |
| 122 | + [XmlIgnore] |
| 123 | + [Category(ConfigurationCategory)] |
| 124 | + [Description("File path to where the ProbeInterface file will be saved for this probe. If the file exists, it will be overwritten.")] |
| 125 | + [FileNameFilter(ProbeInterfaceHelper.ProbeInterfaceFileNameFilter)] |
| 126 | + [Editor("Bonsai.Design.SaveFileNameEditor, Bonsai.Design", DesignTypes.UITypeEditor)] |
| 127 | + public string ProbeInterfaceFileName |
| 128 | + { |
| 129 | + get => probeInterfaceFileName; |
| 130 | + set => probeInterfaceFileName = value; |
| 131 | + } |
| 132 | + |
| 133 | + /// <summary> |
| 134 | + /// Gets or sets the ProbeInterface file name, loading the given file asynchronously when set. |
| 135 | + /// </summary> |
| 136 | + [XmlIgnore] |
| 137 | + [Browsable(false)] |
| 138 | + [Externalizable(false)] |
| 139 | + public string ProbeInterfaceLoadFileName |
| 140 | + { |
| 141 | + get => probeInterfaceFileName; |
| 142 | + set |
| 143 | + { |
| 144 | + probeInterfaceFileName = value; |
| 145 | + probeGroupTask = Task.Run(() => |
| 146 | + { |
| 147 | + if (string.IsNullOrEmpty(probeInterfaceFileName)) |
| 148 | + return new Rhs2116ProbeGroup(); |
| 149 | + |
| 150 | + return ProbeInterfaceHelper.LoadExternalProbeInterfaceFile<Rhs2116ProbeGroup>(probeInterfaceFileName); |
| 151 | + }); |
| 152 | + } |
| 153 | + } |
| 154 | + |
| 155 | + /// <summary> |
| 156 | + /// Gets or sets a string defining the path to an external ProbeInterface JSON file. |
| 157 | + /// This variable is needed to properly save a workflow in Bonsai, but it is not |
| 158 | + /// directly accessible in the Bonsai editor. |
| 159 | + /// </summary> |
| 160 | + /// <remarks> |
| 161 | + /// [Obsolete]. Cannot tag this property with the Obsolete attribute due to https://github.com/dotnet/runtime/issues/100453 |
| 162 | + /// </remarks> |
| 163 | + [Browsable(false)] |
| 164 | + [Externalizable(false)] |
| 165 | + [XmlElement(nameof(ProbeInterfaceFileName))] |
| 166 | + public string ProbeInterfaceFileNameSerialize |
| 167 | + { |
| 168 | + get |
| 169 | + { |
| 170 | + if (string.IsNullOrEmpty(ProbeInterfaceFileName)) |
| 171 | + return ""; |
| 172 | + |
| 173 | + if (probeGroup != null) |
| 174 | + ProbeInterfaceHelper.SaveExternalProbeInterfaceFile(ProbeGroup, ProbeInterfaceFileName); |
| 175 | + |
| 176 | + return ProbeInterfaceFileName; |
| 177 | + } |
| 178 | + set => ProbeInterfaceLoadFileName = value; |
| 179 | + } |
| 180 | + |
| 181 | + /// <summary> |
| 182 | + /// Prevent the ProbeGroup property from being serialized. |
| 183 | + /// </summary> |
| 184 | + /// <returns>False</returns> |
| 185 | + [Obsolete] |
| 186 | + public bool ShouldSerializeProbeGroupString() |
| 187 | + { |
| 188 | + return false; |
| 189 | + } |
86 | 190 |
|
87 | 191 | /// <summary> |
88 | 192 | /// Gets or sets if trigger is armed. |
|
0 commit comments