diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 7ef497cf..ec385399 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -123,9 +123,13 @@ "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" + "max-text-length-horizontal": { + "description": "Maximum number of characters to show in horizontal bar (0 to hide text)", + "label": "Max text length (horizontal)" + }, + "max-text-length-vertical": { + "description": "Maximum number of characters to show in vertical bar (0 to hide text)", + "label": "Max text length (vertical)" }, "icon": { "description": "Select an icon from the library.", diff --git a/Modules/Bar/Widgets/CustomButton.qml b/Modules/Bar/Widgets/CustomButton.qml index 50b83ad8..e73bad54 100644 --- a/Modules/Bar/Widgets/CustomButton.qml +++ b/Modules/Bar/Widgets/CustomButton.qml @@ -44,11 +44,8 @@ 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 @@ -58,9 +55,9 @@ Item { screen: root.screen oppositeDirection: BarService.getPillDirection(root) icon: _dynamicIcon !== "" ? _dynamicIcon : customIcon - text: shouldShowText ? _dynamicText : "" + text: (!isVerticalBar || currentMaxTextLength > 0) ? _dynamicText : "" density: Settings.data.bar.density - rotateText: isVerticalBar && !hideTextInVerticalBar + rotateText: isVerticalBar && currentMaxTextLength > 0 autoHide: false forceOpen: _dynamicText !== "" tooltipText: { @@ -102,8 +99,19 @@ Item { property string _dynamicIcon: "" property string _dynamicTooltip: "" - // Maximum length for text display before scrolling - readonly property int maxTextLength: 8 + // Maximum length for text display before scrolling (different values for horizontal and vertical) + readonly property var maxTextLength: { + "horizontal": ((widgetSettings && widgetSettings.maxTextLength && widgetSettings.maxTextLength.horizontal !== undefined) ? + widgetSettings.maxTextLength.horizontal : + ((widgetMetadata && widgetMetadata.maxTextLength && widgetMetadata.maxTextLength.horizontal !== undefined) ? + widgetMetadata.maxTextLength.horizontal : + 10)), + "vertical": ((widgetSettings && widgetSettings.maxTextLength && widgetSettings.maxTextLength.vertical !== undefined) ? + widgetSettings.maxTextLength.vertical : + ((widgetMetadata && widgetMetadata.maxTextLength && widgetMetadata.maxTextLength.vertical !== undefined) ? + widgetMetadata.maxTextLength.vertical : + 10)) + } readonly property int _staticDuration: 6 // How many cycles to stay static at start/end // Encapsulated state for scrolling text implementation @@ -115,12 +123,15 @@ Item { "phaseCounter": 0 } + // Current max text length based on bar orientation + readonly property int currentMaxTextLength: isVerticalBar ? maxTextLength.vertical : maxTextLength.horizontal + // Periodically run the text command (if set) Timer { id: refreshTimer interval: Math.max(250, textIntervalMs) repeat: true - running: shouldShowText && !textStream && textCommand && textCommand.length > 0 + running: (!isVerticalBar || currentMaxTextLength > 0) && !textStream && textCommand && textCommand.length > 0 triggeredOnStart: true onTriggered: root.runTextCommand() } @@ -129,7 +140,7 @@ Item { Timer { id: restartTimer interval: 1000 - running: shouldShowText && textStream && !textProc.running + running: (!isVerticalBar || currentMaxTextLength > 0) && textStream && !textProc.running onTriggered: root.runTextCommand() } @@ -140,10 +151,10 @@ Item { repeat: true running: false onTriggered: { - if (_scrollState.needsScrolling && _scrollState.originalText.length > maxTextLength) { + if (_scrollState.needsScrolling && _scrollState.originalText.length > currentMaxTextLength) { // Traditional marquee with pause at beginning and end if (_scrollState.phase === 0) { // Static at beginning - _dynamicText = _scrollState.originalText.substring(0, Math.min(maxTextLength, _scrollState.originalText.length)); + _dynamicText = _scrollState.originalText.substring(0, Math.min(currentMaxTextLength, _scrollState.originalText.length)); _scrollState.phaseCounter++; if (_scrollState.phaseCounter >= _staticDuration) { _scrollState.phaseCounter = 0; @@ -152,12 +163,12 @@ Item { } else if (_scrollState.phase === 1) { // Scrolling _scrollState.offset++; var start = _scrollState.offset; - var end = start + maxTextLength; + var end = start + currentMaxTextLength; - if (start >= _scrollState.originalText.length - maxTextLength) { + if (start >= _scrollState.originalText.length - currentMaxTextLength) { // Reached or passed the end, ensure we show the last part var textEnd = _scrollState.originalText.length; - var textStart = Math.max(0, textEnd - maxTextLength); + var textStart = Math.max(0, textEnd - currentMaxTextLength); _dynamicText = _scrollState.originalText.substring(textStart, textEnd); _scrollState.phase = 2; // Move to static end phase _scrollState.phaseCounter = 0; @@ -167,7 +178,7 @@ Item { } else if (_scrollState.phase === 2) { // Static at end // Ensure end text is displayed correctly var textEnd = _scrollState.originalText.length; - var textStart = Math.max(0, textEnd - maxTextLength); + var textStart = Math.max(0, textEnd - currentMaxTextLength); _dynamicText = _scrollState.originalText.substring(textStart, textEnd); _scrollState.phaseCounter++; if (_scrollState.phaseCounter >= _staticDuration) { @@ -234,10 +245,10 @@ Item { } _scrollState.originalText = text; - _scrollState.needsScrolling = text.length > maxTextLength; + _scrollState.needsScrolling = text.length > currentMaxTextLength && currentMaxTextLength > 0; if (_scrollState.needsScrolling) { // Start with the beginning of the text - _dynamicText = text.substring(0, maxTextLength); + _dynamicText = text.substring(0, currentMaxTextLength); _scrollState.phase = 0; // Start at phase 0 (static beginning) _scrollState.phaseCounter = 0; _scrollState.offset = 0; @@ -268,10 +279,10 @@ Item { } _scrollState.originalText = contentStr; - _scrollState.needsScrolling = contentStr.length > maxTextLength; + _scrollState.needsScrolling = contentStr.length > currentMaxTextLength && currentMaxTextLength > 0; if (_scrollState.needsScrolling) { // Start with the beginning of the text - _dynamicText = contentStr.substring(0, maxTextLength); + _dynamicText = contentStr.substring(0, currentMaxTextLength); _scrollState.phase = 0; // Start at phase 0 (static beginning) _scrollState.phaseCounter = 0; _scrollState.offset = 0; diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/CustomButtonSettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/CustomButtonSettings.qml index dfbebd81..e209471b 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/CustomButtonSettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/CustomButtonSettings.qml @@ -16,7 +16,8 @@ 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 + property int valueMaxTextLengthHorizontal: widgetData?.maxTextLength?.horizontal ?? widgetMetadata?.maxTextLength?.horizontal + property int valueMaxTextLengthVertical: widgetData?.maxTextLength?.vertical ?? widgetMetadata?.maxTextLength?.vertical function saveSettings() { var settings = Object.assign({}, widgetData || {}); @@ -31,7 +32,10 @@ ColumnLayout { settings.textCollapse = textCollapseInput.text; settings.textStream = valueTextStream; settings.parseJson = valueParseJson; - settings.hideTextInVerticalBar = valueHideTextInVerticalBar; + settings.maxTextLength = { + "horizontal": valueMaxTextLengthHorizontal, + "vertical": valueMaxTextLengthVertical + }; settings.textIntervalMs = parseInt(textIntervalInput.text || textIntervalInput.placeholderText, 10); return settings; } @@ -145,11 +149,22 @@ 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 + NSpinBox { + label: I18n.tr("bar.widget-settings.custom-button.max-text-length-horizontal.label", "Max text length (horizontal)") + description: I18n.tr("bar.widget-settings.custom-button.max-text-length-horizontal.description", "Maximum number of characters to show in horizontal bar (0 to hide text)") + from: 0 + to: 100 + value: valueMaxTextLengthHorizontal + onValueChanged: valueMaxTextLengthHorizontal = value + } + + NSpinBox { + label: I18n.tr("bar.widget-settings.custom-button.max-text-length-vertical.label", "Max text length (vertical)") + description: I18n.tr("bar.widget-settings.custom-button.max-text-length-vertical.description", "Maximum number of characters to show in vertical bar (0 to hide text)") + from: 0 + to: 100 + value: valueMaxTextLengthVertical + onValueChanged: valueMaxTextLengthVertical = value } NToggle { diff --git a/Services/UI/BarWidgetRegistry.qml b/Services/UI/BarWidgetRegistry.qml index 50923e27..f9423f68 100644 --- a/Services/UI/BarWidgetRegistry.qml +++ b/Services/UI/BarWidgetRegistry.qml @@ -124,7 +124,10 @@ Singleton { "textIntervalMs": 3000, "textCollapse": "", "parseJson": false, - "hideTextInVerticalBar": false + "maxTextLength": { + "horizontal": 10, + "vertical": 10 + } }, "KeyboardLayout": { "allowUserSettings": true,