import QtQuick import QtQuick.Controls import QtQuick.Layouts import ISC Dialog { id: root title: "Sensor Override" modal: true standardButtons: Dialog.NoButton width: 300 // Anchor to the top-left of the window instead of the default centered position. x: 24 y: 24 // called by WaferMapView's TapHandler property int sensorIndex: -1 property string sensorLabel: "" property real currentValue: 0.0 property bool hasOverride: streamController.overriddenSensors.indexOf(sensorIndex) >= 0 function openFor(index) { sensorIndex = index; var dot = streamController.sensorDots[index]; if (!dot) return; sensorLabel = dot.label !== undefined ? String(dot.label) : String(index + 1); currentValue = dot.value; valueField.text = ""; offsetField.text = ""; open(); } background: Rectangle { color: Theme.cardBackground radius: Theme.radiusLg border.color: Theme.cardBorder border.width: Theme.borderThin } ColumnLayout { anchors.fill: parent spacing: Theme.rightPaneGap // ── header ─────────────────────────────────────────────── RowLayout { Layout.fillWidth: true Label { text: "Sensor #" + (root.sensorIndex + 1) + (root.sensorLabel ? " (" + root.sensorLabel + ")" : "") color: Theme.headingColor font.bold: true font.pixelSize: Theme.fontSm Layout.fillWidth: true } Rectangle { visible: root.hasOverride width: overrideTag.implicitWidth + 12 height: overrideTag.implicitHeight + 6 radius: 4 color: Theme.statusWarningColor opacity: 0.85 Label { id: overrideTag anchors.centerIn: parent text: "OVERRIDE" color: Theme.statusBadgeText font.pixelSize: Theme.fontXs font.bold: true font.letterSpacing: 1 } } } Label { text: "Live: " + root.currentValue.toFixed(2) color: Theme.bodyColor font.pixelSize: Theme.fontSm } Rectangle { Layout.fillWidth: true height: 1 color: Theme.cardBorder } // ── replace field ───────────────────────────────────────── Label { text: "Replace with value" color: Theme.bodyColor font.pixelSize: Theme.fontXs } TextField { id: valueField Layout.fillWidth: true placeholderText: "100" inputMethodHints: Qt.ImhFormattedNumbersOnly color: Theme.fieldText placeholderTextColor: Theme.fieldPlaceholder selectedTextColor: Theme.fieldBackground selectionColor: Theme.fieldText background: Rectangle { radius: Theme.radiusXs color: Theme.fieldBackground border.width: valueField.activeFocus ? Theme.borderStrong : Theme.borderThin border.color: valueField.activeFocus ? Theme.fieldBorderFocus : Theme.fieldBorder Behavior on color { ColorAnimation { duration: Theme.durationFast } } Behavior on border.color { ColorAnimation { duration: Theme.durationFast } } } } // ── offset field ────────────────────────────────────────── Label { text: "Or add offset (± delta)" color: Theme.bodyColor font.pixelSize: Theme.fontXs } TextField { id: offsetField Layout.fillWidth: true placeholderText: "e.g. +0.5 or -0.5 (blank = skip)" inputMethodHints: Qt.ImhFormattedNumbersOnly color: Theme.fieldText placeholderTextColor: Theme.fieldPlaceholder selectedTextColor: Theme.fieldBackground selectionColor: Theme.fieldText background: Rectangle { radius: Theme.radiusXs color: Theme.fieldBackground border.width: offsetField.activeFocus ? Theme.borderStrong : Theme.borderThin border.color: offsetField.activeFocus ? Theme.fieldBorderFocus : Theme.fieldBorder Behavior on color { ColorAnimation { duration: Theme.durationFast } } Behavior on border.color { ColorAnimation { duration: Theme.durationFast } } } } Rectangle { Layout.fillWidth: true height: 1 color: Theme.cardBorder } // ── buttons ─────────────────────────────────────────────── RowLayout { Layout.fillWidth: true spacing: 8 Button { id: applyBtn text: "Apply" Layout.fillWidth: true hoverEnabled: true enabled: valueField.text !== "" || offsetField.text !== "" opacity: enabled ? 1.0 : 0.4 background: Rectangle { radius: Theme.radiusSm color: applyBtn.down ? Theme.buttonNeutralPressed : applyBtn.hovered ? Theme.buttonNeutralHover : Theme.buttonNeutralBackground border.width: Theme.borderThin border.color: Theme.fieldBorder } contentItem: Text { text: applyBtn.text color: Theme.buttonNeutralText horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter font.bold: true font.pixelSize: Theme.fontSm } onClicked: { if (valueField.text !== "") { var v = parseFloat(valueField.text); if (!isNaN(v)) streamController.replaceSensor(root.sensorIndex, v); } if (offsetField.text !== "") { var d = parseFloat(offsetField.text); if (!isNaN(d)) streamController.offsetSensor(root.sensorIndex, d); } root.close(); } } Button { id: clearBtn text: "Clear" Layout.fillWidth: true hoverEnabled: true enabled: root.hasOverride opacity: enabled ? 1.0 : 0.4 background: Rectangle { radius: Theme.radiusSm color: clearBtn.down ? Theme.buttonNeutralPressed : clearBtn.hovered ? Theme.buttonNeutralHover : Theme.buttonNeutralBackground border.width: Theme.borderThin border.color: Theme.fieldBorder } contentItem: Text { text: clearBtn.text color: Theme.buttonNeutralText horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter font.bold: true font.pixelSize: Theme.fontSm } onClicked: { streamController.clearSensorEdit(root.sensorIndex); root.close(); } } Button { id: cancelBtn text: "Cancel" hoverEnabled: true background: Rectangle { radius: Theme.radiusSm color: cancelBtn.down ? Theme.buttonNeutralPressed : cancelBtn.hovered ? Theme.buttonNeutralHover : Theme.buttonNeutralBackground border.width: Theme.borderThin border.color: Theme.fieldBorder } contentItem: Text { text: cancelBtn.text color: Theme.buttonNeutralText horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter font.bold: true font.pixelSize: Theme.fontSm } onClicked: root.close() } } } }