Realistic axis travel, wire-log fixes, compact layout

- Axes now span the hardware windows from RIOJoy's calibrator instead of
  the full 14-bit wire range: throttle rests at 0 and travels to -800
  (forward runs negative, matching the ratchet math), spring-loaded
  pedals rest at 0 and press to +500, stick covers +/-80 around center
  (new RioAxisRange in VRio.Core documents the provenance).
- Stick X sign flipped: RIOJoy maps negative samples to the high half of
  its output axis, so dragging right now lowers raw X.
- Removed the Rz mix bar - the real RIO has no such indicator.
- Wire log: newest entries on top with the bound trimming the oldest
  lines, and fixed the anchoring bug that let the box grow past the
  window edge (the panel got its height only after children snapshotted
  their anchors), which also hid the Clear log button.
- Tighter layout: axis readout sits under the status lines, encoder
  strip shrunk to fit the gauges, and the window sizes itself to the
  canvas + control strip.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-06 10:33:01 -05:00
co-authored by Claude Fable 5
parent 8e0a9e71bc
commit 1f0781f06a
5 changed files with 122 additions and 45 deletions
+27 -10
View File
@@ -90,7 +90,9 @@ internal sealed class MainForm : Form
public MainForm()
{
Text = "vRIO — Virtual RIO cockpit device";
ClientSize = new Size(1150, 800);
// Fit the window to its content: the cockpit canvas plus the 330px
// control strip, with just enough height for the strip's log area.
ClientSize = new Size(_canvas.Width + 332, Math.Max(_canvas.Height, 640));
MinimumSize = new Size(1000, 620);
StartPosition = FormStartPosition.CenterScreen;
@@ -113,11 +115,11 @@ internal sealed class MainForm : Form
// Device / service events arrive on worker threads; marshal to the UI.
_device.LampChanged += (_, _) => RunOnUi(_canvas.Invalidate);
_device.AxesChanged += () => RunOnUi(_canvas.Invalidate);
_device.Logged += line => RunOnUi(() => AppendLog(line));
_service.Logged += line => RunOnUi(() => AppendLog(line));
_device.Logged += line => RunOnUi(() => PrependLog(line));
_service.Logged += line => RunOnUi(() => PrependLog(line));
_service.ConnectionChanged += open => RunOnUi(() => OnConnectionChanged(open));
_service.HostHandshake += high => RunOnUi(() =>
AppendLog(high ? "Host raised DTR (board-reset handshake)" : "Host dropped DTR"));
PrependLog(high ? "Host raised DTR (board-reset handshake)" : "Host dropped DTR"));
_rescan.Click += (_, _) => RefreshPorts();
_openClose.Click += (_, _) => ToggleOpen();
@@ -155,7 +157,7 @@ internal sealed class MainForm : Form
RefreshPorts();
UpdateStatus();
AppendLog("vRIO ready. Open a COM port, then point RIOJoy at the other end of the pair.");
PrependLog("vRIO ready. Open a COM port, then point RIOJoy at the other end of the pair.");
}
private Panel BuildControlStrip()
@@ -164,6 +166,11 @@ internal sealed class MainForm : Form
{
Dock = DockStyle.Right,
Width = 330,
// Height must be set before the anchored children are added:
// Anchor offsets are captured against the parent's current size,
// and the 100px default would pin the log box's bottom far below
// the panel, making it grow past the window instead of scrolling.
Height = ClientSize.Height,
Padding = new Padding(8),
BorderStyle = BorderStyle.FixedSingle,
};
@@ -265,13 +272,23 @@ internal sealed class MainForm : Form
: "PORT CLOSED\nOpen a COM port to go live.";
}
private void AppendLog(string line)
private void PrependLog(string line)
{
// Bound the log so an all-day session doesn't grow without limit.
if (_logBox.TextLength > 120_000)
_logBox.Text = _logBox.Text.Substring(_logBox.TextLength - 60_000);
// Newest entry on top; older lines flow downward and eventually fall
// off the bounded end, so the visible top is always current.
string text = $"[{_clock.Elapsed.TotalSeconds,8:F2}s] {line}{Environment.NewLine}" + _logBox.Text;
_logBox.AppendText($"[{_clock.Elapsed.TotalSeconds,8:F2}s] {line}{Environment.NewLine}");
// Bound the log so an all-day session doesn't grow without limit;
// cut at a line boundary so the tail isn't half an entry.
if (text.Length > 120_000)
{
int cut = text.LastIndexOf(Environment.NewLine, 60_000, StringComparison.Ordinal);
text = text.Substring(0, cut < 0 ? 60_000 : cut + Environment.NewLine.Length);
}
_logBox.Text = text;
_logBox.SelectionStart = 0;
_logBox.ScrollToCaret();
}
private void RunOnUi(Action action)