mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-18 01:04:01 -04:00
178 lines
6.3 KiB
QML
178 lines
6.3 KiB
QML
pragma ComponentBehavior: Bound
|
|
|
|
import QtQuick
|
|
import qs.Common
|
|
import qs.DCommon.Widgets
|
|
import qs.Modals.DLauncherV2
|
|
|
|
Rectangle {
|
|
id: root
|
|
|
|
LayoutMirroring.enabled: I18n.isRtl
|
|
LayoutMirroring.childrenInherit: true
|
|
|
|
property bool imageTile: false
|
|
property real iconMargins: 0
|
|
property real iconFallbackLeftMargin: 0
|
|
property real iconFallbackRightMargin: 0
|
|
property real iconFallbackBottomMargin: 0
|
|
property real iconMaterialSizeAdjustment: Theme.spacingM
|
|
property real iconUnicodeScale: Theme.fontSizeXLarge / Theme.iconSizeLarge
|
|
property real minIconSize: Theme.iconSizeLarge
|
|
property real maxIconSize: LauncherMetrics.gridIconSize
|
|
property real iconSizeRatio: Theme.launcherImageRatio
|
|
property bool externalHighlight: false
|
|
readonly property color contentColor: isSelected ? Theme.onSelectedContainer : Theme.onSurface
|
|
property var item: null
|
|
property bool isSelected: false
|
|
property bool isHovered: itemArea.containsMouse
|
|
property var controller: null
|
|
property int flatIndex: -1
|
|
|
|
signal clicked
|
|
signal rightClicked(real mouseX, real mouseY)
|
|
signal pointerMoved
|
|
|
|
readonly property string iconValue: {
|
|
if (!item)
|
|
return "";
|
|
switch (item.iconType) {
|
|
case "material":
|
|
case "nerd":
|
|
return "material:" + (item.icon || "apps");
|
|
case "unicode":
|
|
return "unicode:" + (item.icon || "");
|
|
case "composite":
|
|
return item.iconFull || "";
|
|
case "image":
|
|
default:
|
|
return item.icon || "";
|
|
}
|
|
}
|
|
|
|
readonly property int computedIconSize: Math.min(root.maxIconSize, Math.max(root.minIconSize, width * root.iconSizeRatio))
|
|
|
|
radius: Theme.cornerRadiusL
|
|
color: externalHighlight ? "transparent" : isSelected ? Theme.selectedContainer : Theme.foregroundColor(Theme.cardSurface, Theme.isFloatingWindow(root))
|
|
border.width: externalHighlight ? 0 : Theme.layerOutlineWidth
|
|
border.color: Theme.outlineMedium
|
|
opacity: (root.item?.type === "dmenu" && root.item?.data?.nonSelectable) ? 0.5 : 1.0
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
radius: root.radius
|
|
color: Theme.withAlpha(root.contentColor, itemArea.pressed ? Theme.stateLayerPressed : Theme.stateLayerHover)
|
|
visible: root.isHovered || itemArea.pressed
|
|
}
|
|
|
|
DRipple {
|
|
id: rippleLayer
|
|
rippleColor: root.contentColor
|
|
cornerRadius: root.radius
|
|
}
|
|
|
|
Row {
|
|
anchors.top: parent.top
|
|
anchors.right: parent.right
|
|
anchors.margins: Theme.spacingXS
|
|
spacing: Theme.spacingXS
|
|
z: 1
|
|
|
|
SourceBadge {
|
|
badgeVisible: !root.imageTile
|
|
source: root.item?.type === "app" ? (root.item.source || "") : ""
|
|
glyphSize: Theme.iconSizeSmall
|
|
}
|
|
|
|
DIcon {
|
|
name: "push_pin"
|
|
size: Theme.iconSizeSmall
|
|
color: root.contentColor
|
|
visible: root.item?.pinned === true
|
|
}
|
|
|
|
DIcon { // dmenu --multi-select checkbox
|
|
name: root.item?.data?.checked ? "check_box" : "check_box_outline_blank"
|
|
size: Theme.iconSizeSmall
|
|
color: root.item?.data?.checked ? Theme.primary : root.contentColor
|
|
visible: root.item?.type === "dmenu" && root.controller?.dmenuMultiSelect === true
|
|
}
|
|
}
|
|
|
|
Loader {
|
|
anchors.fill: parent
|
|
active: !root.imageTile
|
|
sourceComponent: Item {
|
|
Column {
|
|
anchors.centerIn: parent
|
|
spacing: Theme.spacingS
|
|
width: parent.width - Theme.spacingL * 2
|
|
|
|
AppIconRenderer {
|
|
visible: !(root.item?.type === "dmenu" && root.item?.data?.nonSelectable && !root.item?.icon)
|
|
fallbackRadius: Theme.fullRadius(width, height)
|
|
fallbackBackgroundColor: Theme.primaryContainer
|
|
fallbackTextColor: Theme.onPrimaryContainer
|
|
width: root.computedIconSize
|
|
height: root.computedIconSize
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
iconValue: root.iconValue
|
|
iconMargins: root.iconMargins
|
|
fallbackLeftMargin: root.iconFallbackLeftMargin
|
|
fallbackRightMargin: root.iconFallbackRightMargin
|
|
fallbackBottomMargin: root.iconFallbackBottomMargin
|
|
unicodeIconScale: root.iconUnicodeScale
|
|
iconSize: root.computedIconSize
|
|
animate: root.visible && root.item?.data?.animated === true
|
|
fallbackText: root.item?.name?.charAt(0).toUpperCase() || "?"
|
|
iconColor: root.contentColor
|
|
materialIconSizeAdjustment: root.iconMaterialSizeAdjustment
|
|
}
|
|
|
|
StyledText {
|
|
width: parent.width
|
|
height: LauncherMetrics.tileLabelBlockHeight
|
|
verticalAlignment: Text.AlignTop
|
|
text: root.item?._hName ?? root.item?.name ?? ""
|
|
textFormat: root.item?._hRich ? Text.RichText : Text.PlainText
|
|
font.pixelSize: Theme.fontSizeSmall
|
|
font.weight: Theme.fontWeightMedium
|
|
font.family: Theme.fontFamily
|
|
color: root.contentColor
|
|
elide: Text.ElideRight
|
|
horizontalAlignment: Text.AlignHCenter
|
|
maximumLineCount: 2
|
|
wrapMode: Text.Wrap
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
MouseArea {
|
|
id: itemArea
|
|
anchors.fill: parent
|
|
hoverEnabled: true
|
|
cursorShape: Qt.PointingHandCursor
|
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
|
|
onPressed: mouse => {
|
|
if (mouse.button === Qt.LeftButton)
|
|
rippleLayer.trigger(mouse.x, mouse.y);
|
|
}
|
|
onClicked: mouse => {
|
|
if (mouse.button === Qt.RightButton) {
|
|
var scenePos = mapToItem(null, mouse.x, mouse.y);
|
|
root.rightClicked(scenePos.x, scenePos.y);
|
|
return;
|
|
}
|
|
root.clicked();
|
|
}
|
|
|
|
onPositionChanged: {
|
|
root.pointerMoved();
|
|
if (root.controller)
|
|
root.controller.keyboardNavigationActive = false;
|
|
}
|
|
}
|
|
}
|