mirror of
https://github.com/zoriya/noctalia-shell.git
synced 2026-08-15 18:43:59 +00:00
NSpinBox: add text input support
This commit is contained in:
+3
-3
@@ -171,14 +171,14 @@ Singleton {
|
||||
// Detect user's favorite locale - languages
|
||||
for (var i = 0; i < Qt.locale().uiLanguages.length; i++) {
|
||||
const fullUserLang = Qt.locale().uiLanguages[i]
|
||||
|
||||
|
||||
// Try full code match (such as zh CN, en US)
|
||||
if (availableLanguages.includes(fullUserLang)) {
|
||||
Logger.log("I18n", `Exact match found: "${fullUserLang}"`)
|
||||
setLanguage(fullUserLang)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// If full code match fails, try short code matching (such as zh, en)
|
||||
const shortUserLang = fullUserLang.substring(0, 2)
|
||||
if (availableLanguages.includes(shortUserLang)) {
|
||||
@@ -186,7 +186,7 @@ Singleton {
|
||||
setLanguage(shortUserLang)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Logger.log("I18n", `No match for system language: "${fullUserLang}"`)
|
||||
}
|
||||
|
||||
|
||||
+104
-48
@@ -9,10 +9,10 @@ RowLayout {
|
||||
id: root
|
||||
|
||||
// Public properties
|
||||
property alias value: spinBox.value
|
||||
property alias from: spinBox.from
|
||||
property alias to: spinBox.to
|
||||
property alias stepSize: spinBox.stepSize
|
||||
property int value: 0
|
||||
property int from: 0
|
||||
property int to: 100
|
||||
property int stepSize: 1
|
||||
property string suffix: ""
|
||||
property string prefix: ""
|
||||
property string label: ""
|
||||
@@ -22,8 +22,8 @@ RowLayout {
|
||||
property int baseSize: Style.baseWidgetSize
|
||||
|
||||
// Convenience properties for common naming
|
||||
property alias minimum: spinBox.from
|
||||
property alias maximum: spinBox.to
|
||||
property alias minimum: root.from
|
||||
property alias maximum: root.to
|
||||
|
||||
signal entered
|
||||
signal exited
|
||||
@@ -35,13 +35,12 @@ RowLayout {
|
||||
description: root.description
|
||||
}
|
||||
|
||||
// Value
|
||||
// Main spinbox container
|
||||
Rectangle {
|
||||
id: spinBoxContainer
|
||||
|
||||
implicitWidth: 100 * scaling // Wider for better proportions
|
||||
implicitHeight: (root.baseSize - 4) * scaling // Slightly shorter than toggle
|
||||
radius: height * 0.5 // Fully rounded like toggle
|
||||
implicitWidth: 120 * scaling
|
||||
implicitHeight: (root.baseSize - 4) * scaling
|
||||
radius: height * 0.5
|
||||
color: Color.mSurfaceVariant
|
||||
border.color: root.hovering ? Color.mPrimary : Color.mOutline
|
||||
border.width: 1
|
||||
@@ -52,7 +51,7 @@ RowLayout {
|
||||
}
|
||||
}
|
||||
|
||||
// Mouse area for scroll wheel and hover
|
||||
// Mouse area for hover and scroll
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.NoButton
|
||||
@@ -66,10 +65,12 @@ RowLayout {
|
||||
root.exited()
|
||||
}
|
||||
onWheel: wheel => {
|
||||
if (wheel.angleDelta.y > 0 && spinBox.value < spinBox.to) {
|
||||
spinBox.increase()
|
||||
} else if (wheel.angleDelta.y < 0 && spinBox.value > spinBox.from) {
|
||||
spinBox.decrease()
|
||||
if (wheel.angleDelta.y > 0 && root.value < root.to) {
|
||||
let newValue = Math.min(root.to, root.value + root.stepSize)
|
||||
root.value = newValue
|
||||
} else if (wheel.angleDelta.y < 0 && root.value > root.from) {
|
||||
let newValue = Math.max(root.from, root.value - root.stepSize)
|
||||
root.value = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,14 +78,14 @@ RowLayout {
|
||||
// Decrease button (left)
|
||||
Rectangle {
|
||||
id: decreaseButton
|
||||
width: parent.height * 0.8 // Make it circular
|
||||
width: parent.height * 0.8
|
||||
height: parent.height * 0.8
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: parent.height * 0.1
|
||||
radius: width * 0.5 // Perfect circle
|
||||
radius: width * 0.5
|
||||
color: decreaseArea.containsMouse ? Color.mPrimary : "transparent"
|
||||
opacity: root.enabled && spinBox.value > spinBox.from ? 1.0 : 0.3
|
||||
opacity: root.enabled && root.value > root.from ? 1.0 : 0.3
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
@@ -105,22 +106,25 @@ RowLayout {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
enabled: root.enabled && spinBox.value > spinBox.from
|
||||
onClicked: spinBox.decrease()
|
||||
enabled: root.enabled && root.value > root.from
|
||||
onClicked: {
|
||||
let newValue = Math.max(root.from, root.value - root.stepSize)
|
||||
root.value = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Increase button (right)
|
||||
Rectangle {
|
||||
id: increaseButton
|
||||
width: parent.height * 0.8 // Make it circular
|
||||
width: parent.height * 0.8
|
||||
height: parent.height * 0.8
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: parent.height * 0.1
|
||||
radius: width * 0.5 // Perfect circle
|
||||
radius: width * 0.5
|
||||
color: increaseArea.containsMouse ? Color.mPrimary : "transparent"
|
||||
opacity: root.enabled && spinBox.value < spinBox.to ? 1.0 : 0.3
|
||||
opacity: root.enabled && root.value < root.to ? 1.0 : 0.3
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
@@ -140,44 +144,96 @@ RowLayout {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
enabled: root.enabled && spinBox.value < spinBox.to
|
||||
onClicked: spinBox.increase()
|
||||
enabled: root.enabled && root.value < root.to
|
||||
onClicked: {
|
||||
let newValue = Math.min(root.to, root.value + root.stepSize)
|
||||
root.value = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Center value display
|
||||
SpinBox {
|
||||
id: spinBox
|
||||
// Center value display with separate prefix, value, and suffix
|
||||
Rectangle {
|
||||
id: valueContainer
|
||||
anchors.left: decreaseButton.right
|
||||
anchors.right: increaseButton.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.margins: 4 * scaling
|
||||
height: parent.height
|
||||
color: "transparent"
|
||||
|
||||
background: Item {}
|
||||
up.indicator: Item {}
|
||||
down.indicator: Item {}
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 0
|
||||
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
font.family: Settings.data.ui.fontDefault
|
||||
|
||||
from: 0
|
||||
to: 100
|
||||
stepSize: 1
|
||||
editable: false // Only use buttons/scroll
|
||||
enabled: root.enabled
|
||||
|
||||
contentItem: Item {
|
||||
anchors.fill: parent
|
||||
|
||||
NText {
|
||||
anchors.centerIn: parent
|
||||
text: root.prefix + spinBox.value + root.suffix
|
||||
// Prefix text (non-editable)
|
||||
Text {
|
||||
text: root.prefix
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
color: Color.mOnSurface
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
visible: root.prefix !== ""
|
||||
}
|
||||
|
||||
// Editable number input
|
||||
TextInput {
|
||||
id: valueInput
|
||||
text: root.value.toString()
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
color: Color.mOnSurface
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
selectByMouse: true
|
||||
enabled: root.enabled
|
||||
|
||||
// Only allow numeric input within range
|
||||
validator: IntValidator {
|
||||
bottom: root.from
|
||||
top: root.to
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: {
|
||||
applyValue()
|
||||
focus = false
|
||||
}
|
||||
|
||||
Keys.onEscapePressed: {
|
||||
text = root.value.toString()
|
||||
focus = false
|
||||
}
|
||||
|
||||
onFocusChanged: {
|
||||
if (focus) {
|
||||
selectAll()
|
||||
} else {
|
||||
applyValue()
|
||||
}
|
||||
}
|
||||
|
||||
function applyValue() {
|
||||
let newValue = parseInt(text)
|
||||
if (!isNaN(newValue)) {
|
||||
newValue = Math.max(root.from, Math.min(root.to, newValue))
|
||||
root.value = newValue
|
||||
text = root.value.toString()
|
||||
} else {
|
||||
text = root.value.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Suffix text (non-editable)
|
||||
Text {
|
||||
text: root.suffix
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
font.pointSize: Style.fontSizeM * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
color: Color.mOnSurface
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
visible: root.suffix !== ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user