Skip to content

Commit a34a941

Browse files
committed
Add PropertyGrid to NeuropixelsV1 dialogs
1 parent fc39c95 commit a34a941

10 files changed

+256
-147
lines changed

OpenEphys.Onix1.Design/NeuropixelsV1ChannelConfigurationDialog.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public NeuropixelsV1ChannelConfigurationDialog(NeuropixelsV1ProbeConfiguration p
3737

3838
ReferenceContacts.AddRange(ReferenceContactsList);
3939

40-
ProbeConfiguration = new(probeConfiguration);
40+
ProbeConfiguration = probeConfiguration;
4141

4242
HighlightEnabledContacts();
4343
UpdateContactLabels();

OpenEphys.Onix1.Design/NeuropixelsV1Dialog.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@ public partial class NeuropixelsV1Dialog : Form
1414
/// Public <see cref="IConfigureNeuropixelsV1"/> interface that is manipulated by
1515
/// <see cref="NeuropixelsV1Dialog"/>.
1616
/// </summary>
17-
[Obsolete]
18-
public IConfigureNeuropixelsV1 ConfigureNode { get; set; }
17+
public IConfigureNeuropixelsV1 ConfigureNode
18+
{
19+
get => (IConfigureNeuropixelsV1)ProbeConfigurationDialog.propertyGrid.SelectedObject;
20+
set => ProbeConfigurationDialog.propertyGrid.SelectedObject = value;
21+
}
1922

2023
/// <summary>
2124
/// Initializes a new instance of <see cref="NeuropixelsV1Dialog"/>.
@@ -26,10 +29,8 @@ public NeuropixelsV1Dialog(IConfigureNeuropixelsV1 configureNode)
2629
InitializeComponent();
2730
Shown += FormShown;
2831

29-
ProbeConfigurationDialog = new(configureNode.ProbeConfiguration);
30-
ProbeConfigurationDialog
31-
.SetChildFormProperties(this)
32-
.AddDialogToPanel(panelProbe);
32+
ProbeConfigurationDialog = new(configureNode);
33+
ProbeConfigurationDialog.SetChildFormProperties(this).AddDialogToPanel(panelProbe);
3334

3435
this.AddMenuItemsFromDialogToFileOption(ProbeConfigurationDialog);
3536
}

