forked from qt-creator/qt-creator
QmlDesigner: Add RGB und HSV picker
* Add modes to color picker * Add color picker for RGBA mode * Add color picker for HSVA mode * Add luminance slider for RGBA mode Change-Id: I0bb1dbb67b7c18d156eee0d4e07cfa942162f832 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
committed by
Henning Gründl
parent
4895eb346a
commit
6fef74a8cb
@@ -413,7 +413,7 @@ SecondColumnLayout {
|
||||
id: transparentIndicator
|
||||
icon: StudioTheme.Constants.transparent
|
||||
pixelSize: StudioTheme.Values.myIconFontSize * 1.4
|
||||
tooltip: qsTr("Transparent TODO")
|
||||
tooltip: qsTr("Transparent")
|
||||
onClicked: {
|
||||
colorPicker.alpha = 0
|
||||
colorPicker.updateColor()
|
||||
@@ -575,22 +575,29 @@ SecondColumnLayout {
|
||||
onRightMouseButtonClicked: contextMenu.popup(colorPicker)
|
||||
|
||||
onColorInvalidated: {
|
||||
if (colorPicker.saturation > 0.0 && colorPicker.lightness > 0.0) {
|
||||
hueSpinBox.value = colorPicker.hue
|
||||
switch (colorPicker.mode) {
|
||||
case ColorPicker.Mode.HSLA:
|
||||
hslHueSpinBox.value = colorPicker.hue
|
||||
hslSaturationSpinBox.value = colorPicker.saturationHSL
|
||||
hslLightnessSpinBox.value = colorPicker.lightness
|
||||
hslAlphaSpinBox.value = colorPicker.alpha
|
||||
break
|
||||
|
||||
case ColorPicker.Mode.RGBA:
|
||||
redSpinBox.value = (colorPicker.color.r * 255)
|
||||
greenSpinBox.value = (colorPicker.color.g * 255)
|
||||
blueSpinBox.value = (colorPicker.color.b * 255)
|
||||
rgbAlphaSpinBox.value = (colorPicker.alpha * 255)
|
||||
break
|
||||
|
||||
case ColorPicker.Mode.HSVA:
|
||||
default:
|
||||
hsvHueSpinBox.value = colorPicker.hue
|
||||
hsvSaturationSpinBox.value = colorPicker.saturationHSV
|
||||
hsvValueSpinBox.value = colorPicker.value
|
||||
hsvAlphaSpinBox.value = colorPicker.alpha
|
||||
break
|
||||
}
|
||||
|
||||
if (colorPicker.lightness > 0.0)
|
||||
saturationSpinBox.value = colorPicker.saturation
|
||||
else
|
||||
colorPicker.saturation = saturationSpinBox.value
|
||||
|
||||
lightnessSpinBox.value = colorPicker.lightness
|
||||
hslaAlphaSpinBox.value = colorPicker.alpha
|
||||
|
||||
redSpinBox.value = (colorPicker.color.r * 255)
|
||||
greenSpinBox.value = (colorPicker.color.g * 255)
|
||||
blueSpinBox.value = (colorPicker.color.b * 255)
|
||||
rgbaAlphaSpinBox.value = (colorPicker.alpha * 255)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -766,29 +773,22 @@ SecondColumnLayout {
|
||||
+ 4 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
||||
width: implicitWidth
|
||||
actionIndicatorVisible: false
|
||||
model: ["RGBA", "HSLA"]
|
||||
onActivated: {
|
||||
switch (colorMode.currentText) {
|
||||
case "RGBA":
|
||||
rgbaRow.visible = true
|
||||
hslaRow.visible = false
|
||||
break
|
||||
case "HSLA":
|
||||
rgbaRow.visible = false
|
||||
hslaRow.visible = true
|
||||
break
|
||||
default:
|
||||
console.log("Unknown color mode selected.")
|
||||
rgbaRow.visible = true
|
||||
hslaRow.visible = false
|
||||
}
|
||||
}
|
||||
textRole: "text"
|
||||
valueRole: "value"
|
||||
model: [
|
||||
{ value: ColorPicker.Mode.HSVA, text: "HSVA" },
|
||||
{ value: ColorPicker.Mode.RGBA, text: "RGBA" },
|
||||
{ value: ColorPicker.Mode.HSLA, text: "HSLA" }
|
||||
]
|
||||
|
||||
onActivated: colorPicker.mode = colorMode.currentValue
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: rgbaRow
|
||||
|
||||
visible: colorPicker.mode === ColorPicker.Mode.RGBA
|
||||
Layout.fillWidth: true
|
||||
spacing: StudioTheme.Values.controlGap
|
||||
|
||||
@@ -847,7 +847,7 @@ SecondColumnLayout {
|
||||
}
|
||||
|
||||
DoubleSpinBox {
|
||||
id: rgbaAlphaSpinBox
|
||||
id: rgbAlphaSpinBox
|
||||
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
||||
|
||||
stepSize: 1
|
||||
@@ -856,7 +856,7 @@ SecondColumnLayout {
|
||||
decimals: 0
|
||||
|
||||
onValueModified: {
|
||||
var tmp = rgbaAlphaSpinBox.value / 255.0
|
||||
var tmp = rgbAlphaSpinBox.value / 255.0
|
||||
if (colorPicker.alpha !== tmp && !colorPicker.block) {
|
||||
colorPicker.alpha = tmp
|
||||
colorPicker.updateColor()
|
||||
@@ -868,49 +868,109 @@ SecondColumnLayout {
|
||||
RowLayout {
|
||||
id: hslaRow
|
||||
|
||||
visible: false
|
||||
visible: colorPicker.mode === ColorPicker.Mode.HSLA
|
||||
Layout.fillWidth: true
|
||||
spacing: StudioTheme.Values.controlGap
|
||||
|
||||
DoubleSpinBox {
|
||||
id: hueSpinBox
|
||||
id: hslHueSpinBox
|
||||
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
||||
onValueModified: {
|
||||
if (colorPicker.hue !== hueSpinBox.value && !colorPicker.block) {
|
||||
colorPicker.hue = hueSpinBox.value
|
||||
if (colorPicker.hue !== hslHueSpinBox.value
|
||||
&& !colorPicker.block) {
|
||||
colorPicker.hue = hslHueSpinBox.value
|
||||
colorPicker.updateColor()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DoubleSpinBox {
|
||||
id: saturationSpinBox
|
||||
id: hslSaturationSpinBox
|
||||
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
||||
onValueModified: {
|
||||
if (colorPicker.saturation !== saturationSpinBox.value && !colorPicker.block) {
|
||||
colorPicker.saturation = saturationSpinBox.value
|
||||
if (colorPicker.saturationHSL !== hslSaturationSpinBox.value
|
||||
&& !colorPicker.block) {
|
||||
colorPicker.saturationHSL = hslSaturationSpinBox.value
|
||||
colorPicker.updateColor()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DoubleSpinBox {
|
||||
id: lightnessSpinBox
|
||||
id: hslLightnessSpinBox
|
||||
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
||||
onValueModified: {
|
||||
if (colorPicker.lightness !== lightnessSpinBox.value && !colorPicker.block) {
|
||||
colorPicker.lightness = lightnessSpinBox.value
|
||||
if (colorPicker.lightness !== hslLightnessSpinBox.value
|
||||
&& !colorPicker.block) {
|
||||
colorPicker.lightness = hslLightnessSpinBox.value
|
||||
colorPicker.updateColor()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DoubleSpinBox {
|
||||
id: hslaAlphaSpinBox
|
||||
id: hslAlphaSpinBox
|
||||
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
||||
onValueModified: {
|
||||
if (colorPicker.alpha !== hslaAlphaSpinBox.value && !colorPicker.block) {
|
||||
colorPicker.alpha = hslaAlphaSpinBox.value
|
||||
if (colorPicker.alpha !== hslAlphaSpinBox.value
|
||||
&& !colorPicker.block) {
|
||||
colorPicker.alpha = hslAlphaSpinBox.value
|
||||
colorPicker.updateColor()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: hsvaRow
|
||||
|
||||
visible: colorPicker.mode === ColorPicker.Mode.HSVA
|
||||
Layout.fillWidth: true
|
||||
spacing: StudioTheme.Values.controlGap
|
||||
|
||||
DoubleSpinBox {
|
||||
id: hsvHueSpinBox
|
||||
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
||||
onValueModified: {
|
||||
if (colorPicker.hue !== hsvHueSpinBox.value
|
||||
&& !colorPicker.block) {
|
||||
colorPicker.hue = hsvHueSpinBox.value
|
||||
colorPicker.updateColor()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DoubleSpinBox {
|
||||
id: hsvSaturationSpinBox
|
||||
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
||||
onValueModified: {
|
||||
if (colorPicker.saturationHSV !== hsvSaturationSpinBox.value
|
||||
&& !colorPicker.block) {
|
||||
colorPicker.saturationHSV = hsvSaturationSpinBox.value
|
||||
colorPicker.updateColor()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DoubleSpinBox {
|
||||
id: hsvValueSpinBox
|
||||
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
||||
onValueModified: {
|
||||
if (colorPicker.value !== hsvValueSpinBox.value
|
||||
&& !colorPicker.block) {
|
||||
colorPicker.value = hsvValueSpinBox.value
|
||||
colorPicker.updateColor()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DoubleSpinBox {
|
||||
id: hsvAlphaSpinBox
|
||||
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
||||
onValueModified: {
|
||||
if (colorPicker.alpha !== hsvAlphaSpinBox.value
|
||||
&& !colorPicker.block) {
|
||||
colorPicker.alpha = hsvAlphaSpinBox.value
|
||||
colorPicker.updateColor()
|
||||
}
|
||||
}
|
||||
|
@@ -29,15 +29,26 @@ import StudioTheme 1.0 as StudioTheme
|
||||
Column {
|
||||
id: root
|
||||
|
||||
enum Mode {
|
||||
HSVA,
|
||||
RGBA,
|
||||
HSLA
|
||||
}
|
||||
|
||||
property int mode: ColorPicker.Mode.HSVA
|
||||
property color color
|
||||
property real alpha: 1
|
||||
|
||||
property real hue: 0
|
||||
property real saturation: 0
|
||||
property real saturationHSL: 0
|
||||
property real saturationHSV: 0
|
||||
property real lightness: 0
|
||||
property real value: 0
|
||||
|
||||
property real alpha: 1
|
||||
|
||||
property bool achromatic: false
|
||||
|
||||
property int sliderMargins: 6
|
||||
|
||||
property bool block: false
|
||||
|
||||
signal updateColor
|
||||
@@ -46,30 +57,84 @@ Column {
|
||||
|
||||
spacing: 10
|
||||
|
||||
onAlphaChanged: invalidateColor()
|
||||
onSaturationChanged: invalidateColor()
|
||||
onLightnessChanged: invalidateColor()
|
||||
onHueChanged: invalidateColor()
|
||||
onColorChanged: {
|
||||
var myAlpha = root.color.a
|
||||
rgbToHsl(root.color)
|
||||
root.alpha = myAlpha
|
||||
onModeChanged: {
|
||||
switch (root.mode) {
|
||||
case ColorPicker.Mode.RGBA:
|
||||
root.color = Qt.rgba(root.color.r, root.color.g, root.color.b, root.alpha)
|
||||
break
|
||||
case ColorPicker.Mode.HSLA:
|
||||
root.color = Qt.hsla(root.hue, root.saturationHSL, root.lightness, root.alpha)
|
||||
break
|
||||
case ColorPicker.Mode.HSVA:
|
||||
default:
|
||||
root.color = Qt.hsva(root.hue, root.saturationHSV, root.value, root.alpha)
|
||||
break
|
||||
}
|
||||
|
||||
gradientOverlay.requestPaint()
|
||||
}
|
||||
|
||||
onHueChanged: {
|
||||
if (root.mode === ColorPicker.Mode.HSLA)
|
||||
root.color.hslHue = root.hue
|
||||
else
|
||||
root.color.hsvHue = root.hue
|
||||
}
|
||||
onSaturationHSLChanged: {
|
||||
root.color.hslSaturation = root.saturationHSL
|
||||
invalidateColor()
|
||||
}
|
||||
onSaturationHSVChanged: {
|
||||
root.color.hsvSaturation = root.saturationHSV
|
||||
}
|
||||
onLightnessChanged: {
|
||||
root.color.hslLightness = root.lightness
|
||||
}
|
||||
onValueChanged: {
|
||||
root.color.hsvValue = root.value
|
||||
}
|
||||
onAlphaChanged: invalidateColor()
|
||||
onColorChanged: invalidateColor()
|
||||
|
||||
function invalidateColor() {
|
||||
if (root.block)
|
||||
return
|
||||
|
||||
root.block = true
|
||||
|
||||
root.color = Qt.hsla(root.hue,
|
||||
root.saturation,
|
||||
root.lightness,
|
||||
root.alpha)
|
||||
if (root.color.hsvSaturation > 0.0
|
||||
&& root.color.hsvValue > 0.0
|
||||
&& root.color.hsvHue !== -1.0)
|
||||
root.hue = root.color.hsvHue
|
||||
|
||||
if (root.saturation > 0.0 && root.lightness > 0.0)
|
||||
hueSlider.value = root.hue
|
||||
if (root.color.hslSaturation > 0.0
|
||||
&& root.color.hslLightness > 0.0
|
||||
&& root.color.hslHue !== -1.0)
|
||||
root.hue = root.color.hslHue
|
||||
|
||||
if (root.color.hslLightness !== 0.0 && root.color.hslLightness !== 1.0 && !root.achromatic)
|
||||
root.saturationHSL = root.color.hslSaturation
|
||||
|
||||
if (root.color.hsvValue !== 0.0 && root.color.hsvValue !== 1.0 && !root.achromatic)
|
||||
root.saturationHSV = root.color.hsvSaturation
|
||||
|
||||
root.lightness = root.color.hslLightness
|
||||
root.value = root.color.hsvValue
|
||||
|
||||
if (root.color.hslLightness === 0.0 || root.color.hslLightness === 1.0
|
||||
|| root.color.hsvValue === 0.0 || root.color.hsvValue === 1.0
|
||||
|| root.color.hsvHue === -1.0 || root.color.hslHue === -1.0)
|
||||
root.achromatic = true
|
||||
else
|
||||
root.achromatic = false
|
||||
|
||||
if (root.mode === ColorPicker.Mode.HSLA)
|
||||
root.color = Qt.hsla(root.hue, root.saturationHSL, root.lightness, root.alpha)
|
||||
else
|
||||
root.color = Qt.hsva(root.hue, root.saturationHSV, root.value, root.alpha)
|
||||
|
||||
luminanceSlider.value = (1.0 - root.value)
|
||||
hueSlider.value = root.hue
|
||||
opacitySlider.value = (1.0 - root.alpha)
|
||||
|
||||
root.colorInvalidated()
|
||||
@@ -77,39 +142,51 @@ Column {
|
||||
root.block = false
|
||||
}
|
||||
|
||||
function rgbToHsl(color) {
|
||||
var r = color.r
|
||||
var g = color.g
|
||||
var b = color.b
|
||||
function drawHSVA(ctx) {
|
||||
for (var row = 0; row < gradientOverlay.height; row++) {
|
||||
var gradient = ctx.createLinearGradient(0, 0, gradientOverlay.width, 0)
|
||||
var v = Math.abs(row - gradientOverlay.height) / gradientOverlay.height
|
||||
|
||||
var max = Math.max(r, g, b), min = Math.min(r, g, b)
|
||||
var h, s, l = (max + min) / 2
|
||||
gradient.addColorStop(0, Qt.hsva(root.hue, 0, v, 1))
|
||||
gradient.addColorStop(1, Qt.hsva(root.hue, 1, v, 1))
|
||||
|
||||
if (max === min) {
|
||||
h = 0
|
||||
s = 0
|
||||
} else {
|
||||
var d = max - min
|
||||
s = l > 0.5 ? d / (2 - max - min) : d / (max + min)
|
||||
switch (max) {
|
||||
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
|
||||
case g: h = (b - r) / d + 2; break;
|
||||
case b: h = (r - g) / d + 4; break;
|
||||
}
|
||||
|
||||
h /= 6
|
||||
ctx.fillStyle = gradient
|
||||
ctx.fillRect(0, row, gradientOverlay.width, 1)
|
||||
}
|
||||
}
|
||||
|
||||
root.block = true
|
||||
function drawRGBA(ctx) {
|
||||
var gradient = ctx.createLinearGradient(0, 0, gradientOverlay.width, 0)
|
||||
gradient.addColorStop(0.000, Qt.rgba(1, 0, 0, 1))
|
||||
gradient.addColorStop(0.167, Qt.rgba(1, 1, 0, 1))
|
||||
gradient.addColorStop(0.333, Qt.rgba(0, 1, 0, 1))
|
||||
gradient.addColorStop(0.500, Qt.rgba(0, 1, 1, 1))
|
||||
gradient.addColorStop(0.667, Qt.rgba(0, 0, 1, 1))
|
||||
gradient.addColorStop(0.833, Qt.rgba(1, 0, 1, 1))
|
||||
gradient.addColorStop(1.000, Qt.rgba(1, 0, 0, 1))
|
||||
|
||||
if (s > 0)
|
||||
root.hue = h
|
||||
ctx.fillStyle = gradient
|
||||
ctx.fillRect(0, 0, gradientOverlay.width, gradientOverlay.height)
|
||||
|
||||
root.saturation = s
|
||||
root.lightness = l
|
||||
gradient = ctx.createLinearGradient(0, 0, 0, gradientOverlay.height)
|
||||
gradient.addColorStop(0.000, Qt.rgba(0, 0, 0, 0))
|
||||
gradient.addColorStop(1.000, Qt.rgba(1, 1, 1, 1))
|
||||
|
||||
root.block = false
|
||||
invalidateColor()
|
||||
ctx.fillStyle = gradient
|
||||
ctx.fillRect(0, 0, gradientOverlay.width, gradientOverlay.height)
|
||||
}
|
||||
|
||||
function drawHSLA(ctx) {
|
||||
for (var row = 0; row < gradientOverlay.height; row++) {
|
||||
var gradient = ctx.createLinearGradient(0, 0, gradientOverlay.width, 0)
|
||||
var l = Math.abs(row - gradientOverlay.height) / gradientOverlay.height
|
||||
|
||||
gradient.addColorStop(0, Qt.hsla(root.hue, 0, l, 1))
|
||||
gradient.addColorStop(1, Qt.hsla(root.hue, 1, l, 1))
|
||||
|
||||
ctx.fillStyle = gradient
|
||||
ctx.fillRect(0, row, gradientOverlay.width, 1)
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@@ -133,26 +210,30 @@ Column {
|
||||
Canvas {
|
||||
id: gradientOverlay
|
||||
|
||||
property real hue: root.hue
|
||||
|
||||
anchors.fill: parent
|
||||
opacity: root.alpha
|
||||
opacity: root.color.a
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
function onHueChanged() { gradientOverlay.requestPaint() }
|
||||
}
|
||||
|
||||
onHueChanged: requestPaint()
|
||||
onPaint: {
|
||||
var ctx = gradientOverlay.getContext('2d')
|
||||
ctx.save()
|
||||
ctx.clearRect(0, 0, gradientOverlay.width, gradientOverlay.height)
|
||||
|
||||
for (var row = 0; row < gradientOverlay.height; row++) {
|
||||
var gradient = ctx.createLinearGradient(0, 0, gradientOverlay.width,0)
|
||||
var l = Math.abs(row - gradientOverlay.height) / gradientOverlay.height
|
||||
|
||||
gradient.addColorStop(0, Qt.hsla(gradientOverlay.hue, 0, l, 1))
|
||||
gradient.addColorStop(1, Qt.hsla(gradientOverlay.hue, 1, l, 1))
|
||||
|
||||
ctx.fillStyle = gradient
|
||||
ctx.fillRect(0, row, gradientOverlay.width, 1)
|
||||
switch (root.mode) {
|
||||
case ColorPicker.Mode.RGBA:
|
||||
root.drawRGBA(ctx)
|
||||
break
|
||||
case ColorPicker.Mode.HSLA:
|
||||
root.drawHSLA(ctx)
|
||||
break
|
||||
case ColorPicker.Mode.HSVA:
|
||||
default:
|
||||
root.drawHSVA(ctx)
|
||||
break
|
||||
}
|
||||
|
||||
ctx.restore()
|
||||
@@ -162,25 +243,41 @@ Column {
|
||||
Canvas {
|
||||
id: pickerCross
|
||||
|
||||
property real cavnasSaturation: root.saturation
|
||||
property real canvasLightness: root.lightness
|
||||
property color strokeStyle: "lightGray"
|
||||
|
||||
opacity: 0.8
|
||||
anchors.fill: parent
|
||||
antialiasing: true
|
||||
|
||||
onCavnasSaturationChanged: requestPaint();
|
||||
onCanvasLightnessChanged: requestPaint();
|
||||
Connections {
|
||||
target: root
|
||||
function onColorInvalidated() { pickerCross.requestPaint() }
|
||||
function onColorChanged() { pickerCross.requestPaint() }
|
||||
function onModeChanged() { pickerCross.requestPaint() }
|
||||
}
|
||||
|
||||
onPaint: {
|
||||
var ctx = pickerCross.getContext('2d')
|
||||
|
||||
ctx.save()
|
||||
|
||||
ctx.clearRect(0, 0, pickerCross.width, pickerCross.height)
|
||||
|
||||
var yy = pickerCross.height -root.lightness * pickerCross.height
|
||||
var xx = root.saturation * pickerCross.width
|
||||
var yy, xx = 0
|
||||
|
||||
switch (root.mode) {
|
||||
case ColorPicker.Mode.RGBA:
|
||||
yy = pickerCross.height - root.saturationHSV * pickerCross.height
|
||||
xx = root.hue * pickerCross.width
|
||||
break
|
||||
case ColorPicker.Mode.HSLA:
|
||||
yy = pickerCross.height - root.lightness * pickerCross.height
|
||||
xx = root.saturationHSL * pickerCross.width
|
||||
break
|
||||
case ColorPicker.Mode.HSVA:
|
||||
default:
|
||||
yy = pickerCross.height - root.value * pickerCross.height
|
||||
xx = root.saturationHSV * pickerCross.width
|
||||
break
|
||||
}
|
||||
|
||||
ctx.strokeStyle = pickerCross.strokeStyle
|
||||
ctx.lineWidth = 1
|
||||
@@ -200,24 +297,37 @@ Column {
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mapMouseArea
|
||||
id: mouseArea
|
||||
|
||||
anchors.fill: parent
|
||||
preventStealing: true
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
|
||||
onPositionChanged: function(mouse) {
|
||||
if (pressed && mouse.buttons === Qt.LeftButton) {
|
||||
if (mouseArea.pressed && mouse.buttons === Qt.LeftButton) {
|
||||
var xx = Math.max(0, Math.min(mouse.x, parent.width))
|
||||
var yy = Math.max(0, Math.min(mouse.y, parent.height))
|
||||
|
||||
root.lightness = 1.0 - yy / parent.height
|
||||
root.saturation = xx / parent.width
|
||||
switch (root.mode) {
|
||||
case ColorPicker.Mode.RGBA:
|
||||
root.saturationHSV = 1.0 - yy / parent.height
|
||||
root.hue = xx / parent.width
|
||||
break
|
||||
case ColorPicker.Mode.HSLA:
|
||||
root.saturationHSL = xx / parent.width
|
||||
root.lightness = 1.0 - yy / parent.height
|
||||
break
|
||||
case ColorPicker.Mode.HSVA:
|
||||
default:
|
||||
root.saturationHSV = xx / parent.width
|
||||
root.value = 1.0 - yy / parent.height
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
onPressed: function(mouse) {
|
||||
if (mouse.button === Qt.LeftButton)
|
||||
positionChanged(mouse)
|
||||
mouseArea.positionChanged(mouse)
|
||||
}
|
||||
onReleased: function(mouse) {
|
||||
if (mouse.button === Qt.LeftButton)
|
||||
@@ -233,10 +343,23 @@ Column {
|
||||
|
||||
HueSlider {
|
||||
id: hueSlider
|
||||
visible: root.mode !== ColorPicker.Mode.RGBA
|
||||
width: parent.width
|
||||
onValueChanged: {
|
||||
if (root.hue !== value)
|
||||
root.hue = value
|
||||
if (root.hue !== hueSlider.value)
|
||||
root.hue = hueSlider.value
|
||||
}
|
||||
onClicked: root.updateColor()
|
||||
}
|
||||
|
||||
LuminanceSlider {
|
||||
id: luminanceSlider
|
||||
visible: root.mode === ColorPicker.Mode.RGBA
|
||||
width: parent.width
|
||||
color: Qt.hsva(root.hue, root.color.hsvSaturation, 1, 1)
|
||||
onValueChanged: {
|
||||
if (root.value !== luminanceSlider.value)
|
||||
root.value = (1.0 - luminanceSlider.value)
|
||||
}
|
||||
onClicked: root.updateColor()
|
||||
}
|
||||
@@ -246,8 +369,8 @@ Column {
|
||||
width: parent.width
|
||||
color: Qt.rgba(root.color.r, root.color.g, root.color.b, 1)
|
||||
onValueChanged: {
|
||||
if (root.alpha !== value)
|
||||
root.alpha = (1.0 - value)
|
||||
if (root.alpha !== opacitySlider.value)
|
||||
root.alpha = (1.0 - opacitySlider.value)
|
||||
}
|
||||
onClicked: root.updateColor()
|
||||
}
|
||||
|
@@ -0,0 +1,121 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.15
|
||||
import StudioTheme 1.0 as StudioTheme
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property real value: 1
|
||||
property real minimum: 0
|
||||
property real maximum: 1
|
||||
property bool pressed: mouseArea.pressed
|
||||
property bool integer: false
|
||||
property color color
|
||||
|
||||
signal clicked
|
||||
|
||||
height: StudioTheme.Values.hueSliderHeight
|
||||
|
||||
function updatePos() {
|
||||
if (root.maximum > root.minimum) {
|
||||
var pos = (track.width - handle.width) * (root.value - root.minimum) / (root.maximum - root.minimum)
|
||||
return Math.min(Math.max(pos, 0), track.width - handle.width)
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: track
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
Image {
|
||||
id: checkerboard
|
||||
anchors.fill: parent
|
||||
source: "images/checkers.png"
|
||||
fillMode: Image.Tile
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
border.color: StudioTheme.Values.themeControlOutline
|
||||
border.width: StudioTheme.Values.border
|
||||
|
||||
gradient: Gradient {
|
||||
orientation: Gradient.Horizontal
|
||||
GradientStop { position: 0.000; color: root.color }
|
||||
GradientStop { position: 1.000; color: "black" }
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: handle
|
||||
width: StudioTheme.Values.hueSliderHandleWidth
|
||||
height: track.height - 4
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
smooth: true
|
||||
color: "transparent"
|
||||
radius: 2
|
||||
border.color: "black"
|
||||
border.width: 1
|
||||
x: root.updatePos()
|
||||
y: 2
|
||||
z: 1
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 1
|
||||
color: "transparent"
|
||||
radius: 1
|
||||
border.color: "white"
|
||||
border.width: 1
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
preventStealing: true
|
||||
|
||||
function calculateValue() {
|
||||
var handleX = Math.max(0, Math.min(mouseArea.mouseX, mouseArea.width))
|
||||
var realValue = (root.maximum - root.minimum) * handleX / mouseArea.width + root.minimum
|
||||
root.value = root.integer ? Math.round(realValue) : realValue
|
||||
}
|
||||
|
||||
onPressed: calculateValue()
|
||||
onReleased: root.clicked()
|
||||
onPositionChanged: {
|
||||
if (pressed)
|
||||
calculateValue()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -45,6 +45,7 @@ Label 2.0 Label.qml
|
||||
LineEdit 2.0 LineEdit.qml
|
||||
LinkIndicator2D 2.0 LinkIndicator2D.qml
|
||||
ListViewComboBox 2.0 ListViewComboBox.qml
|
||||
LuminanceSlider 2.0 LuminanceSlider.qml
|
||||
MarginSection 2.0 MarginSection.qml
|
||||
MultiIconLabel 2.0 MultiIconLabel.qml
|
||||
OpacitySlider 2.0 OpacitySlider.qml
|
||||
|
Reference in New Issue
Block a user