/*SPDX-FileCopyrightText: Joshua Goins <josh@redstrate.com>SPDX-License-Identifier: GPL-2.0-or-later*/import QtQuickimport QtQuick.Windowimport QtQuick.Layoutsimport QtQuick.Shapesimport QtQuick.Controls as QQC2import org.kde.kirigami as Kirigamiimport org.kde.plasma.tablet.kcm as TabletQQC2.ApplicationWindow {id: rootrequired property Tablet.TabletEvents tabletEventsproperty bool toolDown: falseminimumWidth: 400minimumHeight: 200title: i18ndc("kcm_tablet", "@title", "Tablet Tester")function insideDrawingSquare(local_x: real, local_y: real): bool {return local_x >= 0 &&local_y >= 0 &&local_x <= drawingSquare.width &&local_y <= drawingSquare.height;}function scrollLogToBottom(): void {logScrollView.QQC2.ScrollBar.vertical.position = 1.0 - logScrollView.QQC2.ScrollBar.vertical.size;}Connections {target: tabletEventsfunction onToolDown(hardware_serial_hi: int, hardware_serial_lo: int, window_x: real, window_y: real): void {const local = drawingSquare.mapFromItem(container, window_x, window_y);if (insideDrawingSquare(local.x, local.y)) {root.toolDown = true;penPath.path = [];penLogText.append(i18ndc("kcm_tablet", "A tablet stylus was pressed onto the surface X=[x position] Y=[y position]", "Stylus press X=%1 Y=%2", local.x, local.y));scrollLogToBottom();}}function onToolUp(hardware_serial_hi: int, hardware_serial_lo: int, window_x: real, window_y: real): void {const local = drawingSquare.mapFromItem(container, window_x, window_y);root.toolDown = false;penLogText.append(i18ndc("kcm_tablet", "A tablet stylus has 'released' or was lifted from the surface X=[x position] Y=[y position]", "Stylus release X=%1 Y=%2", local.x, local.y));scrollLogToBottom();}function onToolMotion(hardware_serial_hi: int, hardware_serial_lo: int, window_x: real, window_y: real, pressure: real, tilt_x: real, tilt_y: real): void {const local = drawingSquare.mapFromItem(container, window_x, window_y);if (insideDrawingSquare(local.x, local.y) && root.toolDown) {penPath.path.push(local);penLogText.append(i18ndc("kcm_tablet", "A tablet stylus has moved over the surface X=[x position] Y=[y position] P=[pressure] TX=[tilt x] TY=[tilt y]", "Stylus move X=%1 Y=%2 P=%3% TX=%4 TY=%5", local.x, local.y, pressure * 100.0, tilt_x, tilt_y));scrollLogToBottom();}}function onPadButtonReceived(path: string, button: int, pressed: bool): void {if (pressed) {penLogText.append(i18ndc("kcm_tablet", "A tablet pad's button has been pressed B=[the button number]", "Pad button press B=%1", button));} else {penLogText.append(i18ndc("kcm_tablet", "A tablet pad's button has been released B=[the button number]", "Pad button release B=%1", button));}scrollLogToBottom();}function onDialDelta(value120: int): void {penLogText.append(i18ndc("kcm_tablet", "A tablet pad's dial has moved, V120 here refers to 'Value 120' which is a technical term that should be kept as is", "Pad dial moved V120=%1", value120));scrollLogToBottom();}}Item {id: containeranchors.fill: parentRowLayout {id: layoutspacing: Kirigami.Units.largeSpacinganchors {fill: parentmargins: Kirigami.Units.largeSpacing}Rectangle {id: drawingSquareimplicitWidth: 220implicitHeight: 220color: Kirigami.Theme.backgroundColorclip: trueLayout.fillHeight: trueLayout.preferredWidth: Math.round(root.width / 3)Kirigami.Theme.inherit: falseKirigami.Theme.colorSet: Kirigami.Theme.View// Vertical linesRepeater {id: verticalRepeatermodel: 8delegate: Shape {id: verticalShapeanchors.fill: parentKirigami.Theme.inherit: falseKirigami.Theme.colorSet: Kirigami.Theme.WindowShapePath {strokeWidth: 1strokeColor: Kirigami.Theme.backgroundColorfillColor: "transparent"startX: line.xPathLine {id: linex: index * (verticalShape.width / verticalRepeater.count)y: verticalShape.height}}}}// Horizontal linesRepeater {id: horizontalRepeatermodel: 8delegate: Shape {id: horizontalShapeanchors.fill: parentKirigami.Theme.inherit: falseKirigami.Theme.colorSet: Kirigami.Theme.WindowShapePath {strokeWidth: 1strokeColor: Kirigami.Theme.backgroundColorfillColor: "transparent"startY: line.yPathLine {id: linex: horizontalShape.widthy: index * (horizontalShape.height / horizontalRepeater.count) - 1}}}}// Pen PathShape {anchors.fill: parentShapePath {strokeWidth: 2strokeColor: Kirigami.Theme.highlightColorfillColor: "transparent"PathPolyline {id: penPath}}}// This is here just to catch events from going to the window, nothing moreMouseArea {anchors.fill: parent}}ColumnLayout {Layout.fillWidth: trueLayout.fillHeight: trueLayout.preferredHeight: drawingSquare.implicitHeightspacing: Kirigami.Units.largeSpacingQQC2.ScrollView {id: logScrollViewLayout.fillWidth: trueLayout.fillHeight: trueQQC2.TextArea {id: penLogTextreadOnly: truewrapMode: TextEdit.WrapComponent.onCompleted: loadLegend()function loadLegend(): void {text = i18ndc("kcm_tablet", "The tablet tester legend which is shown on start-up", "## Legend:\n# X, Y - event coordinate\n# P - pressure\n# TX,TY - tilt\n");}}}QQC2.Button {text: i18ndc("kcm_tablet", "Clear the tablet tester event log", "Clear")icon.name: "edit-clear-symbolic"onClicked: {penLogText.clear();penLogText.loadLegend();penPath.path = [];}Layout.fillWidth: true}}}}// FIXME: For some reason, setting this declaratively ends up with a broken window until it's resized.Component.onCompleted: width = 730}