forked from Shinonome/dots-hyprland
122 lines
3.3 KiB
QML
122 lines
3.3 KiB
QML
import qs.modules.common
|
|
import qs.modules.common.functions
|
|
import qs.modules.common.widgets
|
|
import QtQuick
|
|
import QtQuick.Controls
|
|
import QtQuick.Effects
|
|
|
|
/**
|
|
* A progress bar with both ends rounded and text acts as clipping like OneUI 7's battery indicator.
|
|
*/
|
|
ProgressBar {
|
|
id: root
|
|
property bool vertical: false
|
|
property real valueBarWidth: 30
|
|
property real valueBarHeight: 18
|
|
property color highlightColor: Appearance?.colors.colOnSecondaryContainer ?? "#685496"
|
|
property color trackColor: ColorUtils.transparentize(highlightColor, 0.5) ?? "#F1D3F9"
|
|
property alias radius: contentItem.radius
|
|
property alias progressRadius: progressFill.radius
|
|
property string text
|
|
default property Item textMask: Item {
|
|
width: root.valueBarWidth
|
|
height: root.valueBarHeight
|
|
VisuallyCenteredStyledText {
|
|
anchors.fill: parent
|
|
font: root.font
|
|
text: root.text
|
|
}
|
|
layer.enabled: true
|
|
}
|
|
|
|
text: Math.round(value * 100)
|
|
font {
|
|
pixelSize: 13
|
|
weight: text.length > 2 ? Font.Medium : Font.DemiBold
|
|
}
|
|
|
|
background: Item {
|
|
implicitHeight: valueBarHeight
|
|
implicitWidth: valueBarWidth
|
|
}
|
|
|
|
contentItem: Rectangle {
|
|
id: contentItem
|
|
anchors.fill: parent
|
|
radius: 9999
|
|
color: root.trackColor
|
|
visible: false
|
|
|
|
Rectangle {
|
|
id: progressFill
|
|
anchors {
|
|
top: parent.top
|
|
bottom: parent.bottom
|
|
left: parent.left
|
|
right: undefined
|
|
}
|
|
width: parent.width * root.visualPosition
|
|
height: parent.height
|
|
|
|
states: State {
|
|
name: "vertical"
|
|
when: root.vertical
|
|
AnchorChanges {
|
|
target: progressFill
|
|
anchors {
|
|
top: undefined
|
|
bottom: parent.bottom
|
|
left: parent.left
|
|
right: parent.right
|
|
}
|
|
}
|
|
PropertyChanges {
|
|
target: progressFill
|
|
width: parent.width
|
|
height: parent.height * root.visualPosition
|
|
}
|
|
}
|
|
|
|
radius: Appearance.rounding.unsharpen
|
|
color: root.highlightColor
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
id: contentMaskRect
|
|
anchors.fill: contentItem
|
|
width: contentItem.width
|
|
height: contentItem.height
|
|
radius: contentItem.radius
|
|
layer.enabled: true
|
|
visible: false
|
|
}
|
|
|
|
Item {
|
|
// textMask has to be rendered somewhere so we put it in a practically invisible item
|
|
anchors.centerIn: parent
|
|
opacity: 0
|
|
Component.onCompleted: root.textMask.layer.enabled = true // for multieffect masking
|
|
children: [root.textMask]
|
|
}
|
|
|
|
MaskMultiEffect {
|
|
id: boxClip
|
|
anchors.fill: parent
|
|
source: contentItem
|
|
maskSource: contentMaskRect
|
|
visible: false
|
|
}
|
|
|
|
MaskMultiEffect {
|
|
id: textClip
|
|
anchors.fill: parent
|
|
implicitWidth: contentItem.implicitWidth
|
|
implicitHeight: contentItem.implicitHeight
|
|
source: boxClip
|
|
maskSource: root.textMask
|
|
maskInverted: true
|
|
}
|
|
|
|
}
|