14 changed files with 372 additions and 11 deletions
@ -0,0 +1,321 @@ |
|||
import QtQuick 2.10 |
|||
import QtQuick.Controls 2.3 |
|||
import QtQuick.Controls.Material 2.3 |
|||
import QtQuick.Layouts 1.3 |
|||
import QtGraphicalEffects 1.0 |
|||
import de.skycoder42.QtMvvm.Quick 1.1 |
|||
|
|||
GridLayout { |
|||
id: _colorPicker |
|||
columns: 2 |
|||
rowSpacing: 16 |
|||
|
|||
ColorHelper { |
|||
id: helper |
|||
} |
|||
|
|||
property bool alpha: false |
|||
property color color |
|||
onColorChanged: { |
|||
if(!_p.changing){ |
|||
var hsvColor = _p.rgbToHsv(color); |
|||
_p.changing = true; |
|||
hueSlider.value = hsvColor.h; |
|||
saturationSlider.value = 1 - hsvColor.s; |
|||
valueSlider.value = hsvColor.v; |
|||
_colorEdit.setColor(color); |
|||
_p.changing = false; |
|||
} |
|||
} |
|||
|
|||
QtObject { |
|||
id: _p |
|||
|
|||
property bool changing: false |
|||
readonly property color color: Qt.hsva(hueSlider.position, 1 - saturationSlider.position, valueSlider.position) |
|||
readonly property color hueColor: Qt.hsva(hueSlider.position, 1, 1); |
|||
|
|||
onColorChanged: { |
|||
if(!_p.changing) { |
|||
_p.changing = true; |
|||
_colorPicker.color = _p.color |
|||
_colorEdit.setColor(color); |
|||
_p.changing = false; |
|||
} |
|||
} |
|||
|
|||
function rgbToHsv(rgbColor) { |
|||
var rr, gg, bb, |
|||
r = rgbColor.r, |
|||
g = rgbColor.g, |
|||
b = rgbColor.b, |
|||
h, s, |
|||
v = Math.max(r, g, b), |
|||
diff = v - Math.min(r, g, b), |
|||
diffc = function(c){ |
|||
return (v - c) / 6 / diff + 1 / 2; |
|||
}; |
|||
|
|||
if (diff == 0) { |
|||
h = s = 0; |
|||
} else { |
|||
s = diff / v; |
|||
rr = diffc(r); |
|||
gg = diffc(g); |
|||
bb = diffc(b); |
|||
|
|||
if (r === v) { |
|||
h = bb - gg; |
|||
} else if (g === v) { |
|||
h = (1 / 3) + rr - bb; |
|||
} else if (b === v) { |
|||
h = (2 / 3) + gg - rr; |
|||
} |
|||
|
|||
if (h < 0) { |
|||
h += 1; |
|||
} else if (h > 1) { |
|||
h -= 1; |
|||
} |
|||
} |
|||
|
|||
return { |
|||
h: h, |
|||
s: s, |
|||
v: v |
|||
}; |
|||
} |
|||
} |
|||
|
|||
Rectangle { |
|||
id: colorPreview |
|||
color: _colorPicker.color |
|||
Layout.rowSpan: 3 |
|||
Layout.preferredWidth: hueSlider.height + saturationSlider.height + valueSlider.height + 2 * _colorPicker.rowSpacing |
|||
Layout.maximumWidth: _colorPicker.width/3 |
|||
Layout.fillHeight: true |
|||
|
|||
border.color: helper.text |
|||
border.width: 1 |
|||
} |
|||
|
|||
Slider { |
|||
id: hueSlider |
|||
Layout.fillWidth: true |
|||
Material.accent: "#FF0000" |
|||
from: 0 |
|||
to: 1 |
|||
|
|||
readonly property real handleWidth: 25 |
|||
readonly property real handleHeight: ((handleWidth-1)/2)*3 + 1 |
|||
leftPadding: (handleWidth-1)/2 + 1 |
|||
rightPadding: (handleWidth-1)/2 + 1 |
|||
|
|||
background: LinearGradient { |
|||
x: hueSlider.leftPadding |
|||
y: 0 |
|||
implicitWidth: 200 |
|||
implicitHeight: hueSlider.handleHeight |
|||
width: hueSlider.availableWidth |
|||
height: implicitHeight |
|||
start: Qt.point(0, 0) |
|||
end: Qt.point(width, 0) |
|||
|
|||
Rectangle { |
|||
anchors.fill: parent |
|||
color: "transparent" |
|||
border.color: helper.text |
|||
} |
|||
|
|||
gradient: Gradient { |
|||
GradientStop { |
|||
position: 0.000 |
|||
color: Qt.rgba(1, 0, 0, 1) |
|||
} |
|||
GradientStop { |
|||
position: 0.167 |
|||
color: Qt.rgba(1, 1, 0, 1) |
|||
} |
|||
GradientStop { |
|||
position: 0.333 |
|||
color: Qt.rgba(0, 1, 0, 1) |
|||
} |
|||
GradientStop { |
|||
position: 0.500 |
|||
color: Qt.rgba(0, 1, 1, 1) |
|||
} |
|||
GradientStop { |
|||
position: 0.667 |
|||
color: Qt.rgba(0, 0, 1, 1) |
|||
} |
|||
GradientStop { |
|||
position: 0.833 |
|||
color: Qt.rgba(1, 0, 1, 1) |
|||
} |
|||
GradientStop { |
|||
position: 1.000 |
|||
color: Qt.rgba(1, 0, 0, 1) |
|||
} |
|||
} |
|||
} |
|||
|
|||
handle: Item { |
|||
x: 1 + hueSlider.visualPosition * (hueSlider.availableWidth - 1) |
|||
width: hueSlider.handleWidth |
|||
height: hueSlider.handleHeight |
|||
|
|||
Rectangle { |
|||
anchors.horizontalCenter: parent.horizontalCenter |
|||
anchors.top: parent.top |
|||
anchors.bottom: circle.top |
|||
width: 1 |
|||
color: helper.text |
|||
} |
|||
|
|||
Rectangle { |
|||
id: circle |
|||
anchors.centerIn: parent |
|||
implicitWidth: parent.width |
|||
implicitHeight: parent.width |
|||
radius: parent.width / 2 |
|||
color: Qt.hsva(hueSlider.position, 1, 1) |
|||
border.color: helper.text |
|||
} |
|||
|
|||
Rectangle { |
|||
anchors.horizontalCenter: parent.horizontalCenter |
|||
anchors.top: circle.bottom |
|||
anchors.bottom: parent.bottom |
|||
width: 1 |
|||
color: helper.text |
|||
} |
|||
} |
|||
} |
|||
|
|||
Slider { |
|||
id: saturationSlider |
|||
Layout.fillWidth: true |
|||
from: 0 |
|||
to: 1 |
|||
|
|||
readonly property real handleSize: 24 |
|||
leftPadding: handleSize/2 + 1 |
|||
rightPadding: handleSize/2 + 1 |
|||
|
|||
background: Item { |
|||
x: saturationSlider.leftPadding |
|||
y: saturationSlider.topPadding + (saturationSlider.availableHeight - height) / 2 |
|||
implicitWidth: 200 |
|||
implicitHeight: 6 |
|||
width: saturationSlider.availableWidth |
|||
height: implicitHeight |
|||
|
|||
Rectangle { |
|||
rotation: -90 |
|||
anchors.centerIn: parent |
|||
width: parent.height |
|||
height: parent.width |
|||
radius: 3 |
|||
border.color: helper.text |
|||
|
|||
gradient: Gradient { |
|||
GradientStop { |
|||
position: 0.000 |
|||
color: Qt.hsva(hueSlider.position, 1, 1) |
|||
} |
|||
GradientStop { |
|||
position: 1.000 |
|||
color: Qt.hsva(hueSlider.position, 0, 1) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
handle: Rectangle { |
|||
x: 1 + saturationSlider.visualPosition * saturationSlider.availableWidth |
|||
y: saturationSlider.topPadding + (saturationSlider.availableHeight - height)/2 |
|||
width: saturationSlider.handleSize |
|||
height: saturationSlider.handleSize |
|||
radius: saturationSlider.handleSize/2 |
|||
color: Qt.hsva(hueSlider.position, 1 - saturationSlider.position, 1) |
|||
border.color: helper.text |
|||
} |
|||
} |
|||
|
|||
Slider { |
|||
id: valueSlider |
|||
Layout.fillWidth: true |
|||
from: 0 |
|||
to: 1 |
|||
|
|||
readonly property real handleSize: 24 |
|||
leftPadding: handleSize/2 + 1 |
|||
rightPadding: handleSize/2 + 1 |
|||
|
|||
background: Item { |
|||
x: valueSlider.leftPadding |
|||
y: valueSlider.topPadding + (valueSlider.availableHeight - height) / 2 |
|||
implicitWidth: 200 |
|||
implicitHeight: 6 |
|||
width: valueSlider.availableWidth |
|||
height: implicitHeight |
|||
|
|||
Rectangle { |
|||
rotation: -90 |
|||
anchors.centerIn: parent |
|||
width: parent.height |
|||
height: parent.width |
|||
radius: 3 |
|||
border.color: helper.text |
|||
|
|||
gradient: Gradient { |
|||
GradientStop { |
|||
position: 0.000 |
|||
color: Qt.hsva(hueSlider.position, 1, 0) |
|||
} |
|||
GradientStop { |
|||
position: 1.000 |
|||
color: Qt.hsva(hueSlider.position, 1, 1) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
handle: Rectangle { |
|||
x: 1 + valueSlider.visualPosition * valueSlider.availableWidth |
|||
y: valueSlider.topPadding + (valueSlider.availableHeight - height)/2 |
|||
width: valueSlider.handleSize |
|||
height: valueSlider.handleSize |
|||
radius: valueSlider.handleSize/2 |
|||
color: Qt.hsva(hueSlider.position, 1, valueSlider.position) |
|||
border.color: helper.text |
|||
} |
|||
} |
|||
|
|||
TextField { |
|||
id: _colorEdit |
|||
Layout.columnSpan: 2 |
|||
Layout.fillWidth: true |
|||
selectByMouse: true |
|||
|
|||
validator: RegExpValidator { |
|||
regExp: _colorPicker.alpha ? /^#(?:[0-9a-f]{4}){1,2}$/ : /^#(?:[0-9a-f]{3}){1,2}$/ |
|||
} |
|||
|
|||
property bool _skipSet: false |
|||
function setColor(color) { |
|||
if(_skipSet) |
|||
_skipSet = false; |
|||
else |
|||
text = color; |
|||
} |
|||
|
|||
text: _colorPicker.color |
|||
onTextEdited: { |
|||
if(_colorEdit.acceptableInput) { |
|||
_skipSet = true; |
|||
_colorPicker.color = text; |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,15 @@ |
|||
import QtQuick 2.10 |
|||
import de.skycoder42.QtMvvm.Quick 1.1 as QtMvvm |
|||
|
|||
QtMvvm.MsgDelegate { |
|||
id: _colorDelegate |
|||
|
|||
editDialogType: "QColor" |
|||
indicatorComponent: Rectangle { |
|||
id: colorCircle |
|||
width: 24 |
|||
height: 24 |
|||
radius: height / 2 |
|||
color: inputValue |
|||
} |
|||
} |
@ -0,0 +1,6 @@ |
|||
import de.skycoder42.QtMvvm.Quick 1.1 as QtMvvm |
|||
|
|||
QtMvvm.ColorEdit { |
|||
id: _edit |
|||
property alias inputValue: _edit.color |
|||
} |
Loading…
Reference in new issue