C

Qt Quick Ultralite Automotive Cluster Demo

// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial

import QtQuick 2.15
import QtQuickUltralite.Extras 2.0
import Automotive 1.0

Item {
    id: root;
    property bool active: false

    Component.onCompleted: active = true

    Connections {
        target: MainModel
        function onClusterModeChanged(clusterMode: int) {
            active = false
       }
    }

    MiddleGauge {
        id: middleGauge
        left: true
        anchors.horizontalCenter: parent.horizontalCenter
        valueVerticalCenterOffset: -27
        y: 62;
        value: MainModel.rpm / 1000;
        maxValue: MainModel.maxRpm / 1000;
        valueText: MainModel.gearShiftText
        textLabel: "Gear shift"
        maxAngle: 285
        minAngle: 45
        labelOpacity: (menu.active || !root.active) ? 0 : 1
        opacity: 0;

        StaticText {
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.verticalCenter: parent.verticalCenter
            anchors.horizontalCenterOffset: -105
            anchors.verticalCenterOffset: 95

            opacity: 0.2
            horizontalAlignment: Text.AlignRight
            text: "x1000\n    RPM"
            color: Style.lightPeriwinkle
            font.pixelSize: 10
            font.family: "Sarabun"
        }
    }

    Item {
        id: gauges
        opacity: 0 ;

        SpeedWarningIndicator {
            opacity: leftGauge.opacity
            anchors.horizontalCenter: leftGauge.horizontalCenter
            anchors.horizontalCenterOffset: leftGauge.labelHorizontalCenterOffset
            y: 295
            width: 44
        }

        SportGauge {
            id: leftGauge;
            x: root.width / 3
            y: 44;
            left: true;
            value: Units.kilometersToLongDistanceUnit(MainModel.speed)
            maxValue: Units.maximumSpeed;
            textLabel: Units.speedUnit
            valueTextScale: 0.8;
            valueHorizontalCenterOffset: -20;
            labelHorizontalCenterOffset: -18;
            labelVerticalOffset: -5;
        }

        TempGauge {
            id: rightGauge;
            x: root.width - rightGauge.width - root.width / 3;
            y: 44;
            value: MainModel.temp;
            maxValue: 180;
            maxAngle: 180;

            opacity: MainModel.gaugesOpacity;
        }
    }

    DriveModeSelector {
        id: modeSelector

        anchors.centerIn: middleGauge
        anchors.verticalCenterOffset: -36
        anchors.horizontalCenterOffset: -65
        spacing: 15
        opacity: menu.active ? 1 : 0

        Behavior on opacity { NumberAnimation { duration: 600 } }
    }

    Item {
        id: menu
        property bool active: SportModeModel.menuActive && root.active
        opacity: gauges.opacity
        anchors.horizontalCenter: middleGauge.horizontalCenter;
        anchors.verticalCenter: middleGauge.verticalCenter;
        anchors.horizontalCenterOffset: 70
        anchors.verticalCenterOffset: 80
        width: 47
        height: 38
        ColorizedImage {
            color: parent.active ? Style.lightPeriwinkle : "#001b4d"
            Behavior on color { ColorAnimation { duration: 600; easing.type: Easing.InCubic } }
            source: "images/setup.png"
            anchors.horizontalCenter: parent.horizontalCenter
        }
        Text {
            text: "Setup"
            anchors.bottom: parent.bottom
            anchors.horizontalCenter: parent.horizontalCenter
            opacity: parent.active ? 1 : 0
            Behavior on opacity { NumberAnimation { duration: 600; easing.type: Easing.InCubic } }
            font.pixelSize: 12;
            font.family: "Sarabun";
            color: Style.lightPeriwinkle;
        }
    }

    states: [
        State {
            name: "active"
            when: active
            PropertyChanges {
                target: middleGauge
                opacity: MainModel.gaugesOpacity
            }
            PropertyChanges {
                target: gauges
                opacity: MainModel.gaugesOpacity
            }
            PropertyChanges {
                target: leftGauge
                x: 20
            }
            PropertyChanges {
                target: rightGauge
                x: root.width - rightGauge.width - 20;
            }
        }
    ]

    transitions: [
        Transition {
            to: "active"
            SequentialAnimation {
                NumberAnimation {
                    target: middleGauge
                    duration: 250
                }
                ParallelAnimation {
                    NumberAnimation {
                        easing.type: Easing.Linear
                        target: gauges;
                        duration: 250;
                    }
                    NumberAnimation {
                        easing.type: Easing.OutExpo
                        target: leftGauge;
                        duration: 350;
                    }
                    NumberAnimation {
                        easing.type: Easing.OutExpo
                        target: rightGauge;
                        duration: 350;
                    }
                }
            }
        },
        Transition {
            from: "active"
            SequentialAnimation {
                ParallelAnimation {
                    NumberAnimation {
                        easing.type: Easing.Linear
                        target: gauges;
                        duration: 250;
                    }
                    NumberAnimation {
                        easing.type: Easing.InExpo
                        target: leftGauge;
                        duration: 350;
                    }
                    NumberAnimation {
                        easing.type: Easing.InExpo
                        target: rightGauge;
                        duration: 350;
                    }
                    NumberAnimation {
                        easing.type: Easing.InExpo
                        target: rightGauge
                        duration: 350
                    }
                }
                NumberAnimation {
                    target: middleGauge
                    duration: 250
                }
            }
        }
    ]
}