169 lines
4.5 KiB
QML
169 lines
4.5 KiB
QML
import QtQuick 2.12
|
|
import QtQuick.Controls 2.12
|
|
import QtQuick.Layouts 1.12
|
|
|
|
RowLayout {
|
|
id: root
|
|
|
|
property string label: ""
|
|
property string hex: "#ffffff"
|
|
readonly property color swatchColor: hex
|
|
|
|
signal colorChanged(string hex)
|
|
|
|
readonly property var palette: [
|
|
"#000000", "#333333", "#666666", "#999999", "#cccccc", "#ffffff",
|
|
"#7b007b", "#00007b", "#4a0080", "#990099", "#cc00cc", "#ff66ff",
|
|
"#004400", "#006622", "#00aa44", "#00cc44", "#33ff66", "#aaffaa",
|
|
"#440000", "#881100", "#cc2200", "#ff4400", "#ff8844", "#ffcccc",
|
|
"#003366", "#0066cc", "#0088ff", "#44aaff", "#aaccff", "#ffff00",
|
|
"#ffaa00", "#884400"
|
|
]
|
|
|
|
function normalizeHex(s) {
|
|
if (!s)
|
|
return ""
|
|
s = String(s).trim()
|
|
if (s.charAt(0) !== "#")
|
|
s = "#" + s
|
|
if (/^#[0-9a-fA-F]{3}$/.test(s)) {
|
|
return ("#" + s.charAt(1) + s.charAt(1)
|
|
+ s.charAt(2) + s.charAt(2)
|
|
+ s.charAt(3) + s.charAt(3)).toLowerCase()
|
|
}
|
|
if (/^#[0-9a-fA-F]{6}$/.test(s))
|
|
return s.toLowerCase()
|
|
return ""
|
|
}
|
|
|
|
function pickColor(h) {
|
|
var n = normalizeHex(h)
|
|
if (!n)
|
|
return
|
|
hex = n
|
|
hexField.text = n
|
|
colorChanged(n)
|
|
}
|
|
|
|
Layout.fillWidth: true
|
|
spacing: 10
|
|
|
|
Text {
|
|
text: root.label
|
|
color: "#ffffff"
|
|
Layout.preferredWidth: 150
|
|
visible: root.label !== ""
|
|
}
|
|
|
|
Rectangle {
|
|
id: swatch
|
|
width: 36
|
|
height: 36
|
|
radius: 18
|
|
color: root.swatchColor
|
|
border.color: "#80ffffff"
|
|
border.width: 1
|
|
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
onClicked: {
|
|
hexField.text = root.hex
|
|
pickerPopup.open()
|
|
}
|
|
}
|
|
}
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
text: root.hex
|
|
color: "#cccccc"
|
|
font.pixelSize: 12
|
|
elide: Text.ElideRight
|
|
}
|
|
|
|
Popup {
|
|
id: pickerPopup
|
|
modal: true
|
|
focus: true
|
|
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
|
width: Math.min(300, root.width > 0 ? root.width : 300)
|
|
padding: 12
|
|
|
|
background: Rectangle {
|
|
color: "#161628"
|
|
radius: 6
|
|
border.color: "#80ffffff"
|
|
border.width: 1
|
|
}
|
|
|
|
contentItem: ColumnLayout {
|
|
spacing: 10
|
|
width: parent.width
|
|
|
|
Text {
|
|
Layout.fillWidth: true
|
|
text: root.label !== "" ? root.label : "Цвет"
|
|
color: "#ffffff"
|
|
font.pixelSize: 14
|
|
font.bold: true
|
|
}
|
|
|
|
GridLayout {
|
|
Layout.fillWidth: true
|
|
columns: 6
|
|
rowSpacing: 6
|
|
columnSpacing: 6
|
|
|
|
Repeater {
|
|
model: root.palette
|
|
delegate: Rectangle {
|
|
Layout.preferredWidth: 36
|
|
Layout.preferredHeight: 36
|
|
radius: 6
|
|
color: modelData
|
|
border.color: root.hex === modelData ? "#ffffff" : "#40ffffff"
|
|
border.width: root.hex === modelData ? 2 : 1
|
|
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
onClicked: root.pickColor(modelData)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
spacing: 8
|
|
|
|
Text {
|
|
text: "#"
|
|
color: "#ffffff"
|
|
}
|
|
TextField {
|
|
id: hexField
|
|
Layout.fillWidth: true
|
|
placeholderText: "RRGGBB"
|
|
color: "#ffffff"
|
|
selectByMouse: true
|
|
onEditingFinished: root.pickColor(text)
|
|
}
|
|
Rectangle {
|
|
width: 32
|
|
height: 32
|
|
radius: 4
|
|
color: root.normalizeHex(hexField.text) || root.swatchColor
|
|
border.color: "#80ffffff"
|
|
border.width: 1
|
|
}
|
|
}
|
|
|
|
Button {
|
|
Layout.fillWidth: true
|
|
text: "Готово"
|
|
onClicked: pickerPopup.close()
|
|
}
|
|
}
|
|
}
|
|
}
|