OpenEphys.Onix1.Design/NeuropixelsV1Editor.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ public override bool EditComponent(ITypeDescriptorContext context, object compon
1818
var editorState = (IWorkflowEditorState)provider.GetService(typeof(IWorkflowEditorState));
1919
if (editorState != null && !editorState.WorkflowRunning && component is IConfigureNeuropixelsV1 configureNeuropixelsV1)
2020
{
21-
using var editorDialog = new NeuropixelsV1Dialog(configureNeuropixelsV1);
21+
var configuration = configureNeuropixelsV1.Clone();
22+
23+
using var editorDialog = new NeuropixelsV1Dialog(configuration);
2224

2325
if (editorDialog.ShowDialog() == DialogResult.OK)
2426
{

OpenEphys.Onix1.Design/NeuropixelsV1ProbeConfigurationDialog.Designer.cs

Lines changed: 105 additions & 48 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

OpenEphys.Onix1.Design/NeuropixelsV1ProbeConfigurationDialog.cs

Lines changed: 125 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using System;
2+
using System.ComponentModel;
23
using System.Drawing;
34
using System.IO;
45
using System.Linq;
6+
using System.Resources;
57
using System.Windows.Forms;
68

79
namespace OpenEphys.Onix1.Design
@@ -26,12 +28,26 @@ private enum ChannelPreset
2628
}
2729

2830
/// <summary>
29-
/// Gets or sets the probe configuration.
31+
/// Public <see cref="NeuropixelsV1ProbeConfiguration"/> interface that is manipulated by
32+
/// <see cref="NeuropixelsV1ProbeConfigurationDialog"/>.
3033
/// </summary>
34+
/// <remarks>
35+
/// When a <see cref="NeuropixelsV1ProbeConfiguration"/> is passed to
36+
/// <see cref="NeuropixelsV1ProbeConfigurationDialog"/>, it is copied and stored in this
37+
/// variable so that any modifications made to configuration settings can be easily reversed
38+
/// by not copying the new settings back to the original instance.
39+
/// </remarks>
3140
public NeuropixelsV1ProbeConfiguration ProbeConfiguration
3241
{
33-
get => ChannelConfiguration.ProbeConfiguration;
34-
set => ChannelConfiguration.ProbeConfiguration = value;
42+
get => ((IConfigureNeuropixelsV1)propertyGrid.SelectedObject).ProbeConfiguration;
43+
set => ((IConfigureNeuropixelsV1)propertyGrid.SelectedObject).ProbeConfiguration = value;
44+
}
45+
46+
[Obsolete]
47+
IConfigureNeuropixelsV1 ConfigureNode
48+
{
49+
get => (IConfigureNeuropixelsV1)propertyGrid.SelectedObject;
50+
set => propertyGrid.SelectedObject = value;
3551
}
3652

3753
/// <inheritdoc cref="NeuropixelsV1ProbeConfiguration.InvertPolarity"/>
@@ -45,56 +61,122 @@ public bool InvertPolarity
4561
/// <summary>
4662
/// Initializes a new instance of <see cref="NeuropixelsV1Dialog"/>.
4763
/// </summary>
48-
/// <param name="probeConfiguration">A <see cref="NeuropixelsV1ProbeConfiguration"/> object holding the current configuration settings.</param>
49-
public NeuropixelsV1ProbeConfigurationDialog(NeuropixelsV1ProbeConfiguration probeConfiguration)
64+
/// <param name="configureNode">Existing configuration node.</param>
65+
public NeuropixelsV1ProbeConfigurationDialog(IConfigureNeuropixelsV1 configureNode)
5066
{
5167
InitializeComponent();
5268
Shown += FormShown;
5369

54-
ChannelConfiguration = new(probeConfiguration);
55-
ChannelConfiguration
56-
.SetChildFormProperties(this)
57-
.AddDialogToPanel(panelProbe);
58-
70+
ChannelConfiguration = new(configureNode.ProbeConfiguration);
71+
ChannelConfiguration.SetChildFormProperties(this).AddDialogToPanel(panelProbe);
5972
this.AddMenuItemsFromDialogToFileOption(ChannelConfiguration);
6073

74+
panelProbe.Controls.Add(ChannelConfiguration);
75+
6176
ChannelConfiguration.OnZoom += UpdateTrackBarLocation;
6277
ChannelConfiguration.OnFileLoad += OnFileLoadEvent;
6378

64-
comboBoxApGain.DataSource = Enum.GetValues(typeof(NeuropixelsV1Gain));
65-
comboBoxApGain.SelectedItem = ProbeConfiguration.SpikeAmplifierGain;
66-
comboBoxApGain.SelectedIndexChanged += SpikeAmplifierGainIndexChanged;
79+
propertyGrid.SelectedObject = configureNode;
80+
bindingSource.DataSource = configureNode;
6781

68-
comboBoxLfpGain.DataSource = Enum.GetValues(typeof(NeuropixelsV1Gain));
69-
comboBoxLfpGain.SelectedItem = ProbeConfiguration.LfpAmplifierGain;
70-
comboBoxLfpGain.SelectedIndexChanged += LfpAmplifierGainIndexChanged;
82+
// NB: Needed to capture mouse scroll wheel updates
83+
void ForceBindingUpdate(object sender, EventArgs e)
84+
{
85+
var control = sender as Control;
7186

72-
comboBoxReference.DataSource = Enum.GetValues(typeof(NeuropixelsV1ReferenceSource));
73-
comboBoxReference.SelectedItem = ProbeConfiguration.Reference;
74-
comboBoxReference.SelectedIndexChanged += ReferenceIndexChanged;
87+
foreach (Binding binding in control.DataBindings)
88+
{
89+
binding.WriteValue();
90+
}
7591

76-
checkBoxSpikeFilter.Checked = ProbeConfiguration.SpikeFilter;
77-
checkBoxSpikeFilter.CheckedChanged += SpikeFilterIndexChanged;
92+
bindingSource.ResetCurrentItem();
93+
}
94+
;
7895

79-
checkBoxInvertPolarity.Checked = ProbeConfiguration.InvertPolarity;
80-
checkBoxInvertPolarity.CheckedChanged += InvertPolarityIndexChanged;
96+
comboBoxApGain.DataSource = Enum.GetValues(typeof(NeuropixelsV1Gain));
97+
comboBoxApGain.DataBindings.Add("SelectedItem",
98+
bindingSource,
99+
$"{nameof(configureNode.ProbeConfiguration)}.{nameof(configureNode.ProbeConfiguration.SpikeAmplifierGain)}",
100+
false,
101+
DataSourceUpdateMode.OnPropertyChanged);
102+
comboBoxApGain.SelectedIndexChanged += (sender, e) =>
103+
{
104+
ForceBindingUpdate(sender, e);
105+
CheckStatus();
106+
};
81107

82-
textBoxAdcCalibrationFile.Text = ProbeConfiguration.AdcCalibrationFileName;
83-
textBoxAdcCalibrationFile.TextChanged += (sender, e) => ProbeConfiguration.AdcCalibrationFileName = ((TextBox)sender).Text;
108+
comboBoxLfpGain.DataSource = Enum.GetValues(typeof(NeuropixelsV1Gain));
109+
comboBoxLfpGain.DataBindings.Add("SelectedItem",
110+
bindingSource,
111+
$"{nameof(configureNode.ProbeConfiguration)}.{nameof(configureNode.ProbeConfiguration.LfpAmplifierGain)}",
112+
false,
113+
DataSourceUpdateMode.OnPropertyChanged);
114+
comboBoxLfpGain.SelectedIndexChanged += (sender, e) =>
115+
{
116+
ForceBindingUpdate(sender, e);
117+
CheckStatus();
118+
};
84119

85-
textBoxGainCalibrationFile.Text = ProbeConfiguration.GainCalibrationFileName;
86-
textBoxGainCalibrationFile.TextChanged += (sender, e) => ProbeConfiguration.GainCalibrationFileName = ((TextBox)sender).Text;
120+
comboBoxReference.DataSource = Enum.GetValues(typeof(NeuropixelsV1ReferenceSource));
121+
comboBoxReference.DataBindings.Add("SelectedItem",
122+
bindingSource,
123+
$"{nameof(configureNode.ProbeConfiguration)}.{nameof(configureNode.ProbeConfiguration.Reference)}",
124+
false,
125+
DataSourceUpdateMode.OnPropertyChanged);
126+
comboBoxReference.SelectedIndexChanged += ForceBindingUpdate;
127+
128+
checkBoxSpikeFilter.DataBindings.Add("Checked",
129+
bindingSource,
130+
$"{nameof(configureNode.ProbeConfiguration)}.{nameof(configureNode.ProbeConfiguration.SpikeFilter)}",
131+
false,
132+
DataSourceUpdateMode.OnPropertyChanged);
133+
134+
checkBoxInvertPolarity.DataBindings.Add("Checked",
135+
bindingSource,
136+
$"{nameof(configureNode.ProbeConfiguration)}.{nameof(configureNode.ProbeConfiguration.InvertPolarity)}",
137+
false,
138+
DataSourceUpdateMode.OnPropertyChanged);
139+
140+
textBoxAdcCalibrationFile.DataBindings.Add("Text",
141+
bindingSource,
142+
$"{nameof(configureNode.ProbeConfiguration)}.{nameof(configureNode.ProbeConfiguration.AdcCalibrationFileName)}",
143+
false,
144+
DataSourceUpdateMode.OnPropertyChanged);
145+
textBoxAdcCalibrationFile.TextChanged += (sender, e) => CheckStatus();
146+
147+
textBoxGainCalibrationFile.DataBindings.Add("Text",
148+
bindingSource,
149+
$"{nameof(configureNode.ProbeConfiguration)}.{nameof(configureNode.ProbeConfiguration.GainCalibrationFileName)}",
150+
false,
151+
DataSourceUpdateMode.OnPropertyChanged);
152+
textBoxGainCalibrationFile.TextChanged += (sender, e) => CheckStatus();
87153

88154
comboBoxChannelPresets.DataSource = Enum.GetValues(typeof(ChannelPreset));
89155
CheckForExistingChannelPreset();
90-
comboBoxChannelPresets.SelectedIndexChanged += ChannelPresetIndexChanged;
156+
comboBoxChannelPresets.SelectedIndexChanged += (sender, e) =>
157+
{
158+
var channelPreset = ((ComboBox)sender).SelectedItem is ChannelPreset preset
159+
? preset
160+
: throw new InvalidEnumArgumentException($"Invalid channel preset value found.");
161+
162+
if (channelPreset != ChannelPreset.None)
163+
{
164+
SetChannelPreset(channelPreset);
165+
}
166+
};
91167

92168
CheckStatus();
93-
}
94169

95-
private void InvertPolarityIndexChanged(object sender, EventArgs e)
96-
{
97-
ProbeConfiguration.InvertPolarity = ((CheckBox)sender).Checked;
170+
bindingSource.ListChanged += (sender, eventArgs) => propertyGrid.Refresh();
171+
172+
tabControl1.SelectedIndexChanged += (sender, eventArgs) =>
173+
{
174+
if (tabControl1.SelectedTab == tabPageProperties)
175+
propertyGrid.Refresh();
176+
177+
else if (tabControl1.SelectedTab == tabPageConfiguration)
178+
bindingSource.ResetCurrentItem();
179+
};
98180
}
99181

100182
private void FormShown(object sender, EventArgs e)
@@ -111,75 +193,32 @@ private void FormShown(object sender, EventArgs e)
111193
ChannelConfiguration.ConnectResizeEventHandler();
112194
}
113195

114-
private void GainCalibrationFileTextChanged(object sender, EventArgs e)
115-
{
116-
CheckStatus();
117-
}
118-
119-
private void AdcCalibrationFileTextChanged(object sender, EventArgs e)
120-
{
121-
CheckStatus();
122-
}
123-
124-
private void SpikeAmplifierGainIndexChanged(object sender, EventArgs e)
125-
{
126-
ProbeConfiguration.SpikeAmplifierGain = (NeuropixelsV1Gain)((ComboBox)sender).SelectedItem;
127-
CheckStatus();
128-
}
129-
130-
private void LfpAmplifierGainIndexChanged(object sender, EventArgs e)
131-
{
132-
ProbeConfiguration.LfpAmplifierGain = (NeuropixelsV1Gain)((ComboBox)sender).SelectedItem;
133-
CheckStatus();
134-
}
135-
136-
private void ReferenceIndexChanged(object sender, EventArgs e)
137-
{
138-
ProbeConfiguration.Reference = (NeuropixelsV1ReferenceSource)((ComboBox)sender).SelectedItem;
139-
}
140-
141-
private void ChannelPresetIndexChanged(object sender, EventArgs e)
142-
{
143-
var channelPreset = (ChannelPreset)((ComboBox)sender).SelectedItem;
144-
145-
if (channelPreset != ChannelPreset.None)
146-
{
147-
SetChannelPreset(channelPreset);
148-
}
149-
}
150-
151-
private void SpikeFilterIndexChanged(object sender, EventArgs e)
152-
{
153-
ProbeConfiguration.SpikeFilter = ((CheckBox)sender).Checked;
154-
}
155-
156196
private void SetChannelPreset(ChannelPreset preset)
157197
{
158-
var probeConfiguration = ChannelConfiguration.ProbeConfiguration;
159-
var electrodes = NeuropixelsV1eProbeGroup.ToElectrodes(ChannelConfiguration.ProbeConfiguration.ProbeGroup);
198+
var electrodes = NeuropixelsV1eProbeGroup.ToElectrodes(ProbeConfiguration.ProbeGroup);
160199

161200
switch (preset)
162201
{
163202
case ChannelPreset.BankA:
164-
probeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.A).ToArray());
203+
ProbeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.A).ToArray());
165204
break;
166205

