diff --git a/Modules/Bar/Bar.qml b/Modules/Bar/Bar.qml index 168c26f..521b84f 100644 --- a/Modules/Bar/Bar.qml +++ b/Modules/Bar/Bar.qml @@ -19,7 +19,7 @@ Variants { readonly property real scaling: modelData ? ScalingService.scale(modelData) : 1.0 active: Settings.isLoaded && modelData && modelData.name ? (Settings.data.bar.monitors.includes(modelData.name) - || (Settings.data.bar.monitors.length === 0)) : false + || (Settings.data.bar.monitors.length === 0)) : false sourceComponent: PanelWindow { screen: modelData || null diff --git a/Modules/Bar/Extras/TrayMenu.qml b/Modules/Bar/Extras/TrayMenu.qml index 54d836c..b8889d8 100644 --- a/Modules/Bar/Extras/TrayMenu.qml +++ b/Modules/Bar/Extras/TrayMenu.qml @@ -22,8 +22,6 @@ NPanel { property bool isSubMenu: false property bool isHovered: false - - function showAt(item, x, y) { if (!item) { Logger.warn("TrayMenu", "anchorItem is undefined, won't show menu.") @@ -36,8 +34,6 @@ NPanel { // Use NPanel's open method instead of PopupWindow's visible open(screen) - - } function hideMenu() { @@ -77,17 +73,17 @@ NPanel { if (menu && opener.children && opener.children.values.length === 0) { // Menu not ready, try again later Qt.callLater(() => { - if (opener.children && opener.children.values.length > 0) { - // Menu is now ready - root.menuItemCount = opener.children.values.length - } - }) + if (opener.children && opener.children.values.length > 0) { + // Menu is now ready + root.menuItemCount = opener.children.values.length + } + }) } else if (opener.children && opener.children.values.length > 0) { root.menuItemCount = opener.children.values.length } } - Flickable { + Flickable { id: flickable anchors.fill: parent anchors.margins: Style.marginS * scaling @@ -95,149 +91,149 @@ NPanel { interactive: true clip: true - // Use a ColumnLayout to handle menu item arrangement - ColumnLayout { - id: columnLayout - width: flickable.width - spacing: 0 + // Use a ColumnLayout to handle menu item arrangement + ColumnLayout { + id: columnLayout + width: flickable.width + spacing: 0 - Repeater { - model: opener.children ? [...opener.children.values] : [] + Repeater { + model: opener.children ? [...opener.children.values] : [] - delegate: Rectangle { - id: entry - required property var modelData + delegate: Rectangle { + id: entry + required property var modelData - Layout.preferredWidth: parent.width - Layout.preferredHeight: { - if (modelData?.isSeparator) { - return 8 * scaling - } else { - // Calculate based on text content - const textHeight = text.contentHeight || (Style.fontSizeS * scaling * 1.2) - return Math.max(28 * scaling, textHeight + (Style.marginS * 2 * scaling)) + Layout.preferredWidth: parent.width + Layout.preferredHeight: { + if (modelData?.isSeparator) { + return 8 * scaling + } else { + // Calculate based on text content + const textHeight = text.contentHeight || (Style.fontSizeS * scaling * 1.2) + return Math.max(28 * scaling, textHeight + (Style.marginS * 2 * scaling)) + } } - } - color: Color.transparent - property var subMenu: null + color: Color.transparent + property var subMenu: null - NDivider { - anchors.centerIn: parent - width: parent.width - (Style.marginM * scaling * 2) - visible: modelData?.isSeparator ?? false - } + NDivider { + anchors.centerIn: parent + width: parent.width - (Style.marginM * scaling * 2) + visible: modelData?.isSeparator ?? false + } - Rectangle { - anchors.fill: parent - color: mouseArea.containsMouse ? Color.mTertiary : Color.transparent - radius: Style.radiusS * scaling - visible: !(modelData?.isSeparator ?? false) - - RowLayout { + Rectangle { anchors.fill: parent - anchors.leftMargin: Style.marginM * scaling - anchors.rightMargin: Style.marginM * scaling - spacing: Style.marginS * scaling + color: mouseArea.containsMouse ? Color.mTertiary : Color.transparent + radius: Style.radiusS * scaling + visible: !(modelData?.isSeparator ?? false) - NText { - id: text - Layout.fillWidth: true - color: (modelData?.enabled - ?? true) ? (mouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurface) : Color.mOnSurfaceVariant - text: modelData?.text !== "" ? modelData?.text.replace(/[\n\r]+/g, ' ') : "..." - font.pointSize: Style.fontSizeS * scaling - verticalAlignment: Text.AlignVCenter - wrapMode: Text.WordWrap + RowLayout { + anchors.fill: parent + anchors.leftMargin: Style.marginM * scaling + anchors.rightMargin: Style.marginM * scaling + spacing: Style.marginS * scaling + + NText { + id: text + Layout.fillWidth: true + color: (modelData?.enabled + ?? true) ? (mouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurface) : Color.mOnSurfaceVariant + text: modelData?.text !== "" ? modelData?.text.replace(/[\n\r]+/g, ' ') : "..." + font.pointSize: Style.fontSizeS * scaling + verticalAlignment: Text.AlignVCenter + wrapMode: Text.WordWrap + } + + Image { + Layout.preferredWidth: Style.marginL * scaling + Layout.preferredHeight: Style.marginL * scaling + source: modelData?.icon ?? "" + visible: (modelData?.icon ?? "") !== "" + fillMode: Image.PreserveAspectFit + } + + NIcon { + text: modelData?.hasChildren ? "menu" : "" + font.pointSize: Style.fontSizeS * scaling + verticalAlignment: Text.AlignVCenter + visible: modelData?.hasChildren ?? false + color: Color.mOnSurface + } } - Image { - Layout.preferredWidth: Style.marginL * scaling - Layout.preferredHeight: Style.marginL * scaling - source: modelData?.icon ?? "" - visible: (modelData?.icon ?? "") !== "" - fillMode: Image.PreserveAspectFit - } + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + enabled: (modelData?.enabled ?? true) && !(modelData?.isSeparator ?? false) && root.visible - NIcon { - text: modelData?.hasChildren ? "menu" : "" - font.pointSize: Style.fontSizeS * scaling - verticalAlignment: Text.AlignVCenter - visible: modelData?.hasChildren ?? false - color: Color.mOnSurface + onClicked: { + if (modelData && !modelData.isSeparator && !modelData.hasChildren) { + modelData.triggered() + root.hideMenu() + } + } + + onEntered: { + if (!root.visible) + return + + // Close all sibling submenus + for (var i = 0; i < columnLayout.children.length; i++) { + const sibling = columnLayout.children[i] + if (sibling !== entry && sibling?.subMenu) { + sibling.subMenu.hideMenu() + sibling.subMenu.destroy() + sibling.subMenu = null + } + } + + // Create submenu if needed + if (modelData?.hasChildren) { + if (entry.subMenu) { + entry.subMenu.hideMenu() + entry.subMenu.destroy() + } + + // Create submenu using the same TrayMenu component + entry.subMenu = Qt.createComponent("TrayMenu.qml").createObject(root, { + "menu": modelData, + "anchorItem": entry, + "anchorX": entry.width, + "anchorY": 0, + "isSubMenu": true + }) + + if (entry.subMenu) { + entry.subMenu.open(screen) + } + } + } + + onExited: { + Qt.callLater(() => { + if (entry.subMenu && !entry.subMenu.isHovered) { + entry.subMenu.hideMenu() + entry.subMenu.destroy() + entry.subMenu = null + } + }) + } } } - MouseArea { - id: mouseArea - anchors.fill: parent - hoverEnabled: true - enabled: (modelData?.enabled ?? true) && !(modelData?.isSeparator ?? false) && root.visible - - onClicked: { - if (modelData && !modelData.isSeparator && !modelData.hasChildren) { - modelData.triggered() - root.hideMenu() - } + Component.onDestruction: { + if (subMenu) { + subMenu.destroy() + subMenu = null } - - onEntered: { - if (!root.visible) - return - - // Close all sibling submenus - for (var i = 0; i < columnLayout.children.length; i++) { - const sibling = columnLayout.children[i] - if (sibling !== entry && sibling?.subMenu) { - sibling.subMenu.hideMenu() - sibling.subMenu.destroy() - sibling.subMenu = null - } - } - - // Create submenu if needed - if (modelData?.hasChildren) { - if (entry.subMenu) { - entry.subMenu.hideMenu() - entry.subMenu.destroy() - } - - // Create submenu using the same TrayMenu component - entry.subMenu = Qt.createComponent("TrayMenu.qml").createObject(root, { - "menu": modelData, - "anchorItem": entry, - "anchorX": entry.width, - "anchorY": 0, - "isSubMenu": true - }) - - if (entry.subMenu) { - entry.subMenu.open(screen) - } - } - } - - onExited: { - Qt.callLater(() => { - if (entry.subMenu && !entry.subMenu.isHovered) { - entry.subMenu.hideMenu() - entry.subMenu.destroy() - entry.subMenu = null - } - }) - } - } - } - - Component.onDestruction: { - if (subMenu) { - subMenu.destroy() - subMenu = null } } } } } } - } } diff --git a/Modules/Bar/Widgets/Tray.qml b/Modules/Bar/Widgets/Tray.qml index 32fb4a7..862b044 100644 --- a/Modules/Bar/Widgets/Tray.qml +++ b/Modules/Bar/Widgets/Tray.qml @@ -132,6 +132,4 @@ Rectangle { } } } - - } diff --git a/Widgets/NPanel.qml b/Widgets/NPanel.qml index 41bf245..2bfc771 100644 --- a/Widgets/NPanel.qml +++ b/Widgets/NPanel.qml @@ -55,7 +55,7 @@ Loader { Logger.warn("NPanel", "Cannot toggle panel: invalid screen object") return } - + if (!active || isClosing) { open(aScreen, buttonItem) } else { @@ -70,7 +70,7 @@ Loader { Logger.warn("NPanel", "Cannot open panel: invalid screen object") return } - + if (aScreen !== null) { screen = aScreen }