nova-shell/shell/modules/BarModule.qml

118 lines
3.4 KiB
QML

import QtQuick
import Quickshell
import "." as M
import "../services" as S
// Unified base component for all bar modules.
// Provides: tooltip on hover, panel state management, OSD flash support.
//
// On tap: toggles _panelOpen and emits tapped(). Modules that want custom tap
// behavior connect onTapped to their action (the toggle still happens).
//
// Panel modules set panelComponent + panel config properties. BarModule owns the
// HoverPanel internally - modules never interact with it directly.
// For content resize grace, call keepPanelOpen(ms).
Row {
id: root
property bool active: true
opacity: active ? 1 : 0
visible: opacity > 0
property string tooltip: ""
property bool _hovered: false
property color accentColor: parent?.accentColor ?? S.Theme.base05
property int cursorShape: Qt.PointingHandCursor
// Panel state
property bool _panelOpen: false
property bool _osdActive: false
readonly property bool _showPanel: _panelOpen || _osdActive
// Panel configuration - set by modules that have applets
property Component panelComponent: null
property string panelNamespace: "nova-panel"
property real panelContentWidth: 220
signal tapped
function flashPanel() {
_osdActive = true;
_osdTimer.restart();
}
function dismissPanel() {
_panelOpen = false;
_osdActive = false;
_osdTimer.stop();
}
function keepPanelOpen(ms) {
if (_panelLoader.item)
_panelLoader.item.keepOpen(ms);
}
Timer {
id: _osdTimer
interval: 1500
onTriggered: if (!root._panelOpen)
root._osdActive = false
}
on_PanelOpenChanged: {
if (_panelOpen)
M.TooltipState.visible = false;
}
HoverHandler {
cursorShape: root.cursorShape
onHoveredChanged: {
root._hovered = hovered;
if (hovered && root.tooltip !== "" && !root._panelOpen) {
M.TooltipState.text = root.tooltip;
M.TooltipState.itemX = root.mapToGlobal(root.width / 2, 0).x - (QsWindow.window?.screen?.x ?? 0);
M.TooltipState.screen = QsWindow.window?.screen ?? null;
M.TooltipState.accentColor = root.accentColor;
M.TooltipState.visible = true;
} else if (!hovered && root.tooltip !== "") {
M.TooltipState.visible = false;
}
}
}
TapHandler {
onTapped: {
root._panelOpen = !root._panelOpen;
root.tapped();
}
}
onTooltipChanged: if (_hovered && tooltip !== "" && !_panelOpen)
M.TooltipState.text = tooltip
Behavior on opacity {
NumberAnimation {
duration: 150
}
}
// HoverPanel - only created when module provides panelComponent
LazyLoader {
id: _panelLoader
active: root.panelComponent !== null
M.HoverPanel {
showPanel: root._showPanel
screen: QsWindow.window?.screen ?? null
anchorItem: root
accentColor: root.accentColor
panelNamespace: root.panelNamespace
contentWidth: root.panelContentWidth
onDismissed: root.dismissPanel()
Loader {
width: root.panelContentWidth
sourceComponent: root.panelComponent
}
}
}
}