167206
case ChannelPreset.BankB:
168-
probeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.B).ToArray());
207+
ProbeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.B).ToArray());
169208
break;
170209

171210
case ChannelPreset.BankC:
172-
probeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.C ||
211+
ProbeConfiguration.SelectElectrodes(electrodes.Where(e => e.Bank == NeuropixelsV1Bank.C ||
173212
(e.Bank == NeuropixelsV1Bank.B && e.Index >= 576)).ToArray());
174213
break;
175214

176215
case ChannelPreset.SingleColumn:
177-
probeConfiguration.SelectElectrodes(electrodes.Where(e => (e.Index % 2 == 0 && e.Bank == NeuropixelsV1Bank.A) ||
216+
ProbeConfiguration.SelectElectrodes(electrodes.Where(e => (e.Index % 2 == 0 && e.Bank == NeuropixelsV1Bank.A) ||
178217
(e.Index % 2 == 1 && e.Bank == NeuropixelsV1Bank.B)).ToArray());
179218
break;
180219

181220
case ChannelPreset.Tetrodes:
182-
probeConfiguration.SelectElectrodes(electrodes.Where(e => (e.Index % 8 < 4 && e.Bank == NeuropixelsV1Bank.A) ||
221+
ProbeConfiguration.SelectElectrodes(electrodes.Where(e => (e.Index % 8 < 4 && e.Bank == NeuropixelsV1Bank.A) ||
183222
(e.Index % 8 > 3 && e.Bank == NeuropixelsV1Bank.B)).ToArray());
184223
break;
185224
}
@@ -192,7 +231,7 @@ private void SetChannelPreset(ChannelPreset preset)
192231

193232
private void CheckForExistingChannelPreset()
194233
{
195-
var channelMap = ChannelConfiguration.ProbeConfiguration.ChannelMap;
234+
var channelMap = ProbeConfiguration.ChannelMap;
196235

197236
if (channelMap.All(e => e.Bank == NeuropixelsV1Bank.A))
198237
{
@@ -225,7 +264,7 @@ private void CheckForExistingChannelPreset()
225264

226265
private void OnFileLoadEvent(object sender, EventArgs e)
227266
{
228-
// NB: Ensure that the newly loaded ProbeConfiguration in the ChannelConfigurationDialog is reflected here.
267+
// NB: Ensure that the newly loaded ProbeGroup in the ChannelConfigurationDialog is reflected here.
229268
ProbeConfiguration = ChannelConfiguration.ProbeConfiguration;
230269
CheckForExistingChannelPreset();
231270
}
@@ -320,6 +359,8 @@ private void CheckStatus()
320359
toolStripLabelGainCalibrationSn.Image = Properties.Resources.StatusBlockedImage;
321360
else
322361
toolStripLabelGainCalibrationSn.Image = Properties.Resources.StatusReadyImage;
362+
363+
propertyGrid.Refresh();
323364
}
324365

325366
private void ChooseGainCalibrationFile_Click(object sender, EventArgs e)
@@ -379,7 +420,7 @@ private void ViewAdcs_Click(object sender, EventArgs e)
379420
if (Adcs == null)
380421
return;
381422

382-
System.Resources.ResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(NeuropixelsV1Dialog));
423+
ResourceManager resources = new ComponentResourceManager(typeof(NeuropixelsV1Dialog));
383424

384425
var adcForm = new Form()
385426
{

OpenEphys.Onix1.Design/NeuropixelsV1ProbeConfigurationDialog.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@
156156
<metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
157157
<value>473, 17</value>
158158
</metadata>
159+
<metadata name="bindingSource.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
160+
<value>565, 5</value>
161+
</metadata>
159162
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
160163
<value>25</value>
161164
</metadata>

OpenEphys.Onix1.Design/NeuropixelsV1eHeadstageDialog.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public NeuropixelsV1eHeadstageDialog(ConfigureNeuropixelsV1e configureNeuropixel
3636

3737
this.AddMenuItemsFromDialogToFileOption(DialogNeuropixelsV1e, "NeuropixelsV1e");
3838

39-
DialogBno055 = new(new ConfigurePolledBno055(configureBno055));
39+
DialogBno055 = new(configureBno055);
4040

4141
DialogBno055.SetChildFormProperties(this).AddDialogToPanel(panelBno055);
4242
}

OpenEphys.Onix1.Design/NeuropixelsV1eHeadstageEditor.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ public override bool EditComponent(ITypeDescriptorContext context, object compon
1919

2020
if (editorState != null && !editorState.WorkflowRunning && component is ConfigureHeadstageNeuropixelsV1e configureHeadstage)
2121
{
22-
using var editorDialog = new NeuropixelsV1eHeadstageDialog(configureHeadstage.NeuropixelsV1e, configureHeadstage.Bno055);
22+
var configuration = configureHeadstage.Clone();
23+
24+
using var editorDialog = new NeuropixelsV1eHeadstageDialog(configuration.NeuropixelsV1e, configuration.Bno055);
2325

2426
if (editorDialog.ShowDialog() == DialogResult.OK)
2527
{
2628
DesignHelper.CopyProperties((ConfigurePolledBno055)editorDialog.DialogBno055.Device, configureHeadstage.Bno055, DesignHelper.PropertiesToIgnore);
2729

28-
configureHeadstage.NeuropixelsV1e.ProbeConfiguration = editorDialog.DialogNeuropixelsV1e.ProbeConfigurationDialog.ProbeConfiguration;
30+
DesignHelper.CopyProperties((ConfigureNeuropixelsV1e)editorDialog.DialogNeuropixelsV1e.ConfigureNode, configureHeadstage.NeuropixelsV1e, DesignHelper.PropertiesToIgnore);
2931

3032
return true;
3133
}

0 commit comments

Comments
 (0)