/*SPDX-FileCopyrightText: 2019 Roman Gilg <subdiff@gmail.com>SPDX-FileCopyrightText: 2012 Dan Vratil <dvratil@redhat.com>SPDX-FileCopyrightText: 2024 Joshua Goins <joshua.gons@kdab.com>SPDX-License-Identifier: GPL-2.0-or-later*/import QtQuickimport QtQuick.Layoutsimport QtQuick.Controls as QQC2import QtQuick.Shapesimport org.kde.kirigami as Kirigamiimport org.kde.plasma.tablet.kcm as KCMimport org.kde.kcmutilsimport org.kde.kquickcontrolsItem {id: outputAreaViewrequired property KCM.InputDevice devicerequired property int moderequired property bool displayVisiblereadonly property bool stretchToFill: mode === 0readonly property bool fitAspectRatio: mode === 1readonly property bool mapToPortion: mode === 2function setOutputAreaMode(mode: int): void {if (mode === 0) {// If fit to screen, use the whole size of the displayoutputAreaItem.x = 0outputAreaItem.y = 0outputAreaItem.width = Qt.binding(() => outputItem.outputWidth);outputAreaItem.height = Qt.binding(() => outputItem.outputHeight);} else {let outputArea = Qt.rect(0, 0, 1, 1);if (mode === 1) {outputArea = Qt.rect(0, 0, 1, outputItem.aspectRatio / tabletItem.aspectRatio);}outputAreaItem.x = Qt.binding(() => outputArea.x * outputItem.outputWidth);outputAreaItem.y = Qt.binding(() => outputArea.y * outputItem.outputHeight);outputAreaItem.width = Qt.binding(() => tabletSizeHandle.x);outputAreaItem.height = Qt.binding(() => tabletSizeHandle.y);tabletSizeHandle.x = Qt.binding(() => outputArea.width * outputItem.outputWidth);tabletSizeHandle.y = Qt.binding(() => outputArea.height * outputItem.outputHeight);if (mode === 2) {keepAspectRatio.checked = outputAreaItem.aspectRatio === (outputAreaView.device.size.width / outputAreaView.device.size.height)}}}function setOutputArea(outputArea: rect): void {outputAreaItem.x = Qt.binding(() => outputArea.x * outputItem.outputWidth);outputAreaItem.y = Qt.binding(() => outputArea.y * outputItem.outputHeight);outputAreaItem.width = Qt.binding(() => tabletSizeHandle.x);outputAreaItem.height = Qt.binding(() => tabletSizeHandle.y);tabletSizeHandle.x = Qt.binding(() => outputArea.width * outputItem.outputWidth);tabletSizeHandle.y = Qt.binding(() => outputArea.height * outputItem.outputHeight);}function setInputArea(inputArea: rect): void {inputAreaItem.x = Qt.binding(() => inputArea.x * tabletItem.outputWidth);inputAreaItem.y = Qt.binding(() => inputArea.y * tabletItem.outputHeight);inputAreaItem.width = Qt.binding(() => inputAreaSizeHandle.x);inputAreaItem.height = Qt.binding(() => inputAreaSizeHandle.y);inputAreaSizeHandle.x = Qt.binding(() => inputArea.width * tabletItem.outputWidth);inputAreaSizeHandle.y = Qt.binding(() => inputArea.height * tabletItem.outputHeight);}readonly property rect outputAreaSetting: Qt.rect(outputAreaItem.x / outputItem.outputWidth,outputAreaItem.y / outputItem.outputHeight,outputAreaItem.width / outputItem.outputWidth,outputAreaItem.height / outputItem.outputHeight)readonly property rect inputAreaSetting: Qt.rect(inputAreaItem.x / tabletItem.outputWidth,inputAreaItem.y / tabletItem.outputHeight,inputAreaItem.width / tabletItem.outputWidth,inputAreaItem.height / tabletItem.outputHeight)property bool outputChanged: falseproperty bool inputChanged: falseonOutputAreaSettingChanged: {if (outputAreaView.device && outputChanged) {outputAreaView.device.outputArea = outputAreaSetting;}}onInputAreaSettingChanged: {if (outputAreaView.device && inputChanged) {outputAreaView.device.inputArea = inputAreaSetting;}}enabled: outputAreaView.deviceimplicitHeight: outputItem.height + tabletItem.height + Kirigami.Units.largeSpacing + (keepAspectRatio.visible ? keepAspectRatio.implicitHeight + keepAspectRatio.anchors.topMargin : 0) + Kirigami.Units.gridUnit * 3QQC2.CheckBox {id: keepAspectRatioanchors {top: parent.tophorizontalCenter: parent.horizontalCenter}text: i18ndc("kcm_tablet", "@option:check", "Lock aspect ratio")visible: outputAreaView.mapToPortionchecked: true}Output {id: outputItemanchors {top: keepAspectRatio.bottomtopMargin: Kirigami.Units.largeSpacing}// Resolution of the selected displayscreenSize: outputsModel.data(outputsModel.index(outputsCombo.currentIndex, 0), Qt.UserRole + 2)visible: outputAreaView.displayVisiblewidth: parent.widthheight: visible ? implicitHeight : 0Rectangle {id: outputAreaItemcolor: Kirigami.Theme.activeBackgroundColoropacity: 0.8readonly property real desiredAspectRatio: outputAreaView.stretchToFill ? outputItem.aspectRatio : outputAreaView.device.size.width / outputAreaView.device.size.heightreadonly property real aspectRatio: width / heightwidth: tabletSizeHandle.xheight: tabletSizeHandle.yColumnLayout {anchors.centerIn: parentvisible: outputAreaView.mapToPortionKirigami.Icon {source: "transform-move-symbolic"Layout.alignment: Qt.AlignHCenter}QQC2.Label {text: i18ndc("kcm_tablet", "tablet area position - size", "%1,%2 - %3×%4", String(Math.floor(outputAreaView.outputAreaSetting.x * outputItem.screenSize.width)), String(Math.floor(outputAreaView.outputAreaSetting.y * outputItem.screenSize.height)), String(Math.floor(outputAreaView.outputAreaSetting.width * outputItem.screenSize.width)), String(Math.floor(outputAreaView.outputAreaSetting.height * outputItem.screenSize.height)))textFormat: Text.PlainTextLayout.fillWidth: true}}border {width: 1color: Kirigami.Theme.highlightColor}DragHandler {cursorShape: Qt.ClosedHandCursortarget: parentenabled: outputAreaView.mapToPortiononActiveChanged: { outputAreaView.outputChanged = true }xAxis.minimum: 0xAxis.maximum: outputItem.outputWidth - outputAreaItem.widthyAxis.minimum: 0yAxis.maximum: outputItem.outputHeight - outputAreaItem.height}TapHandler {gesturePolicy: TapHandler.WithinBounds}QQC2.Button {id: tabletSizeHandlex: outputItem.widthy: outputItem.width / parent.desiredAspectRatiovisible: outputAreaView.mapToPortionicon.name: "transform-scale-symbolic"display: QQC2.AbstractButton.IconOnlytext: i18ndc("kcm_tablet", "@action:button", "Resize the screen area")QQC2.ToolTip {text: tabletSizeHandle.textvisible: parent.hovered && !screenResizeHandler.activedelay: Kirigami.Units.toolTipDelay}DragHandler {id: screenResizeHandlercursorShape: Qt.SizeFDiagCursortarget: parentonActiveChanged: { outputAreaView.inputChanged = true }xAxis.minimum: 10xAxis.maximum: outputItem.outputWidth - outputAreaItem.xyAxis.minimum: keepAspectRatio.checked ? (outputAreaItem.width * tabletItem.inverseAspectRatio) : 10yAxis.maximum: (keepAspectRatio.checked ? (outputAreaItem.width * tabletItem.inverseAspectRatio) : outputItem.outputHeight) - outputAreaItem.y}}}}Tablet {id: tabletItemanchors {top: outputItem.bottomtopMargin: Kirigami.Units.largeSpacinghorizontalCenter: parent.horizontalCenter}readonly property size outputSize: outputAreaView.device.sizereadonly property real aspectRatio: outputSize.width / outputSize.heightreadonly property real inverseAspectRatio: outputSize.height / outputSize.widthproperty rect mappedfunction recalculateMapped(): void {mapped = Qt.binding(function() { return mapToItem(outputAreaView, tabletItem.internalRect.x, tabletItem.internalRect.y, tabletItem.internalRect.width, tabletItem.internalRect.height); } );}onXChanged: recalculateMapped()onYChanged: recalculateMapped()Component.onCompleted: recalculateMapped()outputWidth: parent.width * 0.7outputHeight: width / aspectRatioRectangle {id: inputAreaItemcolor: Kirigami.Theme.activeBackgroundColoropacity: 0.8readonly property real desiredAspectRatio: outputItem.aspectRatioreadonly property real aspectRatio: width / heightwidth: inputAreaSizeHandle.xheight: inputAreaSizeHandle.yborder {width: 1color: Kirigami.Theme.highlightColor}ColumnLayout {anchors.centerIn: parentvisible: outputAreaView.inputAreaSetting.width !== 1.0 || outputAreaView.inputAreaSetting.height !== 1.0Kirigami.Icon {source: "transform-move-symbolic"Layout.alignment: Qt.AlignHCenter}QQC2.Label {text: i18ndc("kcm_tablet", "tablet area position - size", "%1%,%2% - %3%×%4%", String(Math.floor(outputAreaView.inputAreaSetting.x * 100)), String(Math.floor(outputAreaView.inputAreaSetting.y * 100)), String(Math.floor(outputAreaView.inputAreaSetting.width * 100)), String(Math.floor(outputAreaView.inputAreaSetting.height * 100)))textFormat: Text.PlainTextLayout.fillWidth: true}}DragHandler {cursorShape: Qt.ClosedHandCursortarget: parentenabled: outputAreaView.device.supportsInputAreaonActiveChanged: { outputAreaView.inputChanged = true }xAxis.minimum: 0xAxis.maximum: tabletItem.outputWidth - inputAreaItem.widthyAxis.minimum: 0yAxis.maximum: tabletItem.outputHeight - inputAreaItem.height}TapHandler {gesturePolicy: TapHandler.WithinBounds}QQC2.Button {id: inputAreaSizeHandlex: tabletItem.widthy: tabletItem.width / parent.desiredAspectRatiovisible: outputAreaView.device.supportsInputAreaicon.name: "transform-scale-symbolic"display: QQC2.AbstractButton.IconOnlytext: i18ndc("kcm_tablet", "@action:button", "Resize the tablet area")QQC2.ToolTip {text: inputAreaSizeHandle.textvisible: parent.hovered && !resizeHandler.activedelay: Kirigami.Units.toolTipDelay}DragHandler {id: resizeHandlercursorShape: Qt.SizeFDiagCursortarget: parentonActiveChanged: { outputAreaView.inputChanged = true }xAxis.minimum: 10xAxis.maximum: tabletItem.outputWidth - inputAreaItem.xyAxis.minimum: 10yAxis.maximum: tabletItem.outputHeight - inputAreaItem.y}}}}Shape {preferredRendererType: Shape.CurveRenderervisible: outputAreaView.displayVisibleShapePath {id: topLeftPathstrokeWidth: 1strokeColor: Qt.alpha(Kirigami.Theme.highlightColor, 0.5)startX: outputAreaItem.parent.x + outputAreaItem.xstartY: outputItem.y + outputAreaItem.parent.y + outputAreaItem.yPathLine {x: tabletItem.mapped.x + inputAreaItem.xy: tabletItem.mapped.y + inputAreaItem.y}}ShapePath {id: topRightPathstrokeWidth: 1strokeColor: Qt.alpha(Kirigami.Theme.highlightColor, 0.5)startX: outputAreaItem.parent.x + outputAreaItem.x + outputAreaItem.widthstartY: outputItem.y + outputAreaItem.parent.y + outputAreaItem.yPathLine {x: tabletItem.mapped.x + inputAreaItem.x + inputAreaItem.widthy: tabletItem.mapped.y + inputAreaItem.y}}ShapePath {id: bottomLeftPathstrokeWidth: 1strokeColor: Qt.alpha(Kirigami.Theme.highlightColor, 0.5)startX: outputAreaItem.parent.x + outputAreaItem.xstartY: outputItem.y + outputAreaItem.parent.y + outputAreaItem.y + outputAreaItem.heightPathLine {x: tabletItem.mapped.x + inputAreaItem.xy: tabletItem.mapped.y + inputAreaItem.height + inputAreaItem.y}}ShapePath {id: bottomRightPathstrokeWidth: 1strokeColor: Qt.alpha(Kirigami.Theme.highlightColor, 0.5)startX: outputAreaItem.parent.x + outputAreaItem.x + outputAreaItem.widthstartY: outputItem.y + outputAreaItem.parent.y + outputAreaItem.y + outputAreaItem.heightPathLine {x: tabletItem.mapped.x + inputAreaItem.width + inputAreaItem.xy: tabletItem.mapped.y + inputAreaItem.height + inputAreaItem.y}}}}