Introduces a new `WindowControls` component in the desktop top bar with minimize, maximize/restore, and close actions for the focused window. `WindowService` now exposes focused-window presence/maximized state plus focused-window convenience actions to support this UI. Also extends Nebula UI with a reusable `NebulaToolTip`, keyboard/pressed-state support in `NebulaIconButton`, new window-control glyphs in `NebulaIcon`, and theme tokens for pressed/danger hover states, with CMake and README updates to register/document the new components.
99 lines
2.3 KiB
QML
99 lines
2.3 KiB
QML
import QtQuick
|
|
import QtQuick.Window
|
|
|
|
Item {
|
|
id: root
|
|
|
|
property string text: ""
|
|
property bool active: false
|
|
property int delay: 550
|
|
property int timeout: 4000
|
|
|
|
width: 0
|
|
height: 0
|
|
enabled: false
|
|
Accessible.ignored: true
|
|
|
|
Timer {
|
|
id: showTimer
|
|
interval: root.delay
|
|
repeat: false
|
|
onTriggered: root.open()
|
|
}
|
|
|
|
Timer {
|
|
id: hideTimer
|
|
interval: root.timeout
|
|
repeat: false
|
|
onTriggered: tip.visible = false
|
|
}
|
|
|
|
Window {
|
|
id: tip
|
|
flags: Qt.Popup | Qt.ToolTip | Qt.FramelessWindowHint | Qt.WindowDoesNotAcceptFocus
|
|
color: "transparent"
|
|
visible: false
|
|
width: Math.ceil(tipText.implicitWidth) + 16
|
|
height: Math.ceil(tipText.implicitHeight) + 10
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
radius: Theme.radiusSmall
|
|
color: Theme.surfaceRaised
|
|
border.color: Theme.borderStrong
|
|
border.width: 1
|
|
|
|
Text {
|
|
id: tipText
|
|
anchors.centerIn: parent
|
|
text: root.text
|
|
color: Theme.textPrimary
|
|
font.family: Theme.fontFamily
|
|
font.pixelSize: Theme.fontSizeSmall
|
|
}
|
|
}
|
|
}
|
|
|
|
onActiveChanged: root.sync()
|
|
onTextChanged: {
|
|
if (tip.visible)
|
|
root.place()
|
|
else
|
|
root.sync()
|
|
}
|
|
|
|
function sync() {
|
|
if (root.active && root.text.length > 0) {
|
|
showTimer.restart()
|
|
return
|
|
}
|
|
showTimer.stop()
|
|
hideTimer.stop()
|
|
tip.visible = false
|
|
}
|
|
|
|
function open() {
|
|
if (!root.active || root.text.length === 0)
|
|
return
|
|
const host = root.parent
|
|
if (!host)
|
|
return
|
|
const win = host.Window.window
|
|
if (win)
|
|
tip.transientParent = win
|
|
root.place()
|
|
tip.visible = true
|
|
hideTimer.restart()
|
|
}
|
|
|
|
function place() {
|
|
const host = root.parent
|
|
if (!host)
|
|
return
|
|
const pos = host.mapToGlobal(host.width / 2, host.height + 6)
|
|
const screenWidth = Screen.width
|
|
tip.x = Math.round(Math.max(8, Math.min(pos.x - tip.width / 2, screenWidth - tip.width - 8)))
|
|
tip.y = Math.round(pos.y)
|
|
}
|
|
}
|