mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
Merge pull request #664 from lonerOrz/fix/vertical-bar-text
fix(custom button): Adjust the custom button text display when the bar is vertical
This commit is contained in:
@@ -123,6 +123,10 @@
|
||||
"stream-description": "Geben Sie einen Befehl ein, der kontinuierlich ausgeführt werden soll."
|
||||
},
|
||||
"dynamic-text": "Dynamischer Text",
|
||||
"hide-vertical": {
|
||||
"description": "Wenn aktiviert, wird der Text aus der Befehlsausgabe nicht angezeigt, wenn sich die Leiste in einem vertikalen Layout befindet (links oder rechts).",
|
||||
"label": "Text in vertikaler Leiste ausblenden"
|
||||
},
|
||||
"icon": {
|
||||
"description": "Symbol aus der Bibliothek auswählen.",
|
||||
"label": "Symbol"
|
||||
|
||||
@@ -123,6 +123,10 @@
|
||||
"stream-description": "Enter a command to run continuously."
|
||||
},
|
||||
"dynamic-text": "Dynamic text",
|
||||
"hide-vertical": {
|
||||
"description": "If enabled, the text from the command output will not be shown when the bar is in a vertical layout (left or right).",
|
||||
"label": "Hide text in vertical bar"
|
||||
},
|
||||
"icon": {
|
||||
"description": "Select an icon from the library.",
|
||||
"label": "Icon"
|
||||
|
||||
@@ -123,6 +123,10 @@
|
||||
"stream-description": "Introduce un comando para ejecutar continuamente."
|
||||
},
|
||||
"dynamic-text": "Texto dinámico",
|
||||
"hide-vertical": {
|
||||
"description": "Si está activado, el texto de la salida del comando no se mostrará cuando la barra esté en un diseño vertical (izquierda o derecha).",
|
||||
"label": "Ocultar texto en barra vertical"
|
||||
},
|
||||
"icon": {
|
||||
"description": "Selecciona un icono de la biblioteca.",
|
||||
"label": "Icono"
|
||||
|
||||
@@ -123,6 +123,10 @@
|
||||
"stream-description": "Entrez une commande à exécuter en continu."
|
||||
},
|
||||
"dynamic-text": "Texte dynamique",
|
||||
"hide-vertical": {
|
||||
"description": "Si activé, le texte de la sortie de la commande ne sera pas affiché lorsque la barre est en disposition verticale (gauche ou droite).",
|
||||
"label": "Masquer le texte dans la barre verticale"
|
||||
},
|
||||
"icon": {
|
||||
"description": "Sélectionnez une icône dans la bibliothèque.",
|
||||
"label": "Icône"
|
||||
|
||||
@@ -123,6 +123,10 @@
|
||||
"stream-description": "Insira um comando para executar continuamente."
|
||||
},
|
||||
"dynamic-text": "Texto dinâmico",
|
||||
"hide-vertical": {
|
||||
"description": "Se ativado, o texto da saída do comando não será exibido quando a barra estiver em um layout vertical (esquerda ou direita).",
|
||||
"label": "Ocultar texto na barra vertical"
|
||||
},
|
||||
"icon": {
|
||||
"description": "Selecione um ícone da biblioteca.",
|
||||
"label": "Ícone"
|
||||
|
||||
@@ -123,6 +123,10 @@
|
||||
"stream-description": "Sürekli çalıştırılacak bir komut girin."
|
||||
},
|
||||
"dynamic-text": "Dinamik metin",
|
||||
"hide-vertical": {
|
||||
"description": "Etkinleştirilirse, komut çıktısındaki metin, çubuk dikey düzende (sol veya sağ) olduğunda gösterilmeyecektir.",
|
||||
"label": "Dikey çubukta metni gizle"
|
||||
},
|
||||
"icon": {
|
||||
"description": "Kütüphaneden bir ikon seçin.",
|
||||
"label": "İkon"
|
||||
|
||||
@@ -123,6 +123,10 @@
|
||||
"stream-description": "Введіть команду для безперервного запуску."
|
||||
},
|
||||
"dynamic-text": "Динамічний текст",
|
||||
"hide-vertical": {
|
||||
"description": "Якщо увімкнено, текст з виводу команди не відображатиметься, коли панель знаходиться у вертикальному розташуванні (ліворуч або праворуч).",
|
||||
"label": "Приховати текст у вертикальній панелі"
|
||||
},
|
||||
"icon": {
|
||||
"description": "Вибрати значок з бібліотеки.",
|
||||
"label": "Значок"
|
||||
|
||||
@@ -123,6 +123,10 @@
|
||||
"stream-description": "输入一个要持续运行的命令。"
|
||||
},
|
||||
"dynamic-text": "动态文本",
|
||||
"hide-vertical": {
|
||||
"description": "如果启用,当栏处于垂直布局(左或右)时,将不显示命令输出的文本。",
|
||||
"label": "在垂直栏中隐藏文本"
|
||||
},
|
||||
"icon": {
|
||||
"description": "从库中选择图标。",
|
||||
"label": "图标"
|
||||
|
||||
@@ -17,6 +17,7 @@ Item {
|
||||
property bool forceClose: false
|
||||
property bool oppositeDirection: false
|
||||
property bool hovered: false
|
||||
property bool rotateText: false
|
||||
|
||||
readonly property string barPosition: Settings.data.bar.position
|
||||
readonly property bool isVerticalBar: barPosition === "left" || barPosition === "right"
|
||||
@@ -52,6 +53,7 @@ Item {
|
||||
oppositeDirection: root.oppositeDirection
|
||||
hovered: root.hovered
|
||||
density: root.density
|
||||
rotateText: root.rotateText
|
||||
onShown: root.shown()
|
||||
onHidden: root.hidden()
|
||||
onEntered: root.entered()
|
||||
|
||||
@@ -18,6 +18,7 @@ Item {
|
||||
property bool forceClose: false
|
||||
property bool oppositeDirection: false
|
||||
property bool hovered: false
|
||||
property bool rotateText: false
|
||||
|
||||
// Bar position detection for pill direction
|
||||
readonly property string barPosition: Settings.data.bar.position
|
||||
@@ -48,8 +49,8 @@ Item {
|
||||
readonly property int pillHeight: buttonSize
|
||||
readonly property int pillPaddingVertical: 3 * 2 // Very precise adjustment don't replace by Style.margin
|
||||
readonly property int pillOverlap: Math.round(buttonSize * 0.5)
|
||||
readonly property int maxPillWidth: buttonSize
|
||||
readonly property int maxPillHeight: Math.max(1, Math.round(textItem.implicitHeight + pillPaddingVertical * 4))
|
||||
readonly property int maxPillWidth: rotateText ? Math.max(buttonSize, Math.round(textItem.implicitHeight + pillPaddingVertical * 2)) : buttonSize
|
||||
readonly property int maxPillHeight: rotateText ? Math.max(1, Math.round(textItem.implicitWidth + pillPaddingVertical * 2 + Math.round(iconCircle.height / 4))) : Math.max(1, Math.round(textItem.implicitHeight + pillPaddingVertical * 4))
|
||||
|
||||
readonly property real iconSize: {
|
||||
switch (root.density) {
|
||||
@@ -109,14 +110,8 @@ Item {
|
||||
id: textItem
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.verticalCenterOffset: {
|
||||
var offset = openDownward ? Math.round(pillPaddingVertical * 0.75) : -Math.round(pillPaddingVertical * 0.75)
|
||||
if (forceOpen) {
|
||||
// If its force open, the icon disc background is the same color as the bg pill move text slightly
|
||||
offset += oppositeDirection ? -Style.marginXXS : Style.marginXXS
|
||||
}
|
||||
return offset
|
||||
}
|
||||
anchors.verticalCenterOffset: rotateText ? Math.round(iconCircle.height / 4) : getVerticalCenterOffset()
|
||||
rotation: rotateText ? -90 : 0
|
||||
text: root.text + root.suffix
|
||||
family: Settings.data.ui.fontFixed
|
||||
pointSize: textSize
|
||||
@@ -126,8 +121,15 @@ Item {
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: forceOpen ? Color.mOnSurface : Color.mPrimary
|
||||
visible: revealed
|
||||
}
|
||||
|
||||
function getVerticalCenterOffset() {
|
||||
var offset = openDownward ? Math.round(pillPaddingVertical * 0.75) : -Math.round(pillPaddingVertical * 0.75)
|
||||
if (forceOpen) {
|
||||
offset += oppositeDirection ? -Style.marginXXS : Style.marginXXS
|
||||
}
|
||||
return offset
|
||||
}
|
||||
}
|
||||
Behavior on width {
|
||||
enabled: showAnim.running || hideAnim.running
|
||||
NumberAnimation {
|
||||
|
||||
@@ -30,7 +30,8 @@ Item {
|
||||
return {}
|
||||
}
|
||||
|
||||
// Use settings or defaults from BarWidgetRegistry
|
||||
readonly property bool isVerticalBar: Settings.data.bar.position === "left" || Settings.data.bar.position === "right"
|
||||
|
||||
readonly property string customIcon: widgetSettings.icon || widgetMetadata.icon
|
||||
readonly property string leftClickExec: widgetSettings.leftClickExec || widgetMetadata.leftClickExec
|
||||
readonly property string rightClickExec: widgetSettings.rightClickExec || widgetMetadata.rightClickExec
|
||||
@@ -40,8 +41,11 @@ Item {
|
||||
readonly property int textIntervalMs: widgetSettings.textIntervalMs !== undefined ? widgetSettings.textIntervalMs : (widgetMetadata.textIntervalMs || 3000)
|
||||
readonly property string textCollapse: widgetSettings.textCollapse !== undefined ? widgetSettings.textCollapse : (widgetMetadata.textCollapse || "")
|
||||
readonly property bool parseJson: widgetSettings.parseJson !== undefined ? widgetSettings.parseJson : (widgetMetadata.parseJson || false)
|
||||
readonly property bool hideTextInVerticalBar: widgetSettings.hideTextInVerticalBar !== undefined ? widgetSettings.hideTextInVerticalBar : (widgetMetadata.hideTextInVerticalBar || false)
|
||||
readonly property bool hasExec: (leftClickExec || rightClickExec || middleClickExec)
|
||||
|
||||
readonly property bool shouldShowText: !isVerticalBar || !hideTextInVerticalBar
|
||||
|
||||
implicitWidth: pill.width
|
||||
implicitHeight: pill.height
|
||||
|
||||
@@ -50,25 +54,37 @@ Item {
|
||||
|
||||
oppositeDirection: BarService.getPillDirection(root)
|
||||
icon: _dynamicIcon !== "" ? _dynamicIcon : customIcon
|
||||
text: _dynamicText
|
||||
text: shouldShowText ? _dynamicText : ""
|
||||
density: Settings.data.bar.density
|
||||
rotateText: isVerticalBar && !hideTextInVerticalBar
|
||||
autoHide: false
|
||||
forceOpen: _dynamicText !== ""
|
||||
tooltipText: {
|
||||
if (!hasExec) {
|
||||
return "Custom button, configure in settings."
|
||||
} else {
|
||||
var lines = []
|
||||
var tooltipLines = []
|
||||
|
||||
if (hasExec) {
|
||||
if (leftClickExec !== "") {
|
||||
lines.push(`Left click: ${leftClickExec}.`)
|
||||
tooltipLines.push(`Left click: ${leftClickExec}.`)
|
||||
}
|
||||
if (rightClickExec !== "") {
|
||||
lines.push(`Right click: ${rightClickExec}.`)
|
||||
tooltipLines.push(`Right click: ${rightClickExec}.`)
|
||||
}
|
||||
if (middleClickExec !== "") {
|
||||
lines.push(`Middle click: ${middleClickExec}.`)
|
||||
tooltipLines.push(`Middle click: ${middleClickExec}.`)
|
||||
}
|
||||
return lines.join("\n")
|
||||
}
|
||||
|
||||
if (_dynamicTooltip !== "") {
|
||||
if (tooltipLines.length > 0) {
|
||||
tooltipLines.push("")
|
||||
}
|
||||
tooltipLines.push(_dynamicTooltip)
|
||||
}
|
||||
|
||||
if (tooltipLines.length === 0) {
|
||||
return "Custom button, configure in settings."
|
||||
} else {
|
||||
return tooltipLines.join("\n")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,13 +96,14 @@ Item {
|
||||
// Internal state for dynamic text
|
||||
property string _dynamicText: ""
|
||||
property string _dynamicIcon: ""
|
||||
property string _dynamicTooltip: ""
|
||||
|
||||
// Periodically run the text command (if set)
|
||||
Timer {
|
||||
id: refreshTimer
|
||||
interval: Math.max(250, textIntervalMs)
|
||||
repeat: true
|
||||
running: !textStream && textCommand && textCommand.length > 0
|
||||
running: shouldShowText && !textStream && textCommand && textCommand.length > 0
|
||||
triggeredOnStart: true
|
||||
onTriggered: root.runTextCommand()
|
||||
}
|
||||
@@ -95,7 +112,7 @@ Item {
|
||||
Timer {
|
||||
id: restartTimer
|
||||
interval: 1000
|
||||
running: textStream && !textProc.running
|
||||
running: shouldShowText && textStream && !textProc.running
|
||||
onTriggered: root.runTextCommand()
|
||||
}
|
||||
|
||||
@@ -123,38 +140,49 @@ Item {
|
||||
|
||||
function parseDynamicContent(content) {
|
||||
var contentStr = String(content || "").trim()
|
||||
if (contentStr.indexOf("\n") !== -1) {
|
||||
contentStr = contentStr.split("\n")[0]
|
||||
}
|
||||
|
||||
if (parseJson) {
|
||||
var lineToParse = contentStr
|
||||
|
||||
if (!textStream && contentStr.includes('\n')) {
|
||||
const lines = contentStr.split('\n').filter(line => line.trim() !== '')
|
||||
if (lines.length > 0) {
|
||||
lineToParse = lines[lines.length - 1]
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
var parsed = JSON.parse(contentStr)
|
||||
var text = parsed.text || ""
|
||||
const parsed = JSON.parse(lineToParse)
|
||||
const text = parsed.text || ""
|
||||
const icon = parsed.icon || ""
|
||||
const tooltip = parsed.tooltip || ""
|
||||
|
||||
if (checkCollapse(text)) {
|
||||
_dynamicText = ""
|
||||
_dynamicIcon = ""
|
||||
_dynamicTooltip = ""
|
||||
return
|
||||
}
|
||||
|
||||
_dynamicText = text
|
||||
_dynamicIcon = parsed.icon || ""
|
||||
_dynamicIcon = icon
|
||||
_dynamicTooltip = tooltip
|
||||
return
|
||||
} catch (e) {
|
||||
|
||||
// Not a valid JSON, treat as plain text
|
||||
Logger.w("CustomButton", `Failed to parse JSON. Content: "${lineToParse}"`)
|
||||
}
|
||||
}
|
||||
|
||||
if (checkCollapse(contentStr)) {
|
||||
_dynamicText = ""
|
||||
_dynamicIcon = ""
|
||||
_dynamicTooltip = ""
|
||||
return
|
||||
}
|
||||
|
||||
_dynamicText = contentStr
|
||||
_dynamicIcon = ""
|
||||
_dynamicTooltip = ""
|
||||
}
|
||||
|
||||
function checkCollapse(text) {
|
||||
|
||||
@@ -15,6 +15,7 @@ ColumnLayout {
|
||||
property string valueIcon: widgetData.icon !== undefined ? widgetData.icon : widgetMetadata.icon
|
||||
property bool valueTextStream: widgetData.textStream !== undefined ? widgetData.textStream : widgetMetadata.textStream
|
||||
property bool valueParseJson: widgetData.parseJson !== undefined ? widgetData.parseJson : widgetMetadata.parseJson
|
||||
property bool valueHideTextInVerticalBar: widgetData.hideTextInVerticalBar !== undefined ? widgetData.hideTextInVerticalBar : widgetMetadata.hideTextInVerticalBar
|
||||
|
||||
function saveSettings() {
|
||||
var settings = Object.assign({}, widgetData || {})
|
||||
@@ -26,6 +27,7 @@ ColumnLayout {
|
||||
settings.textCollapse = textCollapseInput.text
|
||||
settings.textStream = valueTextStream
|
||||
settings.parseJson = valueParseJson
|
||||
settings.hideTextInVerticalBar = valueHideTextInVerticalBar
|
||||
settings.textIntervalMs = parseInt(textIntervalInput.text || textIntervalInput.placeholderText, 10)
|
||||
return settings
|
||||
}
|
||||
@@ -94,6 +96,13 @@ ColumnLayout {
|
||||
label: I18n.tr("bar.widget-settings.custom-button.dynamic-text")
|
||||
}
|
||||
|
||||
NToggle {
|
||||
label: I18n.tr("bar.widget-settings.custom-button.hide-vertical.label", "Hide text in vertical bar")
|
||||
description: I18n.tr("bar.widget-settings.custom-button.hide-vertical.description", "If enabled, the text from the command output will not be shown when the bar is in a vertical layout (left or right).")
|
||||
checked: valueHideTextInVerticalBar
|
||||
onToggled: checked => valueHideTextInVerticalBar = checked
|
||||
}
|
||||
|
||||
NToggle {
|
||||
id: textStreamInput
|
||||
label: I18n.tr("bar.widget-settings.custom-button.text-stream.label")
|
||||
|
||||
@@ -99,7 +99,8 @@ Singleton {
|
||||
"textStream": false,
|
||||
"textIntervalMs": 3000,
|
||||
"textCollapse": "",
|
||||
"parseJson": false
|
||||
"parseJson": false,
|
||||
"hideTextInVerticalBar": false
|
||||
},
|
||||
"KeyboardLayout": {
|
||||
"allowUserSettings": true,
|
||||
|
||||
Reference in New Issue
Block a user