import QtQuick import QtQuick.Controls AbstractButton { id: root property int paddingZero: 2 // 1=> "01" property int modelRangeMin: 0 property int modelRangeMax: 12 property list model: [] property int visibleItemCount: 7 property int currentIndex: 0 // property real opacityStep: 0 property alias prefix: prefix.text property alias midItemHeight: midItem.height property alias midItemY: midItem.y // property alias selected: root.checked property bool active: false property bool loop: true function scrollUp() { if (loop) { currentIndex-- if (currentIndex < 0) currentIndex = model.length - 1 } else { if (currentIndex > 0) currentIndex-- } } function scrollDown() { if (loop) { currentIndex++ if (currentIndex > model.length) currentIndex = 0 } else { if (currentIndex < (model.length - 1)) currentIndex++ } } function activeButtonGroup() { for (let i = 0; i < root.parent.children.length; i++) { root.parent.children[i].active = true } } implicitWidth: column.implicitWidth + prefix.implicitWidth implicitHeight: column.implicitHeight checkable: true // onModelRangeMinChanged: column.createModel() // onModelRangeMaxChanged: column.createModel() Component.onCompleted: column.createModel() onPressed: { // activeButtonGroup() if (checked) { if (pressY > root.height / 2) { root.scrollUp() } else { root.scrollDown() } } } component SideItem: Text { font.pixelSize: 56 font.family: "Kawasaki Type 003" font.weight: 400 color: "#c0c0c0" anchors.horizontalCenter: parent.horizontalCenter } component MiddleItem: Text { font.pixelSize: 90 font.family: "Kawasaki Type 003" font.weight: 400 color: root.active ? "white" : "#555555" } Column { id: column x: prefix.implicitWidth // internal property readonly property int sizeVisibleItemCount: root.visibleItemCount / 2 function modelAt(index: int): string { if (index < 0) { if (loop) { index = model.length + index; } else { return " " } } if (index >= 0 && index < model.length) { return model[index]; } else { if (loop) { return model[index - model.length]; } else { return " " } } } function createModel() { if (root.modelRangeMin >= root.modelRangeMax || root.model.length != 0) return root.model = [] for (let i = modelRangeMin; i <= modelRangeMax; i++) root.model.push(i.toString().padStart(root.paddingZero, '0')) } Repeater { id: upperItems model: column.sizeVisibleItemCount delegate: SideItem { required property int index text: column.modelAt(root.currentIndex + (index - column.sizeVisibleItemCount)) // opacity: 1 - root.opacityStep * (column.sizeVisibleItemCount - index) // onOpacityChanged: console.log("up", opacity) } } MiddleItem { id: midItem text: column.modelAt(root.currentIndex) topPadding: 15 bottomPadding: 10 rightPadding: 15 leftPadding: 18 color: root.active ? (root.checked ? "#00ffb7" : "white") : "#555555" z: 1 Image { width: root.width height: parent.y y: -height source: "../assets/shade_upper.png" } Image { width: root.width height: root.height - downItems.y y: midItem.height source: "../assets/shade_lower.png" } BorderImage { visible: root.checked border.top: 5 border.right: 5 border.left: 10 border.bottom: 15 anchors.fill: parent anchors.margins: 5 source: "../assets/base_picked_number_picked_active.png" Image { anchors.horizontalCenter: parent.horizontalCenter anchors.bottom: parent.top anchors.margins: 10 source: "../assets/spin_up.png" } Image { anchors.horizontalCenter: parent.horizontalCenter anchors.top: parent.bottom anchors.margins: 10 source: "../assets/spin_down.png" } } MiddleItem { id: prefix anchors.right: parent.left anchors.verticalCenter: parent.verticalCenter } } Repeater { id: downItems model: column.sizeVisibleItemCount delegate: SideItem { required property int index text: column.modelAt(root.currentIndex + index + 1) // opacity: 1 - root.opacityStep * (index + 1) // onOpacityChanged: console.log("down", opacity ) } } } }