Merge pull request 'Blob bounciness' (#67) from bounce-test into main

Reviewed-on: #67
This commit was merged in pull request #67.
This commit is contained in:
2026-04-22 00:01:46 +02:00
16 changed files with 239 additions and 602 deletions
+2 -2
View File
@@ -97,7 +97,7 @@ CustomMouseArea {
visibilities.dock = true; visibilities.dock = true;
if (panels.sidebar.width === 0) { if (panels.sidebar.width === 0) {
const showOsd = inRightPanel(panels.osd, x, y); const showOsd = inRightPanel(panels.osdWrapper, x, y);
if (showOsd) { if (showOsd) {
osdShortcutActive = false; osdShortcutActive = false;
@@ -105,7 +105,7 @@ CustomMouseArea {
} }
} else { } else {
const outOfSidebar = x < width - panels.sidebar.width; const outOfSidebar = x < width - panels.sidebar.width;
const showOsd = outOfSidebar && inRightPanel(panels.osd, x, y); const showOsd = outOfSidebar && inRightPanel(panels.osdWrapper, x, y);
if (!osdShortcutActive) { if (!osdShortcutActive) {
visibilities.osd = showOsd; visibilities.osd = showOsd;
+59 -12
View File
@@ -20,15 +20,18 @@ Item {
required property Item bar required property Item bar
readonly property alias dashboard: dashboard readonly property alias dashboard: dashboard
readonly property alias dashboardWrapper: dashboardWrapper
readonly property alias dock: dock readonly property alias dock: dock
readonly property alias drawing: drawing readonly property alias drawing: drawing
required property Canvas drawingItem required property Canvas drawingItem
readonly property alias launcher: launcher readonly property alias launcher: launcher
readonly property alias notifications: notifications readonly property alias notifications: notifications
readonly property alias osd: osd readonly property alias osd: osd
readonly property alias osdWrapper: osdWrapper
readonly property alias popouts: popouts.content readonly property alias popouts: popouts.content
readonly property alias popoutsWrapper: popouts readonly property alias popoutsWrapper: popouts
readonly property alias resources: resources readonly property alias resources: resources
readonly property alias resourcesWrapper: resourcesWrapper
required property ShellScreen screen required property ShellScreen screen
readonly property alias settings: settings readonly property alias settings: settings
readonly property alias sidebar: sidebar readonly property alias sidebar: sidebar
@@ -40,6 +43,15 @@ Item {
anchors.margins: Config.barConfig.border anchors.margins: Config.barConfig.border
anchors.topMargin: bar.implicitHeight anchors.topMargin: bar.implicitHeight
Item {
id: resourcesWrapper
anchors.left: parent.left
anchors.top: parent.top
clip: true
implicitHeight: resources.implicitHeight * (1 - resources.offsetScale)
implicitWidth: resources.implicitWidth
Resources.Wrapper { Resources.Wrapper {
id: resources id: resources
@@ -47,6 +59,28 @@ Item {
anchors.top: parent.top anchors.top: parent.top
visibilities: root.visibilities visibilities: root.visibilities
} }
}
Item {
id: osdWrapper
anchors.right: parent.right
anchors.rightMargin: sidebar.width * (1 - sidebar.offsetScale)
anchors.verticalCenter: parent.verticalCenter
clip: sidebar.visible
implicitHeight: osd.implicitHeight
implicitWidth: osd.implicitWidth * (1 - osd.offsetScale)
Osd.Wrapper {
id: osd
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
screen: root.screen
sidebarOrSessionVisible: sidebar.visible
visibilities: root.visibilities
}
}
Drawing.Wrapper { Drawing.Wrapper {
id: drawing id: drawing
@@ -58,17 +92,6 @@ Item {
visibilities: root.visibilities visibilities: root.visibilities
} }
Osd.Wrapper {
id: osd
anchors.right: parent.right
anchors.rightMargin: sidebar.width
anchors.verticalCenter: parent.verticalCenter
clip: sidebar.width > 0
screen: root.screen
visibilities: root.visibilities
}
Modules.ClipWrapper { Modules.ClipWrapper {
id: popouts id: popouts
@@ -90,6 +113,7 @@ Item {
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.top: parent.top
panels: root panels: root
sidebarPanel: sidebar
visibilities: root.visibilities visibilities: root.visibilities
} }
@@ -113,13 +137,34 @@ Item {
visibilities: root.visibilities visibilities: root.visibilities
} }
Item {
id: dashboardWrapper
property real offsetScale: dashboard.shouldBeActive ? 0 : 1
anchors.right: parent.right
anchors.top: parent.top
clip: true
implicitHeight: dashboard.implicitHeight * (1 - offsetScale)
implicitWidth: dashboard.implicitWidth
Behavior on offsetScale {
Anim {
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
}
Dashboard.Wrapper { Dashboard.Wrapper {
id: dashboard id: dashboard
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: (-implicitHeight - 5) * offsetScale
offsetScale: dashboardWrapper.offsetScale
visibilities: root.visibilities visibilities: root.visibilities
} }
}
Sidebar.Wrapper { Sidebar.Wrapper {
id: sidebar id: sidebar
@@ -134,7 +179,9 @@ Item {
Settings.Wrapper { Settings.Wrapper {
id: settings id: settings
anchors.centerIn: parent anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
// anchors.centerIn: parent
panels: root panels: root
screen: root.screen screen: root.screen
visibilities: root.visibilities visibilities: root.visibilities
+32 -10
View File
@@ -170,15 +170,19 @@ Variants {
PanelBg { PanelBg {
id: dashBg id: dashBg
deformAmount: 0.15 * Config.appearance.deform.scale deformAmount: 0.08 * Config.appearance.deform.scale
implicitHeight: panels.dashboard.height
implicitWidth: panels.dashboard.width
panel: panels.dashboard panel: panels.dashboard
radius: Appearance.rounding.normal radius: Appearance.rounding.normal
x: panels.dashboardWrapper.x + panels.dashboard.x + Config.barConfig.border
y: panels.dashboardWrapper.y + panels.dashboard.y + bar.implicitHeight
} }
PanelBg { PanelBg {
id: launcherBg id: launcherBg
deformAmount: 0.15 * Config.appearance.deform.scale deformAmount: 0.08 * Config.appearance.deform.scale
panel: panels.launcher panel: panels.launcher
radius: Appearance.rounding.smallest + 5 radius: Appearance.rounding.smallest + 5
} }
@@ -187,8 +191,8 @@ Variants {
id: sidebarBg id: sidebarBg
bottomLeftRadius: 0 bottomLeftRadius: 0
deformAmount: 0.1 * Config.appearance.deform.scale deformAmount: 0.08 * Config.appearance.deform.scale
exclude: panels.sidebar.offsetscale > 0.08 ? [] : [utilsBg] exclude: panels.sidebar.offsetScale > 0.08 ? [] : [utilsBg]
implicitHeight: panel.height * (1 / rawDeformMatrix.m22) + 2 implicitHeight: panel.height * (1 / rawDeformMatrix.m22) + 2
panel: panels.sidebar panel: panels.sidebar
} }
@@ -197,8 +201,12 @@ Variants {
id: osdBg id: osdBg
deformAmount: 0.1 * Config.appearance.deform.scale deformAmount: 0.1 * Config.appearance.deform.scale
implicitHeight: panels.osd.height
implicitWidth: panels.osd.width
panel: panels.osd panel: panels.osd
radius: 20 radius: 20
x: panels.osdWrapper.x + panels.osd.x + Config.barConfig.border
y: panels.osdWrapper.y + panels.osd.y + bar.implicitHeight
} }
PanelBg { PanelBg {
@@ -219,24 +227,38 @@ Variants {
PanelBg { PanelBg {
id: popoutBg id: popoutBg
deformAmount: 0.15 * Config.appearance.deform.scale property real extraHeight: panels.popouts.isDetached ? 0 : 0.2
deformAmount: panels.popouts.isDetached ? 0.05 * Config.appearance.deform.scale : panels.popouts.hasCurrent ? 0.15 * Config.appearance.deform.scale : 0.1 * Config.appearance.deform.scale
implicitHeight: panels.popouts.height * (1 + extraHeight)
implicitWidth: panels.popouts.width implicitWidth: panels.popouts.width
panel: panels.popoutsWrapper panel: panels.popouts
radius: (panels.popouts.currentName.startsWith("audio") || panels.popouts.currentName.startsWith("updates")) ? Appearance.rounding.normal : Appearance.rounding.smallest radius: (panels.popouts.currentName.startsWith("audio") || panels.popouts.currentName.startsWith("updates")) ? Appearance.rounding.normal : Appearance.rounding.smallest
x: panels.popoutsWrapper.x + panels.popouts.x + Config.barConfig.border
y: panels.popoutsWrapper.y + panels.popouts.y + bar.implicitHeight - panels.popouts.height * extraHeight
Behavior on extraHeight {
Anim {
}
}
} }
PanelBg { PanelBg {
id: resourcesBg id: resourcesBg
deformAmount: 0.15 * Config.appearance.deform.scale deformAmount: 0.08 * Config.appearance.deform.scale
implicitHeight: panels.resources.height
implicitWidth: panels.resources.width
panel: panels.resources panel: panels.resources
radius: Appearance.rounding.normal radius: Appearance.rounding.normal
x: panels.resourcesWrapper.x + panels.resources.x + Config.barConfig.border
y: panels.resourcesWrapper.y + panels.resources.y + bar.implicitHeight
} }
PanelBg { PanelBg {
id: settingsBg id: settingsBg
deformAmount: 0.1 * Config.appearance.deform.scale deformAmount: 0.08 * Config.appearance.deform.scale
panel: panels.settings panel: panels.settings
radius: Appearance.rounding.large radius: Appearance.rounding.large
topLeftRadius: Appearance.rounding.large + Appearance.padding.smaller topLeftRadius: Appearance.rounding.large + Appearance.padding.smaller
@@ -246,7 +268,7 @@ Variants {
PanelBg { PanelBg {
id: dockBg id: dockBg
deformAmount: 0.15 * Config.appearance.deform.scale deformAmount: 0.08 * Config.appearance.deform.scale
panel: panels.dock panel: panels.dock
radius: Appearance.rounding.normal radius: Appearance.rounding.normal
} }
@@ -342,7 +364,7 @@ Variants {
required property Item panel required property Item panel
deformScale: deformAmount / 10000 deformScale: deformAmount / 10000
group: panel.width > 0 && panel.height > 0 ? blobGroup : null group: blobGroup
implicitHeight: panel.height implicitHeight: panel.height
implicitWidth: panel.width implicitWidth: panel.width
radius: Appearance.rounding.smallest radius: Appearance.rounding.smallest
+5 -1
View File
@@ -17,12 +17,16 @@ Item {
implicitWidth: content.implicitWidth implicitWidth: content.implicitWidth
visible: width > 0 && height > 0 visible: width > 0 && height > 0
x: { x: {
const off = content.currentCenter - content.nonAnimWidth / 2; if (content.isDetached)
return (parent.width - content.nonAnimWidth) / 2;
const off = content.currentCenter - Config.barConfig.border - content.nonAnimWidth / 2;
const diff = parent.width - Math.floor(off + content.nonAnimWidth); const diff = parent.width - Math.floor(off + content.nonAnimWidth);
if (diff < 0) if (diff < 0)
return off + diff; return off + diff;
return Math.floor(Math.max(off, 0)); return Math.floor(Math.max(off, 0));
} }
y: content.isDetached ? (parent.height - content.nonAnimHeight) / 2 : 0
Behavior on offsetScale { Behavior on offsetScale {
Anim { Anim {
+7 -59
View File
@@ -15,78 +15,26 @@ Item {
reloadableId: "dashboardState" reloadableId: "dashboardState"
} }
readonly property real nonAnimHeight: state === "visible" ? (content.item?.nonAnimHeight ?? 0) : 0 readonly property real nonAnimHeight: state === "visible" ? (content.item?.nonAnimHeight ?? 0) : 0
required property real offsetScale
readonly property bool shouldBeActive: root.visibilities.dashboard && Config.dashboard.enabled
required property PersistentProperties visibilities required property PersistentProperties visibilities
implicitHeight: 0 implicitHeight: content.implicitHeight
implicitWidth: content.implicitWidth implicitWidth: content.implicitWidth || 854 // Hard coded fallback for first open
visible: height > 0 opacity: 1 - offsetScale
states: State { // visible: offsetScale < 1
name: "visible"
when: root.visibilities.dashboard && Config.dashboard.enabled
PropertyChanges {
root.implicitHeight: content.implicitHeight
}
}
transitions: [
Transition {
from: ""
to: "visible"
Anim {
duration: MaterialEasing.expressiveEffectsTime
easing.bezierCurve: MaterialEasing.expressiveEffects
property: "implicitHeight"
target: root
}
},
Transition {
from: "visible"
to: ""
Anim {
easing.bezierCurve: MaterialEasing.expressiveEffects
property: "implicitHeight"
target: root
}
}
]
onStateChanged: {
if (state === "visible" && timer.running) {
timer.triggered();
timer.stop();
}
}
Timer {
id: timer
interval: Appearance.anim.durations.extraLarge
running: true
onTriggered: {
content.active = Qt.binding(() => (root.visibilities.dashboard && Config.dashboard.enabled) || root.visible);
content.visible = true;
}
}
CustomClippingRect {
anchors.fill: parent
Loader { Loader {
id: content id: content
active: true active: root.shouldBeActive || root.visible
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
visible: false
sourceComponent: Content { sourceComponent: Content {
state: root.dashState state: root.dashState
visibilities: root.visibilities visibilities: root.visibilities
} }
} }
}
} }
+13 -74
View File
@@ -11,97 +11,36 @@ Item {
property int contentHeight property int contentHeight
required property var panels required property var panels
required property ShellScreen screen required property ShellScreen screen
readonly property bool shouldBeActive: visibilities.dock
required property PersistentProperties visibilities required property PersistentProperties visibilities
implicitHeight: 0 readonly property bool shouldBeActive: visibilities.dock
implicitWidth: content.implicitWidth property real offsetScale: shouldBeActive ? 0 : 1
visible: height > 0
Behavior on implicitWidth { visible: offsetScale < 1
anchors.bottomMargin: (-implicitHeight - 5) * offsetScale
implicitHeight: content.implicitHeight
implicitWidth: content.implicitWidth || 400
opacity: 1 - offsetScale
Behavior on offsetScale {
Anim { Anim {
duration: Appearance.anim.durations.small duration: Appearance.anim.durations.expressiveDefaultSpatial
} easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
onShouldBeActiveChanged: {
if (shouldBeActive) {
timer.stop();
hideAnim.stop();
showAnim.start();
} else {
showAnim.stop();
hideAnim.start();
}
}
SequentialAnimation {
id: showAnim
Anim {
duration: Appearance.anim.durations.small
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
property: "implicitHeight"
target: root
to: root.contentHeight
}
ScriptAction {
script: root.implicitHeight = Qt.binding(() => content.implicitHeight)
}
}
SequentialAnimation {
id: hideAnim
ScriptAction {
script: root.implicitHeight = root.implicitHeight
}
Anim {
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
property: "implicitHeight"
target: root
to: 0
}
}
Timer {
id: timer
interval: Appearance.anim.durations.small
onRunningChanged: {
if (running && !root.shouldBeActive) {
content.visible = false;
content.active = true;
} else {
content.active = Qt.binding(() => root.shouldBeActive || root.visible);
content.visible = true;
if (showAnim.running) {
showAnim.stop();
showAnim.start();
}
}
} }
} }
Loader { Loader {
id: content id: content
active: false
anchors.left: parent.left anchors.left: parent.left
anchors.top: parent.top anchors.top: parent.top
visible: false
active: root.shouldBeActive || root.visible
sourceComponent: Content { sourceComponent: Content {
panels: root.panels panels: root.panels
screen: root.screen screen: root.screen
visibilities: root.visibilities visibilities: root.visibilities
Component.onCompleted: root.contentHeight = implicitHeight
} }
Component.onCompleted: timer.start()
} }
} }
+13 -40
View File
@@ -21,55 +21,33 @@ Item {
} }
required property var panels required property var panels
required property ShellScreen screen required property ShellScreen screen
readonly property bool shouldBeActive: visibilities.launcher
required property PersistentProperties visibilities required property PersistentProperties visibilities
readonly property bool shouldBeActive: visibilities.launcher
property real offsetScale: shouldBeActive ? 0 : 1
implicitHeight: 0
implicitWidth: content.implicitWidth
visible: height > 0
onMaxHeightChanged: timer.start()
onShouldBeActiveChanged: { onShouldBeActiveChanged: {
if (shouldBeActive) { if (shouldBeActive) {
implicitHeight = Qt.binding(() => content.implicitHeight);
timer.stop(); timer.stop();
hideAnim.stop();
showAnim.start();
} else { } else {
showAnim.stop(); implicitHeight = implicitHeight;
hideAnim.start();
} }
} }
SequentialAnimation { visible: offsetScale < 1
id: showAnim anchors.bottomMargin: (-implicitHeight - 5) * offsetScale
implicitHeight: content.implicitHeight
implicitWidth: content.implicitWidth || 400
opacity: 1 - offsetScale
Behavior on offsetScale {
Anim { Anim {
duration: Appearance.anim.durations.small duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveEffects easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
property: "implicitHeight"
target: root
to: root.contentHeight
}
ScriptAction {
script: root.implicitHeight = Qt.binding(() => content.implicitHeight)
} }
} }
SequentialAnimation { onMaxHeightChanged: timer.start()
id: hideAnim
ScriptAction {
script: root.implicitHeight = root.implicitHeight
}
Anim {
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
property: "implicitHeight"
target: root
to: 0
}
}
Connections { Connections {
function onEnabledChanged(): void { function onEnabledChanged(): void {
@@ -105,10 +83,6 @@ Item {
root.contentHeight = Math.min(root.maxHeight, content.implicitHeight); root.contentHeight = Math.min(root.maxHeight, content.implicitHeight);
content.active = Qt.binding(() => root.shouldBeActive || root.visible); content.active = Qt.binding(() => root.shouldBeActive || root.visible);
content.visible = true; content.visible = true;
if (showAnim.running) {
showAnim.stop();
showAnim.start();
}
} }
} }
} }
@@ -119,7 +93,6 @@ Item {
active: false active: false
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top anchors.top: parent.top
visible: false
sourceComponent: Content { sourceComponent: Content {
maxHeight: root.maxHeight maxHeight: root.maxHeight
+11 -51
View File
@@ -20,69 +20,29 @@ Item {
required property Item sidebar required property Item sidebar
required property var visibilities required property var visibilities
implicitHeight: 0 property real offsetScale: shouldBeActive ? 0 : 1
implicitWidth: sidebar.visible ? sidebar.width : Config.utilities.sizes.width
visible: height > 0
states: State { visible: offsetScale < 1
name: "visible" anchors.bottomMargin: (-implicitHeight - 5) * offsetScale
when: root.shouldBeActive implicitHeight: content.implicitHeight + 8 * 2
implicitWidth: sidebar.width * (1 - sidebar.offsetScale)
PropertyChanges { opacity: 1 - offsetScale
root.implicitHeight: content.implicitHeight + 8 * 2
}
}
transitions: [
Transition {
from: ""
to: "visible"
Behavior on offsetScale {
Anim { Anim {
duration: MaterialEasing.expressiveEffectsTime duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: MaterialEasing.expressiveEffects easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
property: "implicitHeight"
target: root
}
},
Transition {
from: "visible"
to: ""
Anim {
easing.bezierCurve: MaterialEasing.expressiveEffects
property: "implicitHeight"
target: root
}
}
]
onStateChanged: {
if (state === "visible" && timer.running) {
timer.triggered();
timer.stop();
}
}
Timer {
id: timer
interval: 1000
running: true
onTriggered: {
content.active = Qt.binding(() => root.shouldBeActive || root.visible);
content.visible = true;
} }
} }
Loader { Loader {
id: content id: content
active: true
anchors.left: parent.left anchors.left: parent.left
anchors.margins: 8 anchors.margins: 8
anchors.top: parent.top anchors.top: parent.top
visible: false
active: root.shouldBeActive || root.visible
sourceComponent: Content { sourceComponent: Content {
implicitWidth: root.implicitWidth - 8 * 2 implicitWidth: root.implicitWidth - 8 * 2
+11 -32
View File
@@ -12,57 +12,36 @@ Item {
} }
required property var visibilities required property var visibilities
implicitWidth: 0 readonly property bool shouldBeActive: root.visibilities.sidebar && Config.sidebar.enabled
visible: width > 0 property real offsetScale: shouldBeActive ? 0 : 1
states: State { visible: offsetScale < 1
name: "visible" anchors.rightMargin: (-implicitWidth - 5) * offsetScale
when: root.visibilities.sidebar implicitWidth: Config.sidebar.sizes.width
opacity: 1 - offsetScale
PropertyChanges {
root.implicitWidth: Config.sidebar.sizes.width
}
}
transitions: [
Transition {
from: ""
to: "visible"
Behavior on offsetScale {
Anim { Anim {
duration: MaterialEasing.expressiveEffectsTime duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: MaterialEasing.expressiveEffects easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
property: "implicitWidth"
target: root
}
},
Transition {
from: "visible"
to: ""
Anim {
easing.bezierCurve: MaterialEasing.expressiveEffects
property: "implicitWidth"
target: root
} }
} }
]
Loader { Loader {
id: content id: content
active: true
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.bottomMargin: 0 anchors.bottomMargin: 0
anchors.left: parent.left anchors.left: parent.left
anchors.margins: 8 anchors.margins: 8
anchors.top: parent.top anchors.top: parent.top
active: root.shouldBeActive || root.visible
sourceComponent: Content { sourceComponent: Content {
implicitWidth: Config.sidebar.sizes.width - 8 * 2 implicitWidth: Config.sidebar.sizes.width - 8 * 2
props: root.props props: root.props
visibilities: root.visibilities visibilities: root.visibilities
} }
Component.onCompleted: active = Qt.binding(() => (root.visibilities.sidebar && Config.sidebar.enabled) || root.visible)
} }
} }
+4 -3
View File
@@ -6,10 +6,11 @@ Item {
id: root id: root
required property Item panels required property Item panels
required property Item sidebarPanel
required property var visibilities required property var visibilities
implicitHeight: content.implicitHeight implicitHeight: content.implicitHeight
implicitWidth: Math.max(panels.sidebar.width, content.implicitWidth) implicitWidth: content.implicitWidth
visible: height > 0 visible: height > 0
states: State { states: State {
@@ -22,8 +23,8 @@ Item {
} }
transitions: Transition { transitions: Transition {
Anim { Anim {
duration: MaterialEasing.expressiveEffectsTime duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: MaterialEasing.expressiveEffects easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
property: "implicitHeight" property: "implicitHeight"
target: root target: root
} }
+13 -35
View File
@@ -26,40 +26,22 @@ Item {
timer.restart(); timer.restart();
} }
property real offsetScale: shouldBeActive ? 0 : 1
required property bool sidebarOrSessionVisible
property real sidebarOffset: sidebarOrSessionVisible ? 12 : 0
visible: offsetScale < 1
anchors.rightMargin: (-implicitWidth - 5 - sidebarOffset) * offsetScale
implicitWidth: content.implicitWidth
implicitHeight: content.implicitHeight implicitHeight: content.implicitHeight
implicitWidth: 0 opacity: 1 - offsetScale
visible: width > 0
states: State {
name: "visible"
when: root.shouldBeActive
PropertyChanges {
root.implicitWidth: content.implicitWidth
}
}
transitions: [
Transition {
from: ""
to: "visible"
Behavior on offsetScale {
Anim { Anim {
easing.bezierCurve: MaterialEasing.expressiveEffects duration: Appearance.anim.durations.expressiveDefaultSpatial
property: "implicitWidth" easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
target: root
}
},
Transition {
from: "visible"
to: ""
Anim {
easing.bezierCurve: MaterialEasing.expressiveEffects
property: "implicitWidth"
target: root
} }
} }
]
Component.onCompleted: { Component.onCompleted: {
volume = Audio.volume; volume = Audio.volume;
@@ -113,15 +95,14 @@ Item {
} }
} }
CustomClippingRect {
anchors.fill: parent
Loader { Loader {
id: content id: content
anchors.left: parent.left anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
active: root.shouldBeActive || root.visible
sourceComponent: Content { sourceComponent: Content {
brightness: root.brightness brightness: root.brightness
monitor: root.monitor monitor: root.monitor
@@ -131,8 +112,5 @@ Item {
visibilities: root.visibilities visibilities: root.visibilities
volume: root.volume volume: root.volume
} }
Component.onCompleted: active = Qt.binding(() => root.shouldBeActive || root.visible)
}
} }
} }
+12 -56
View File
@@ -9,78 +9,34 @@ Item {
id: root id: root
readonly property real nonAnimHeight: state === "visible" ? (content.item?.nonAnimHeight ?? 0) : 0 readonly property real nonAnimHeight: state === "visible" ? (content.item?.nonAnimHeight ?? 0) : 0
property real offsetScale: shouldBeActive ? 0 : 1
readonly property bool shouldBeActive: root.visibilities.resources
required property PersistentProperties visibilities required property PersistentProperties visibilities
implicitHeight: 0 anchors.topMargin: (-implicitHeight - 5) * offsetScale
implicitWidth: content.implicitWidth clip: true
visible: height > 0 implicitHeight: content.implicitHeight
implicitWidth: content.implicitWidth || 854 // Hard coded fallback for first open
states: State { opacity: 1 - offsetScale
name: "visible" visible: offsetScale < 1
when: root.visibilities.resources
PropertyChanges {
root.implicitHeight: content.implicitHeight
}
}
transitions: [
Transition {
from: ""
to: "visible"
Behavior on offsetScale {
Anim { Anim {
duration: MaterialEasing.expressiveEffectsTime duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: MaterialEasing.expressiveEffects easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
property: "implicitHeight"
target: root
}
},
Transition {
from: "visible"
to: ""
Anim {
easing.bezierCurve: MaterialEasing.expressiveEffects
property: "implicitHeight"
target: root
} }
} }
]
onStateChanged: {
if (state === "visible" && timer.running) {
timer.triggered();
timer.stop();
}
}
Timer {
id: timer
interval: Appearance.anim.durations.extraLarge
running: true
onTriggered: {
content.active = Qt.binding(() => (root.visibilities.resources) || root.visible);
content.visible = true;
}
}
CustomClippingRect {
anchors.fill: parent
Loader { Loader {
id: content id: content
active: true active: root.shouldBeActive || root.visible
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
visible: false
sourceComponent: Content { sourceComponent: Content {
padding: Appearance.padding.normal padding: Appearance.padding.normal
visibilities: root.visibilities visibilities: root.visibilities
} }
} }
}
} }
+5 -174
View File
@@ -18,8 +18,8 @@ Item {
readonly property int topMargin: 0 readonly property int topMargin: 0
required property var wrapper required property var wrapper
implicitHeight: layout.implicitHeight + Appearance.padding.small * 2 implicitHeight: vol.implicitHeight + Appearance.padding.small * 2
implicitWidth: layout.implicitWidth + Appearance.padding.small * 2 implicitWidth: 400 + Appearance.padding.small * 2
CustomRect { CustomRect {
anchors.left: parent.left anchors.left: parent.left
@@ -38,184 +38,15 @@ Item {
} }
} }
ColumnLayout { VolumesTab {
id: layout id: vol
// anchors.centerIn: parent
anchors.left: parent.left anchors.left: parent.left
anchors.margins: Appearance.padding.small anchors.margins: Appearance.padding.small
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.verticalCenter: parent.verticalCenter
implicitWidth: stack.currentItem ? stack.currentItem.childrenRect.height : 0
spacing: 12
RowLayout {
id: tabBar
property int tabHeight: 36
Layout.fillWidth: true
spacing: 6
CustomClippingRect {
Layout.fillWidth: true
Layout.preferredHeight: tabBar.tabHeight
color: stack.currentIndex === 0 ? DynamicColors.palette.m3primary : DynamicColors.tPalette.m3surfaceContainer
radius: root.rounding
StateLayer {
function onClicked(): void {
stack.currentIndex = 0;
} }
CustomText {
anchors.centerIn: parent
color: stack.currentIndex === 0 ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3primary
text: qsTr("Volumes")
}
}
}
CustomClippingRect {
Layout.fillWidth: true
Layout.preferredHeight: tabBar.tabHeight
color: stack.currentIndex === 1 ? DynamicColors.palette.m3primary : DynamicColors.tPalette.m3surfaceContainer
radius: root.rounding
StateLayer {
function onClicked(): void {
stack.currentIndex = 1;
}
CustomText {
anchors.centerIn: parent
color: stack.currentIndex === 1 ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3primary
text: qsTr("Devices")
}
}
}
}
StackLayout {
id: stack
Layout.fillWidth: true
Layout.preferredHeight: currentIndex === 0 ? vol.childrenRect.height : dev.childrenRect.height
currentIndex: 0
// Behavior on Layout.preferredHeight {
// Anim {
// duration: MaterialEasing.expressiveEffectsTime
// easing.bezierCurve: MaterialEasing.expressiveEffects
// }
// }
Behavior on currentIndex {
SequentialAnimation {
ParallelAnimation {
Anim {
duration: MaterialEasing.expressiveEffectsTime
property: "opacity"
target: stack
to: 0
}
Anim {
duration: MaterialEasing.expressiveEffectsTime
property: "scale"
target: stack
to: 0.9
}
}
PropertyAction {
}
ParallelAnimation {
Anim {
duration: MaterialEasing.expressiveEffectsTime
property: "opacity"
target: stack
to: 1
}
Anim {
duration: MaterialEasing.expressiveEffectsTime
property: "scale"
target: stack
to: 1
}
}
}
}
VolumesTab {
id: vol
}
DevicesTab {
id: dev
}
}
}
component DevicesTab: Item {
implicitHeight: deviceColumn.height + Appearance.padding.normal
implicitWidth: deviceColumn.width + Appearance.padding.normal
ColumnLayout {
id: deviceColumn
anchors.centerIn: parent
spacing: 12
ButtonGroup {
id: sinks
}
ButtonGroup {
id: sources
}
CustomText {
font.weight: 500
text: qsTr("Output device")
}
Repeater {
model: Audio.sinks
CustomRadioButton {
required property PwNode modelData
ButtonGroup.group: sinks
checked: Audio.sink?.id === modelData.id
text: modelData.description
onClicked: Audio.setAudioSink(modelData)
}
}
CustomText {
Layout.topMargin: 10
font.weight: 500
text: qsTr("Input device")
}
Repeater {
model: Audio.sources
CustomRadioButton {
required property PwNode modelData
ButtonGroup.group: sources
checked: Audio.source?.id === modelData.id
text: modelData.description
onClicked: Audio.setAudioSource(modelData)
}
}
}
}
component VolumesTab: ColumnLayout { component VolumesTab: ColumnLayout {
spacing: 12 spacing: 12
+1 -1
View File
@@ -25,7 +25,7 @@ CustomClippingRect {
anchors.centerIn: parent anchors.centerIn: parent
height: 200 height: 200
visible: script.values.length === 0 visible: script.values.length === 0
width: 300 width: 600
MaterialIcon { MaterialIcon {
id: noUpdatesIcon id: noUpdatesIcon
+1 -2
View File
@@ -15,6 +15,7 @@ Item {
property real currentCenter property real currentCenter
property alias currentName: popoutState.currentName property alias currentName: popoutState.currentName
property string detachedMode property string detachedMode
readonly property bool isDetached: detachedMode.length > 0
property alias hasCurrent: popoutState.hasCurrent property alias hasCurrent: popoutState.hasCurrent
readonly property real nonAnimHeight: children.find(c => c.shouldBeActive)?.implicitHeight ?? content.implicitHeight readonly property real nonAnimHeight: children.find(c => c.shouldBeActive)?.implicitHeight ?? content.implicitHeight
readonly property real nonAnimWidth: children.find(c => c.shouldBeActive)?.implicitWidth ?? content.implicitWidth readonly property real nonAnimWidth: children.find(c => c.shouldBeActive)?.implicitWidth ?? content.implicitWidth
@@ -50,8 +51,6 @@ Item {
implicitWidth: nonAnimWidth implicitWidth: nonAnimWidth
Behavior on implicitHeight { Behavior on implicitHeight {
enabled: root.offsetScale < 1
Anim { Anim {
duration: root.animLength duration: root.animLength
easing.bezierCurve: root.animCurve easing.bezierCurve: root.animCurve
+1 -1
View File
@@ -1,6 +1,6 @@
//@ pragma UseQApplication //@ pragma UseQApplication
//@ pragma Env QSG_RENDER_LOOP=threaded //@ pragma Env QSG_RENDER_LOOP=threaded
//@ pragma Env QSG_RHI_BACKEND=vulkan // @ pragma Env QSG_RHI_BACKEND=vulkan
//@ pragma Env QSG_USE_SIMPLE_ANIMATION_DRIVER=0 //@ pragma Env QSG_USE_SIMPLE_ANIMATION_DRIVER=0
//@ pragma Env QS_NO_RELOAD_POPUP=1 //@ pragma Env QS_NO_RELOAD_POPUP=1
//@ pragma Env QT_SCALE_FACTOR_ROUNDING_POLICY=Round //@ pragma Env QT_SCALE_FACTOR_ROUNDING_POLICY=Round