DPS_Manage/DelegateUI/Controls/DelRate.qml

231 lines
7.8 KiB
QML

import QtQuick 2.15
import QtGraphicalEffects 1.15
import DelegateUI 1.0
Item {
id: control
implicitWidth: __mouseArea.width
implicitHeight: __mouseArea.height
toolTipFont {
family: DelTheme.DelRate.fontFamily
pixelSize: DelTheme.DelRate.fontSize
}
property bool animationEnabled: DelTheme.animationEnabled
property int hoverCursorShape: Qt.PointingHandCursor
property int count: 5
property real initValue: -1
property real value: 0
property alias spacing: __row.spacing
property int iconSize: 24
/* 文字提示 */
property font toolTipFont
property bool toolTipVisible: false
property var toolTipTexts: []
property color colorFill: DelTheme.DelRate.colorFill
property color colorEmpty: DelTheme.DelRate.colorEmpty
property color colorHalf: DelTheme.DelRate.colorHalf
property color colorToolTipText: DelTheme.DelRate.colorToolTipText
property color colorToolTipBg: DelTheme.isDark ? DelTheme.DelRate.colorToolTipBgDark : DelTheme.DelRate.colorToolTipBg
/* 允许半星 */
property bool allowHalf: false
property bool isDone: false
property int fillIcon: DelIcon.StarFilled
property int emptyIcon: DelIcon.StarFilled
property int halfIcon: DelIcon.StarFilled
property Component fillDelegate: DelIconText {
colorIcon: control.colorFill
iconSource: control.fillIcon
iconSize: control.iconSize
}
property Component emptyDelegate: DelIconText {
colorIcon: control.colorEmpty
iconSource: control.emptyIcon
iconSize: control.iconSize
}
property Component halfDelegate: DelIconText {
colorIcon: control.colorEmpty
iconSource: control.emptyIcon
iconSize: control.iconSize
DelIconText {
id: __source
colorIcon: control.colorHalf
iconSource: control.halfIcon
iconSize: control.iconSize
layer.enabled: true
layer.effect: halfRateHelper
}
}
property Component toolTipDelegate: Item {
width: 12
height: 6
opacity: hovered ? 1 : 0
Behavior on opacity { enabled: control.animationEnabled; NumberAnimation { duration: DelTheme.Primary.durationMid } }
DropShadow {
anchors.fill: __item
radius: 16
samples: 17
color: DelThemeFunctions.alpha(control.colorToolTipText, DelTheme.isDark ? 0.1 : 0.2)
source: __item
}
Item {
id: __item
width: __toolTipBg.width
height: __arrow.height + __toolTipBg.height - 1
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
Rectangle {
id: __toolTipBg
width: __toolTipText.implicitWidth + 14
height: __toolTipText.implicitHeight + 12
anchors.bottom: __arrow.top
anchors.bottomMargin: -1
anchors.horizontalCenter: parent.horizontalCenter
color: control.colorToolTipBg
radius: 4
Text {
id: __toolTipText
color: control.colorToolTipText
text: control.toolTipTexts[index]
font: control.toolTipFont
anchors.centerIn: parent
}
}
Canvas {
id: __arrow
width: 12
height: 6
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
onColorBgChanged: requestPaint();
onPaint: {
const ctx = getContext("2d");
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(width, 0);
ctx.lineTo(width * 0.5, height);
ctx.closePath();
ctx.fillStyle = colorBg;
ctx.fill();
}
property color colorBg: control.colorToolTipBg
}
}
}
property Component halfRateHelper: ShaderEffect {
fragmentShader: "qrc:/DelegateUI/shaders/delrate.frag"
}
onInitValueChanged: {
__private.doneValue = value = initValue;
isDone = true;
}
/* 结束 */
signal done(int value);
QtObject {
id: __private
property real doneValue: 0
}
MouseArea {
id: __mouseArea
width: __row.width
height: control.iconSize
hoverEnabled: true
enabled: control.enabled
onExited: {
if (control.isDone) {
control.value = __private.doneValue;
}
}
Row {
id: __row
spacing: 4
Repeater {
id: __repeater
property int fillCount: Math.floor(control.value)
property int emptyStartIndex: Math.round(control.value)
property bool hasHalf: control.value - fillCount > 0
model: control.count
delegate: MouseArea {
id: __rootItem
width: control.iconSize
height: control.iconSize
hoverEnabled: true
cursorShape: hovered ? control.hoverCursorShape : Qt.ArrowCursor
enabled: control.enabled
onEntered: hovered = true;
onExited: hovered = false;
onClicked: {
control.isDone = !control.isDone;
if (control.isDone) {
__private.doneValue = control.value;
control.done(__private.doneValue);
}
}
onPositionChanged: function(mouse) {
if (control.allowHalf) {
if (mouse.x > (width * 0.5)) {
control.value = index + 1;
} else {
control.value = index + 0.5;
}
} else {
control.value = index + 1;
}
}
required property int index
property bool hovered: false
Loader {
active: index < __repeater.fillCount
sourceComponent: control.fillDelegate
property int index: __rootItem.index
property bool hovered: __rootItem.hovered
}
Loader {
active: __repeater.hasHalf && index === (__repeater.emptyStartIndex - 1)
sourceComponent: control.halfDelegate
property int index: __rootItem.index
property bool hovered: __rootItem.hovered
}
Loader {
active: index >= __repeater.emptyStartIndex
sourceComponent: control.emptyDelegate
property int index: __rootItem.index
property bool hovered: __rootItem.hovered
}
Loader {
x: (parent.width - width) * 0.5
y: -height - 4
z: 10
active: control.toolTipVisible
sourceComponent: control.toolTipDelegate
property int index: __rootItem.index
property bool hovered: __rootItem.hovered
}
}
}
}
}
}