diff --git a/MainForm.cs b/MainForm.cs index 026902a..955ece8 100644 --- a/MainForm.cs +++ b/MainForm.cs @@ -36,8 +36,11 @@ public class MainForm : Form readonly TrackBar _limitBarB; readonly Label _lblLimitA; readonly Label _lblLimitB; + readonly Label _lblLimitValA; + readonly Label _lblLimitValB; readonly CheckBox _chkScaleA; readonly CheckBox _chkScaleB; + readonly CheckBox _chkSwap; readonly Icon _iconNeutral; readonly Icon _iconActive; @@ -58,7 +61,7 @@ public class MainForm : Form _loopCts = new CancellationTokenSource(); Text = $"Substation {typeof(MainForm).Assembly.GetName().Version}"; - ClientSize = new Size(420, 410); + ClientSize = new Size(420, 425); FormBorderStyle = FormBorderStyle.FixedSingle; MaximizeBox = false; StartPosition = FormStartPosition.CenterScreen; @@ -96,11 +99,20 @@ public class MainForm : Form _btnConnect = new Button { Text = "Connect", - Location = new Point(296, 64), - Size = new Size(108, 24) + Location = new Point(236, 64), + Size = new Size(80, 24) }; _btnConnect.Click += OnConnect; + _chkSwap = new CheckBox + { + Text = "Swap", + Location = new Point(328, 66), + Size = new Size(56, 20), + Checked = false + }; + _chkSwap.CheckedChanged += OnSwapChanged; + _btnTest = new Button { Text = "Test", @@ -190,25 +202,33 @@ public class MainForm : Form _lblLimitA = new Label { - Text = "Lim A: 30", + Text = "Lim A", Location = new Point(16, 274), - Size = new Size(56, 20), + Size = new Size(40, 20), Font = new Font(Font.FontFamily, 9, FontStyle.Bold) }; _limitBarA = new TrackBar { - Location = new Point(72, 270), - Size = new Size(250, 45), + Location = new Point(60, 270), + Size = new Size(220, 45), Minimum = 0, Maximum = 200, TickFrequency = 50, Value = 30 }; _limitBarA.ValueChanged += OnLimitChanged; + FixTrackbarKeys(_limitBarA); + _lblLimitValA = new Label + { + Text = "30", + Location = new Point(286, 274), + Size = new Size(32, 20), + TextAlign = ContentAlignment.MiddleRight + }; _chkScaleA = new CheckBox { Text = "Scale", - Location = new Point(328, 274), + Location = new Point(320, 274), Size = new Size(76, 24), Checked = false }; @@ -216,32 +236,40 @@ public class MainForm : Form _lblLimitB = new Label { - Text = "Lim B: 30", - Location = new Point(16, 312), - Size = new Size(56, 20), + Text = "Lim B", + Location = new Point(16, 322), + Size = new Size(40, 20), Font = new Font(Font.FontFamily, 9, FontStyle.Bold) }; _limitBarB = new TrackBar { - Location = new Point(72, 308), - Size = new Size(250, 45), + Location = new Point(60, 318), + Size = new Size(220, 45), Minimum = 0, Maximum = 200, TickFrequency = 50, Value = 30 }; _limitBarB.ValueChanged += OnLimitChanged; + FixTrackbarKeys(_limitBarB); + _lblLimitValB = new Label + { + Text = "30", + Location = new Point(286, 322), + Size = new Size(32, 20), + TextAlign = ContentAlignment.MiddleRight + }; _chkScaleB = new CheckBox { Text = "Scale", - Location = new Point(328, 312), + Location = new Point(320, 322), Size = new Size(76, 24), Checked = false }; _chkScaleB.CheckedChanged += OnLimitChanged; OnLimitChanged(null, EventArgs.Empty); - Controls.AddRange(new Control[] { _lblBle, _lblWs, _lblDeviceName, _txtDeviceName, _btnConnect, _btnTest, _btnMusic, _btnStop, _lblTrack, _lblSendA, _heatA, _lblSendB, _heatB, _lblRecvA, _gaugeRecvA, _lblRecvB, _gaugeRecvB, _lblLimitA, _limitBarA, _chkScaleA, _lblLimitB, _limitBarB, _chkScaleB }); + Controls.AddRange(new Control[] { _lblBle, _lblWs, _lblDeviceName, _txtDeviceName, _btnConnect, _chkSwap, _btnTest, _btnMusic, _btnStop, _lblTrack, _lblSendA, _heatA, _lblSendB, _heatB, _lblRecvA, _gaugeRecvA, _lblRecvB, _gaugeRecvB, _lblLimitA, _limitBarA, _lblLimitValA, _chkScaleA, _lblLimitB, _limitBarB, _lblLimitValB, _chkScaleB }); // Tray icon — three cached variants: neutral=gray, active=gold, hot=red-orange _iconNeutral = CreateVoltageIcon(Color.Gray); @@ -401,6 +429,7 @@ public class MainForm : Form if (IsDisposed) return; BeginInvoke(() => { + if (_state.SwapChannels) (a, b) = (b, a); _gaugeRecvA.Value = Math.Clamp(a, 0, 200); _gaugeRecvB.Value = Math.Clamp(b, 0, 200); }); @@ -501,8 +530,13 @@ public class MainForm : Form var modeB = _chkScaleB.Checked ? LimitMode.Scale : LimitMode.Clamp; _state.SetLimitA(maxA, modeA); _state.SetLimitB(maxB, modeB); - _lblLimitA.Text = $"Lim A: {maxA}"; - _lblLimitB.Text = $"Lim B: {maxB}"; + _lblLimitValA.Text = $"{maxA}"; + _lblLimitValB.Text = $"{maxB}"; + } + + void OnSwapChanged(object? sender, EventArgs e) + { + _state.SwapChannels = _chkSwap.Checked; } string _musicFilePath = ""; @@ -620,6 +654,23 @@ public class MainForm : Form }; } + static void FixTrackbarKeys(TrackBar tb) + { + tb.KeyDown += (s, e) => + { + if (s is not TrackBar t) return; + int step = e.KeyCode == Keys.Up || e.KeyCode == Keys.Down ? 1 + : e.KeyCode == Keys.PageUp || e.KeyCode == Keys.PageDown ? 10 + : 0; + if (step == 0) return; + if (e.KeyCode is Keys.Up or Keys.PageUp or Keys.Home) + t.Value = Math.Min(t.Maximum, t.Value + (e.KeyCode == Keys.Home ? t.Maximum : step)); + else + t.Value = Math.Max(t.Minimum, t.Value - (e.KeyCode == Keys.End ? t.Maximum : step)); + e.Handled = true; + }; + } + static Icon CreateVoltageIcon(Color boltColor) { const int sz = 32; diff --git a/State.cs b/State.cs index b70eaac..aa675f5 100644 --- a/State.cs +++ b/State.cs @@ -25,6 +25,7 @@ public class State public int MaxB = 200; public LimitMode LimitModeA = LimitMode.Clamp; public LimitMode LimitModeB = LimitMode.Clamp; + public bool SwapChannels; public void SetLimitA(int max, LimitMode mode) { @@ -129,6 +130,19 @@ public class State LastIntensityA = hasA ? (intA[0] + intA[1] + intA[2] + intA[3]) / 4 : 0; LastIntensityB = hasB ? (intB[0] + intB[1] + intB[2] + intB[3]) / 4 : 0; + if (SwapChannels) + { + (valA, valB) = (valB, valA); + (modeA, modeB) = (modeB, modeA); + (freqA, freqB) = (freqB, freqA); + (intA, intB) = (intB, intA); + (LastSentA, LastSentB) = (LastSentB, LastSentA); + (LastFreqA, LastFreqB) = (LastFreqB, LastFreqA); + (LastIntA, LastIntB) = (LastIntB, LastIntA); + (LastActiveA, LastActiveB) = (LastActiveB, LastActiveA); + (LastIntensityA, LastIntensityB) = (LastIntensityB, LastIntensityA); + } + return (modeA, valA, modeB, valB, freqA, intA, freqB, intB); } }