webui: add calibration editor to the V-Scale toolbar
Adds the Cal row (Scale / Offset / Unit / Reset) to #vscale-menu, its CSS, and the refreshVScaleMenu() / commitCal() logic that wires it to calTable and the hub via setCalibrationWS. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
0e9ec61226
commit
4e3a90b2c6
@@ -3514,6 +3514,32 @@ function escHtml(s) {
|
||||
════════════════════════════════════════════════════════════════ */
|
||||
let _vsMenuKey = null, _vsMenuPlotId = null;
|
||||
|
||||
// Re-read the calibration fields from calTable for the currently open toolbar.
|
||||
// Safe to call when the toolbar is closed.
|
||||
function refreshVScaleMenu() {
|
||||
if (!_vsMenuKey) return;
|
||||
const cal = calForKey(_vsMenuKey);
|
||||
const base = baseSigForKey(_vsMenuKey);
|
||||
const meta = findSignalMeta(_vsMenuKey);
|
||||
const n = meta ? numElements(meta) : 1;
|
||||
const lbl = document.getElementById('vscale-cal-lbl');
|
||||
lbl.textContent = n > 1 ? 'Cal (' + base + ', ' + n + ' elem)' : 'Cal (' + base + ')';
|
||||
const scaleEl = document.getElementById('vscale-cal-scale');
|
||||
const offsetEl = document.getElementById('vscale-cal-offset');
|
||||
const unitEl = document.getElementById('vscale-cal-unit');
|
||||
// Skip the field the user is currently typing in, so a hub broadcast does not
|
||||
// yank the caret out from under them.
|
||||
const focused = document.activeElement;
|
||||
if (focused !== scaleEl) scaleEl.value = cal.scale;
|
||||
if (focused !== offsetEl) offsetEl.value = cal.offset;
|
||||
if (focused !== unitEl) unitEl.value = cal.unit;
|
||||
[scaleEl, offsetEl, unitEl].forEach(el => el.classList.remove('cal-invalid'));
|
||||
const srcLabel = srcLabelForKey(_vsMenuKey);
|
||||
const usable = srcLabel !== '' && base !== '';
|
||||
[scaleEl, offsetEl, unitEl, document.getElementById('btn-cal-reset')]
|
||||
.forEach(el => { el.disabled = !usable; });
|
||||
}
|
||||
|
||||
function showVScaleMenu(key, plotId) {
|
||||
hideSignalMenu();
|
||||
// If the toolbar was open for a different plot, hide that bar first.
|
||||
@@ -3562,6 +3588,8 @@ function showVScaleMenu(key, plotId) {
|
||||
btn.classList.toggle('active', btn.dataset.type === (vs.digitalInMixed ? 'digital' : 'analog')));
|
||||
}
|
||||
|
||||
refreshVScaleMenu();
|
||||
|
||||
// Move the toolbar div into this plot's vscale bar.
|
||||
const bar = document.getElementById('vstb-' + plotId);
|
||||
if (bar) {
|
||||
@@ -3686,6 +3714,46 @@ function initVScaleMenu() {
|
||||
if (p) { createUPlot(p); p.needsRedraw = true; }
|
||||
});
|
||||
});
|
||||
// ── Calibration ───────────────────────────────────────────────────────
|
||||
// Commit the three fields as one entry. Validation mirrors the hub exactly
|
||||
// (Calib.normaliseCal); an invalid value marks the field and is not sent, so
|
||||
// the last accepted value stays in force.
|
||||
function commitCal() {
|
||||
if (!_vsMenuKey) return;
|
||||
const scaleEl = document.getElementById('vscale-cal-scale');
|
||||
const offsetEl = document.getElementById('vscale-cal-offset');
|
||||
const unitEl = document.getElementById('vscale-cal-unit');
|
||||
const source = srcLabelForKey(_vsMenuKey);
|
||||
const signal = baseSigForKey(_vsMenuKey);
|
||||
const entry = Calib.normaliseCal({
|
||||
source, signal,
|
||||
scale: parseFloat(scaleEl.value),
|
||||
offset: parseFloat(offsetEl.value),
|
||||
unit: unitEl.value,
|
||||
});
|
||||
const scaleBad = entry === null && !(isFinite(parseFloat(scaleEl.value)) && parseFloat(scaleEl.value) !== 0);
|
||||
scaleEl.classList.toggle('cal-invalid', scaleBad);
|
||||
offsetEl.classList.toggle('cal-invalid', entry === null && !isFinite(parseFloat(offsetEl.value)));
|
||||
if (entry === null) return;
|
||||
calTable.set(entry);
|
||||
setCalibrationWS(entry.source, entry.signal, entry.scale, entry.offset, entry.unit);
|
||||
applyCalibrationChanged();
|
||||
}
|
||||
|
||||
document.getElementById('vscale-cal-scale').addEventListener('change', commitCal);
|
||||
document.getElementById('vscale-cal-offset').addEventListener('change', commitCal);
|
||||
document.getElementById('vscale-cal-unit').addEventListener('change', commitCal);
|
||||
document.getElementById('btn-cal-reset').addEventListener('click', () => {
|
||||
if (!_vsMenuKey) return;
|
||||
const source = srcLabelForKey(_vsMenuKey);
|
||||
const signal = baseSigForKey(_vsMenuKey);
|
||||
if (!source || !signal) return;
|
||||
calTable.set({ source, signal, scale: 1, offset: 0, unit: '' });
|
||||
setCalibrationWS(source, signal, 1, 0, '');
|
||||
applyCalibrationChanged();
|
||||
refreshVScaleMenu();
|
||||
});
|
||||
|
||||
document.getElementById('btn-vscale-close').addEventListener('click', hideVScaleMenu);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user