NValueSlider: new component + pimped NSlider with a small gradient and removed rounded corners due to issues.
This commit is contained in:
parent
5ce5659b38
commit
5aa7ff7e91
14 changed files with 266 additions and 441 deletions
|
|
@ -243,24 +243,19 @@ Popup {
|
|||
Layout.preferredWidth: 20 * scaling
|
||||
}
|
||||
|
||||
NSlider {
|
||||
NValueSlider {
|
||||
id: redSlider
|
||||
Layout.fillWidth: true
|
||||
from: 0
|
||||
to: 255
|
||||
value: Math.round(root.selectedColor.r * 255)
|
||||
onMoved: {
|
||||
root.selectedColor = Qt.rgba(value / 255, root.selectedColor.g, root.selectedColor.b, 1)
|
||||
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255)
|
||||
root.currentHue = hsv[0]
|
||||
root.currentSaturation = hsv[1]
|
||||
}
|
||||
}
|
||||
|
||||
NText {
|
||||
text: Math.round(redSlider.value)
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
Layout.preferredWidth: 30 * scaling
|
||||
onMoved: value => {
|
||||
root.selectedColor = Qt.rgba(value / 255, root.selectedColor.g, root.selectedColor.b, 1)
|
||||
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255)
|
||||
root.currentHue = hsv[0]
|
||||
root.currentSaturation = hsv[1]
|
||||
}
|
||||
text: Math.round(value)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -274,25 +269,20 @@ Popup {
|
|||
Layout.preferredWidth: 20 * scaling
|
||||
}
|
||||
|
||||
NSlider {
|
||||
NValueSlider {
|
||||
id: greenSlider
|
||||
Layout.fillWidth: true
|
||||
from: 0
|
||||
to: 255
|
||||
value: Math.round(root.selectedColor.g * 255)
|
||||
onMoved: {
|
||||
root.selectedColor = Qt.rgba(root.selectedColor.r, value / 255, root.selectedColor.b, 1)
|
||||
// Update stored hue and saturation when RGB changes
|
||||
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255)
|
||||
root.currentHue = hsv[0]
|
||||
root.currentSaturation = hsv[1]
|
||||
}
|
||||
}
|
||||
|
||||
NText {
|
||||
text: Math.round(greenSlider.value)
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
Layout.preferredWidth: 30 * scaling
|
||||
onMoved: value => {
|
||||
root.selectedColor = Qt.rgba(root.selectedColor.r, value / 255, root.selectedColor.b, 1)
|
||||
// Update stored hue and saturation when RGB changes
|
||||
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255)
|
||||
root.currentHue = hsv[0]
|
||||
root.currentSaturation = hsv[1]
|
||||
}
|
||||
text: Math.round(value)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -306,25 +296,20 @@ Popup {
|
|||
Layout.preferredWidth: 20 * scaling
|
||||
}
|
||||
|
||||
NSlider {
|
||||
NValueSlider {
|
||||
id: blueSlider
|
||||
Layout.fillWidth: true
|
||||
from: 0
|
||||
to: 255
|
||||
value: Math.round(root.selectedColor.b * 255)
|
||||
onMoved: {
|
||||
root.selectedColor = Qt.rgba(root.selectedColor.r, root.selectedColor.g, value / 255, 1)
|
||||
// Update stored hue and saturation when RGB changes
|
||||
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255)
|
||||
root.currentHue = hsv[0]
|
||||
root.currentSaturation = hsv[1]
|
||||
}
|
||||
}
|
||||
|
||||
NText {
|
||||
text: Math.round(blueSlider.value)
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
Layout.preferredWidth: 30 * scaling
|
||||
onMoved: value => {
|
||||
root.selectedColor = Qt.rgba(root.selectedColor.r, root.selectedColor.g, value / 255, 1)
|
||||
// Update stored hue and saturation when RGB changes
|
||||
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255)
|
||||
root.currentHue = hsv[0]
|
||||
root.currentSaturation = hsv[1]
|
||||
}
|
||||
text: Math.round(value)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -338,7 +323,7 @@ Popup {
|
|||
Layout.preferredWidth: 80 * scaling
|
||||
}
|
||||
|
||||
NSlider {
|
||||
NValueSlider {
|
||||
id: brightnessSlider
|
||||
Layout.fillWidth: true
|
||||
from: 0
|
||||
|
|
@ -347,27 +332,22 @@ Popup {
|
|||
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255)
|
||||
return hsv[2]
|
||||
}
|
||||
onMoved: {
|
||||
var hue = root.currentHue
|
||||
var saturation = root.currentSaturation
|
||||
onMoved: value => {
|
||||
var hue = root.currentHue
|
||||
var saturation = root.currentSaturation
|
||||
|
||||
if (hue === 0 && saturation === 0) {
|
||||
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255)
|
||||
hue = hsv[0]
|
||||
saturation = hsv[1]
|
||||
root.currentHue = hue
|
||||
root.currentSaturation = saturation
|
||||
}
|
||||
if (hue === 0 && saturation === 0) {
|
||||
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255)
|
||||
hue = hsv[0]
|
||||
saturation = hsv[1]
|
||||
root.currentHue = hue
|
||||
root.currentSaturation = saturation
|
||||
}
|
||||
|
||||
var rgb = root.hsvToRgb(hue, saturation, value)
|
||||
root.selectedColor = Qt.rgba(rgb[0] / 255, rgb[1] / 255, rgb[2] / 255, 1)
|
||||
}
|
||||
}
|
||||
|
||||
NText {
|
||||
var rgb = root.hsvToRgb(hue, saturation, value)
|
||||
root.selectedColor = Qt.rgba(rgb[0] / 255, rgb[1] / 255, rgb[2] / 255, 1)
|
||||
}
|
||||
text: Math.round(brightnessSlider.value) + "%"
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
Layout.preferredWidth: 40 * scaling
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,13 +7,12 @@ import qs.Services
|
|||
Slider {
|
||||
id: root
|
||||
|
||||
// Optional color to cut the track beneath the knob (should match surrounding background)
|
||||
property var cutoutColor
|
||||
property var cutoutColor: Color.mSurface
|
||||
property bool snapAlways: true
|
||||
property real heightRatio: 0.75
|
||||
|
||||
readonly property real knobDiameter: Math.round(Style.baseWidgetSize * heightRatio * scaling)
|
||||
readonly property real trackHeight: knobDiameter * 0.5
|
||||
readonly property real trackHeight: knobDiameter * 0.4
|
||||
readonly property real cutoutExtra: Math.round(Style.baseWidgetSize * 0.1 * scaling)
|
||||
|
||||
snapMode: snapAlways ? Slider.SnapAlways : Slider.SnapOnRelease
|
||||
|
|
@ -26,15 +25,38 @@ Slider {
|
|||
implicitHeight: trackHeight
|
||||
width: root.availableWidth
|
||||
height: implicitHeight
|
||||
radius: height / 2
|
||||
radius: 0
|
||||
color: Color.mSurface
|
||||
|
||||
// Animated gradient active track
|
||||
Rectangle {
|
||||
id: activeTrack
|
||||
width: root.visualPosition * parent.width
|
||||
height: parent.height
|
||||
color: Color.mPrimary
|
||||
radius: parent.radius
|
||||
|
||||
// Animated gradient fill
|
||||
gradient: Gradient {
|
||||
orientation: Gradient.Horizontal
|
||||
GradientStop {
|
||||
position: 0.0
|
||||
color: Qt.darker(Color.mPrimary, 1.2)
|
||||
Behavior on color { ColorAnimation { duration: 300 } }
|
||||
}
|
||||
GradientStop {
|
||||
position: 0.5
|
||||
color: Color.mPrimary
|
||||
SequentialAnimation on position {
|
||||
loops: Animation.Infinite
|
||||
NumberAnimation { from: 0.3; to: 0.7; duration: 2000; easing.type: Easing.InOutSine }
|
||||
NumberAnimation { from: 0.7; to: 0.3; duration: 2000; easing.type: Easing.InOutSine }
|
||||
}
|
||||
}
|
||||
GradientStop {
|
||||
position: 1.0
|
||||
color: Qt.lighter(Color.mPrimary, 1.2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Circular cutout
|
||||
|
|
@ -44,8 +66,7 @@ Slider {
|
|||
height: knobDiameter + cutoutExtra
|
||||
radius: width / 2
|
||||
color: root.cutoutColor !== undefined ? root.cutoutColor : Color.mSurface
|
||||
x: Math.max(0, Math.min(parent.width - width, Math.round(root.visualPosition * (parent.width - root.knobDiameter) - cutoutExtra / 2)))
|
||||
y: (parent.height - height) / 2
|
||||
x: root.leftPadding + root.visualPosition * (root.availableWidth - root.knobDiameter) - cutoutExtra / 2
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
|
@ -73,4 +94,4 @@ Slider {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import qs.Commons
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
RowLayout {
|
||||
id: root
|
||||
|
||||
// Properties that mirror NSlider
|
||||
property real from: 0
|
||||
property real to: 1
|
||||
property real value: 0
|
||||
property real stepSize: 0.01
|
||||
property var cutoutColor
|
||||
property bool snapAlways: true
|
||||
property real heightRatio: 0.75
|
||||
property bool showPercentage: true
|
||||
property string suffix: "%"
|
||||
property int decimalPlaces: 0 // 0 for integers, 1 for one decimal place, etc.
|
||||
|
||||
// Signals
|
||||
signal moved(real value)
|
||||
signal pressedChanged(bool pressed)
|
||||
|
||||
spacing: Style.marginS * scaling
|
||||
|
||||
NSlider {
|
||||
id: slider
|
||||
Layout.fillWidth: true
|
||||
from: root.from
|
||||
to: root.to
|
||||
value: root.value
|
||||
stepSize: root.stepSize
|
||||
cutoutColor: root.cutoutColor
|
||||
snapAlways: root.snapAlways
|
||||
heightRatio: root.heightRatio
|
||||
stableWidth: true
|
||||
minWidth: 200 * scaling
|
||||
|
||||
onMoved: root.moved(value)
|
||||
onPressedChanged: root.pressedChanged(pressed)
|
||||
}
|
||||
|
||||
NText {
|
||||
id: percentageLabel
|
||||
visible: root.showPercentage
|
||||
text: {
|
||||
if (root.decimalPlaces === 0) {
|
||||
return Math.round(slider.value * 100) + root.suffix
|
||||
} else {
|
||||
return (slider.value * 100).toFixed(root.decimalPlaces) + root.suffix
|
||||
}
|
||||
}
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.leftMargin: Style.marginS * scaling
|
||||
Layout.preferredWidth: 50 * scaling
|
||||
horizontalAlignment: Text.AlignRight
|
||||
}
|
||||
}
|
||||
48
Widgets/NValueSlider.qml
Normal file
48
Widgets/NValueSlider.qml
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import qs.Commons
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
RowLayout {
|
||||
id: root
|
||||
|
||||
property real from: 0
|
||||
property real to: 1
|
||||
property real value: 0
|
||||
property real stepSize: 0.01
|
||||
property var cutoutColor: Color.mSurface
|
||||
property bool snapAlways: true
|
||||
property real heightRatio: 0.75
|
||||
property string text: ""
|
||||
|
||||
// Signals
|
||||
signal moved(real value)
|
||||
signal pressedChanged(bool pressed, real value)
|
||||
|
||||
spacing: Style.marginL * scaling
|
||||
|
||||
NSlider {
|
||||
id: slider
|
||||
Layout.fillWidth: true
|
||||
from: root.from
|
||||
to: root.to
|
||||
value: root.value
|
||||
stepSize: root.stepSize
|
||||
cutoutColor: root.cutoutColor
|
||||
snapAlways: root.snapAlways
|
||||
heightRatio: root.heightRatio
|
||||
onMoved: root.moved(value)
|
||||
onPressedChanged: root.pressedChanged(pressed, value)
|
||||
}
|
||||
|
||||
NText {
|
||||
visible: root.text !== ""
|
||||
text: root.text
|
||||
font.family: Settings.data.ui.fontFixed
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.preferredWidth: 40 * scaling
|
||||
horizontalAlignment: Text.AlignRight
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue