mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
016b7a6780
This reverts commit 4b9a289814.
229 lines
6.9 KiB
QML
229 lines
6.9 KiB
QML
import QtQuick
|
|
import qs.Commons
|
|
import qs.Services.Compositor
|
|
import qs.Widgets
|
|
|
|
Item {
|
|
id: pillContainer
|
|
|
|
required property var workspace
|
|
required property bool isVertical
|
|
|
|
// These must be provided by the parent Workspace widget
|
|
required property real baseDimensionRatio
|
|
required property real capsuleHeight
|
|
required property real barHeight
|
|
required property string labelMode
|
|
required property int fontWeight
|
|
required property int characterCount
|
|
required property real textRatio
|
|
required property bool showLabelsOnlyWhenOccupied
|
|
required property string focusedColor
|
|
required property string occupiedColor
|
|
required property string emptyColor
|
|
required property real masterProgress
|
|
required property bool effectsActive
|
|
required property color effectColor
|
|
required property var getWorkspaceWidth
|
|
required property var getWorkspaceHeight
|
|
|
|
// Fixed dimension (cross-axis) for visual pill
|
|
readonly property real fixedDimension: Style.toOdd(capsuleHeight * baseDimensionRatio)
|
|
|
|
// Animated pill dimensions (for visual pill, not container)
|
|
property real pillWidth: isVertical ? fixedDimension : getWorkspaceWidth(workspace, false)
|
|
property real pillHeight: isVertical ? getWorkspaceHeight(workspace, false) : fixedDimension
|
|
|
|
// Container uses full barHeight on cross-axis for larger click area
|
|
width: isVertical ? barHeight : getWorkspaceWidth(workspace, false)
|
|
height: isVertical ? getWorkspaceHeight(workspace, false) : barHeight
|
|
|
|
states: [
|
|
State {
|
|
name: "active"
|
|
when: workspace.isActive
|
|
PropertyChanges {
|
|
target: pillContainer
|
|
width: isVertical ? barHeight : getWorkspaceWidth(workspace, true)
|
|
height: isVertical ? getWorkspaceHeight(workspace, true) : barHeight
|
|
pillWidth: isVertical ? fixedDimension : getWorkspaceWidth(workspace, true)
|
|
pillHeight: isVertical ? getWorkspaceHeight(workspace, true) : fixedDimension
|
|
}
|
|
}
|
|
]
|
|
|
|
transitions: [
|
|
Transition {
|
|
from: "inactive"
|
|
to: "active"
|
|
NumberAnimation {
|
|
properties: isVertical ? "height,pillHeight" : "width,pillWidth"
|
|
duration: Style.animationNormal
|
|
easing.type: Easing.OutBack
|
|
}
|
|
},
|
|
Transition {
|
|
from: "active"
|
|
to: "inactive"
|
|
NumberAnimation {
|
|
properties: isVertical ? "height,pillHeight" : "width,pillWidth"
|
|
duration: Style.animationNormal
|
|
easing.type: Easing.OutBack
|
|
}
|
|
}
|
|
]
|
|
|
|
Rectangle {
|
|
id: pill
|
|
width: pillContainer.pillWidth
|
|
height: pillContainer.pillHeight
|
|
x: Style.pixelAlignCenter(parent.width, width)
|
|
y: Style.pixelAlignCenter(parent.height, height)
|
|
radius: Style.radiusM
|
|
z: 0
|
|
|
|
color: {
|
|
if (pillMouseArea.containsMouse)
|
|
return Color.mHover;
|
|
if (workspace.isFocused)
|
|
return Color.resolveColorKey(focusedColor);
|
|
if (workspace.isUrgent)
|
|
return Color.mError;
|
|
if (workspace.isOccupied)
|
|
return Color.resolveColorKey(occupiedColor);
|
|
return Qt.alpha(Color.resolveColorKey(emptyColor), 0.3);
|
|
}
|
|
|
|
Loader {
|
|
active: (labelMode !== "none") && (!showLabelsOnlyWhenOccupied || workspace.isOccupied || workspace.isFocused)
|
|
anchors.fill: parent
|
|
sourceComponent: Component {
|
|
NText {
|
|
text: {
|
|
if (workspace.name && workspace.name.length > 0) {
|
|
if (labelMode === "name") {
|
|
return workspace.name.substring(0, characterCount);
|
|
}
|
|
if (labelMode === "index+name") {
|
|
// Vertical mode: compact format (no space, first char only)
|
|
// Horizontal mode: full format (space, more chars)
|
|
if (isVertical) {
|
|
return workspace.idx.toString() + workspace.name.substring(0, 1);
|
|
}
|
|
return workspace.idx.toString() + " " + workspace.name.substring(0, characterCount);
|
|
}
|
|
}
|
|
return workspace.idx.toString();
|
|
}
|
|
family: Settings.data.ui.fontFixed
|
|
// Size based on the fixed dimension (cross-axis) of the visual pill
|
|
pointSize: (isVertical ? pillContainer.pillWidth : pillContainer.pillHeight) * textRatio
|
|
applyUiScale: false
|
|
font.capitalization: Font.AllUppercase
|
|
font.weight: fontWeight
|
|
horizontalAlignment: Text.AlignHCenter
|
|
verticalAlignment: Text.AlignVCenter
|
|
wrapMode: Text.Wrap
|
|
color: {
|
|
if (pillMouseArea.containsMouse)
|
|
return Color.mOnHover;
|
|
if (workspace.isFocused)
|
|
return Color.resolveOnColorKey(focusedColor);
|
|
if (workspace.isUrgent)
|
|
return Color.mOnError;
|
|
if (workspace.isOccupied)
|
|
return Color.resolveOnColorKey(occupiedColor);
|
|
return Color.resolveOnColorKey(emptyColor);
|
|
}
|
|
|
|
Behavior on color {
|
|
enabled: !Color.isTransitioning
|
|
ColorAnimation {
|
|
duration: Style.animationFast
|
|
easing.type: Easing.InOutQuad
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Material 3-inspired smooth animations
|
|
Behavior on scale {
|
|
NumberAnimation {
|
|
duration: Style.animationNormal
|
|
easing.type: Easing.OutBack
|
|
}
|
|
}
|
|
Behavior on color {
|
|
enabled: !Color.isTransitioning
|
|
ColorAnimation {
|
|
duration: Style.animationFast
|
|
easing.type: Easing.InOutQuad
|
|
}
|
|
}
|
|
Behavior on opacity {
|
|
NumberAnimation {
|
|
duration: Style.animationFast
|
|
easing.type: Easing.InOutCubic
|
|
}
|
|
}
|
|
Behavior on radius {
|
|
NumberAnimation {
|
|
duration: Style.animationNormal
|
|
easing.type: Easing.OutBack
|
|
}
|
|
}
|
|
}
|
|
|
|
Behavior on width {
|
|
NumberAnimation {
|
|
duration: Style.animationNormal
|
|
easing.type: Easing.OutBack
|
|
}
|
|
}
|
|
Behavior on height {
|
|
NumberAnimation {
|
|
duration: Style.animationNormal
|
|
easing.type: Easing.OutBack
|
|
}
|
|
}
|
|
Behavior on pillWidth {
|
|
NumberAnimation {
|
|
duration: Style.animationNormal
|
|
easing.type: Easing.OutBack
|
|
}
|
|
}
|
|
Behavior on pillHeight {
|
|
NumberAnimation {
|
|
duration: Style.animationNormal
|
|
easing.type: Easing.OutBack
|
|
}
|
|
}
|
|
|
|
// Full-height click area
|
|
MouseArea {
|
|
id: pillMouseArea
|
|
anchors.fill: parent
|
|
cursorShape: Qt.PointingHandCursor
|
|
hoverEnabled: true
|
|
onClicked: {
|
|
CompositorService.switchToWorkspace(workspace);
|
|
}
|
|
}
|
|
|
|
// Burst effect overlay for focused pill
|
|
Rectangle {
|
|
id: pillBurst
|
|
anchors.centerIn: pill
|
|
width: pillContainer.pillWidth + 18 * masterProgress * scale
|
|
height: pillContainer.pillHeight + 18 * masterProgress * scale
|
|
radius: width / 2
|
|
color: "transparent"
|
|
border.color: effectColor
|
|
border.width: Math.max(1, Math.round((2 + 6 * (1.0 - masterProgress))))
|
|
opacity: effectsActive && workspace.isFocused ? (1.0 - masterProgress) * 0.7 : 0
|
|
visible: effectsActive && workspace.isFocused
|
|
z: 1
|
|
}
|
|
}
|