feat: Replace hideTextInVerticalBar with maxTextLength object

- Replace boolean hideTextInVerticalBar with maxTextLength object that has
  separate horizontal and vertical properties for more flexible text length control
- Add NSpinBox controls in settings UI to configure both horizontal and
  vertical max text length independently
- Update CustomButton widget to use new maxTextLength structure and
  implement text scrolling based on direction-specific limits
- Set default values to 10 for both horizontal and vertical (was 20/0)
- Update translations and widget registry metadata accordingly
- When vertical maxTextLength is 0, text is completely hidden (preserving
  original hideTextInVerticalBar: true behavior)

This allows users to set different text length limits for horizontal and
vertical bar orientations, providing more granular control over text display.
This commit is contained in:
loner
2025-11-21 09:07:30 +08:00
parent e549cfcb78
commit 516fc47b68
4 changed files with 63 additions and 30 deletions
+7 -3
View File
@@ -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.",
+30 -19
View File
@@ -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;
@@ -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 {
+4 -1
View File
@@ -124,7 +124,10 @@ Singleton {
"textIntervalMs": 3000,
"textCollapse": "",
"parseJson": false,
"hideTextInVerticalBar": false
"maxTextLength": {
"horizontal": 10,
"vertical": 10
}
},
"KeyboardLayout": {
"allowUserSettings": true,