mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
I forgor to add the ColorPicker file
This commit is contained in:
+577
-214
@@ -1,16 +1,25 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import "../Helpers/ColorsConvert.js" as ColorsConvert
|
||||
import qs.Commons
|
||||
import qs.Widgets
|
||||
import qs.Services.UI
|
||||
import "../Helpers/ColorList.js" as ColorList
|
||||
|
||||
Popup {
|
||||
id: root
|
||||
|
||||
property color selectedColor: Color.black
|
||||
property real currentHue: 0
|
||||
property real currentSaturation: 0
|
||||
property string editMode: "r" // Options: "r", "g", "b", "h", "s", "v"
|
||||
|
||||
// Code to deal with Hue when color is achromatic
|
||||
property real stableHue: 0
|
||||
onSelectedColorChanged: {
|
||||
if (selectedColor.hsvHue >= 0) {
|
||||
stableHue = selectedColor.hsvHue;
|
||||
}
|
||||
}
|
||||
readonly property real displayHue: selectedColor.hsvHue < 0 ? stableHue : selectedColor.hsvHue
|
||||
|
||||
signal colorSelected(color color)
|
||||
|
||||
@@ -116,256 +125,610 @@ Popup {
|
||||
}
|
||||
}
|
||||
|
||||
// Hex input
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginM
|
||||
|
||||
NLabel {
|
||||
label: I18n.tr("widgets.color-picker.hex.label")
|
||||
description: I18n.tr("widgets.color-picker.hex.description")
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
NTextInput {
|
||||
text: root.selectedColor.toString().toUpperCase()
|
||||
fontFamily: Settings.data.ui.fontFixed
|
||||
Layout.fillWidth: true
|
||||
onEditingFinished: {
|
||||
if (/^#[0-9A-F]{6}$/i.test(text)) {
|
||||
root.selectedColor = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RGB sliders section
|
||||
// Main Box
|
||||
NBox {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: slidersSection.implicitHeight + Style.marginL * 2
|
||||
Layout.preferredHeight: controlsOutterColumn.implicitHeight + Style.marginL * 2
|
||||
|
||||
ButtonGroup {
|
||||
id: colorValues
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: slidersSection
|
||||
id: controlsOutterColumn
|
||||
anchors.fill: parent
|
||||
anchors.margins: Style.marginL
|
||||
spacing: Style.marginM
|
||||
|
||||
NLabel {
|
||||
label: I18n.tr("widgets.color-picker.rgb.label")
|
||||
description: I18n.tr("widgets.color-picker.rgb.description")
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginM
|
||||
spacing: Style.marginL // Ensure nice gap between Left and Right groups
|
||||
|
||||
NText {
|
||||
text: "R"
|
||||
font.weight: Font.Bold
|
||||
Layout.preferredWidth: 20
|
||||
}
|
||||
|
||||
NValueSlider {
|
||||
id: redSlider
|
||||
// SpinBoxes Column
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
from: 0
|
||||
to: 255
|
||||
value: Math.round(root.selectedColor.r * 255)
|
||||
onMoved: value => {
|
||||
root.selectedColor = Qt.rgba(value / 255, root.selectedColor.g, root.selectedColor.b, 1);
|
||||
var hsv = ColorsConvert.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255);
|
||||
root.currentHue = hsv.h;
|
||||
root.currentSaturation = hsv.s;
|
||||
}
|
||||
text: Math.round(value)
|
||||
}
|
||||
}
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.preferredWidth: 3
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginM
|
||||
// --- RED ---
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginM
|
||||
|
||||
NText {
|
||||
text: "G"
|
||||
font.weight: Font.Bold
|
||||
Layout.preferredWidth: 20
|
||||
}
|
||||
NRadioButton {
|
||||
ButtonGroup.group: colorValues
|
||||
text: "R"
|
||||
font.weight: Font.Bold
|
||||
checked: true
|
||||
onClicked: root.editMode = "r"
|
||||
Layout.fillWidth: false
|
||||
}
|
||||
|
||||
NValueSlider {
|
||||
id: greenSlider
|
||||
Layout.fillWidth: true
|
||||
from: 0
|
||||
to: 255
|
||||
value: Math.round(root.selectedColor.g * 255)
|
||||
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 = ColorsConvert.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255);
|
||||
root.currentHue = hsv.h;
|
||||
root.currentSaturation = hsv.s;
|
||||
}
|
||||
text: Math.round(value)
|
||||
}
|
||||
}
|
||||
NSpinBox {
|
||||
id: redSpinBox
|
||||
from: 0
|
||||
to: 255
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginM
|
||||
|
||||
NText {
|
||||
text: "B"
|
||||
font.weight: Font.Bold
|
||||
Layout.preferredWidth: 20
|
||||
}
|
||||
|
||||
NValueSlider {
|
||||
id: blueSlider
|
||||
Layout.fillWidth: true
|
||||
from: 0
|
||||
to: 255
|
||||
value: Math.round(root.selectedColor.b * 255)
|
||||
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 = ColorsConvert.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255);
|
||||
root.currentHue = hsv.h;
|
||||
root.currentSaturation = hsv.s;
|
||||
}
|
||||
text: Math.round(value)
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginM
|
||||
|
||||
NText {
|
||||
text: I18n.tr("widgets.color-picker.brightness")
|
||||
font.weight: Font.Bold
|
||||
Layout.preferredWidth: 80
|
||||
}
|
||||
|
||||
NValueSlider {
|
||||
id: brightnessSlider
|
||||
Layout.fillWidth: true
|
||||
from: 0
|
||||
to: 100
|
||||
value: {
|
||||
var hsv = ColorsConvert.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255);
|
||||
return hsv.v;
|
||||
onValueChanged: {
|
||||
if (!selectedSlider.pressed && !fieldMouse.pressed && !hexInput.activeFocus && value !== Math.round(root.selectedColor.r * 255)) {
|
||||
root.selectedColor = Qt.rgba(value / 255, root.selectedColor.g, root.selectedColor.b, 1);
|
||||
}
|
||||
}
|
||||
Binding {
|
||||
target: redSpinBox
|
||||
property: "value"
|
||||
value: Math.round(root.selectedColor.r * 255)
|
||||
}
|
||||
}
|
||||
}
|
||||
onMoved: value => {
|
||||
var hue = root.currentHue;
|
||||
var saturation = root.currentSaturation;
|
||||
|
||||
if (hue === 0 && saturation === 0) {
|
||||
var hsv = ColorsConvert.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255);
|
||||
hue = hsv.h;
|
||||
saturation = hsv.s;
|
||||
root.currentHue = hue;
|
||||
root.currentSaturation = saturation;
|
||||
}
|
||||
// --- GREEN ---
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginM
|
||||
|
||||
var rgb = ColorsConvert.hsvToRgb(hue, saturation, value);
|
||||
root.selectedColor = Qt.rgba(rgb.r / 255, rgb.g / 255, rgb.b / 255, 1);
|
||||
}
|
||||
text: Math.round(brightnessSlider.value) + "%"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
NRadioButton {
|
||||
ButtonGroup.group: colorValues
|
||||
text: "G"
|
||||
font.weight: Font.Bold
|
||||
onClicked: root.editMode = "g"
|
||||
Layout.fillWidth: false
|
||||
}
|
||||
|
||||
NBox {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: themePalette.implicitHeight + Style.marginL * 2
|
||||
NSpinBox {
|
||||
id: greenSpinBox
|
||||
from: 0
|
||||
to: 255
|
||||
|
||||
ColumnLayout {
|
||||
id: themePalette
|
||||
anchors.fill: parent
|
||||
anchors.margins: Style.marginL
|
||||
spacing: Style.marginS
|
||||
onValueChanged: {
|
||||
if (!selectedSlider.pressed && !fieldMouse.pressed && !hexInput.activeFocus && value !== Math.round(root.selectedColor.g * 255)) {
|
||||
root.selectedColor = Qt.rgba(root.selectedColor.r, value / 255, root.selectedColor.b, 1);
|
||||
}
|
||||
}
|
||||
Binding {
|
||||
target: greenSpinBox
|
||||
property: "value"
|
||||
value: Math.round(root.selectedColor.g * 255)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NLabel {
|
||||
label: I18n.tr("widgets.color-picker.theme-colors.label")
|
||||
description: I18n.tr("widgets.color-picker.theme-colors.description")
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
// --- BLUE ---
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginM
|
||||
|
||||
Flow {
|
||||
spacing: 6
|
||||
Layout.fillWidth: true
|
||||
flow: Flow.LeftToRight
|
||||
NRadioButton {
|
||||
ButtonGroup.group: colorValues
|
||||
text: "B"
|
||||
font.weight: Font.Bold
|
||||
onClicked: root.editMode = "b"
|
||||
Layout.fillWidth: false
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: [Color.mPrimary, Color.mSecondary, Color.mTertiary, Color.mError, Color.mSurface, Color.mSurfaceVariant, Color.mOutline, Color.white, Color.black]
|
||||
NSpinBox {
|
||||
id: blueSpinBox
|
||||
from: 0
|
||||
to: 255
|
||||
|
||||
Rectangle {
|
||||
width: 24
|
||||
height: 24
|
||||
radius: 4
|
||||
color: modelData
|
||||
border.color: root.selectedColor === modelData ? Color.mPrimary : Color.mOutline
|
||||
border.width: root.selectedColor === modelData ? 2 : 1
|
||||
onValueChanged: {
|
||||
if (!selectedSlider.pressed && !fieldMouse.pressed && !hexInput.activeFocus && value !== Math.round(root.selectedColor.b * 255)) {
|
||||
root.selectedColor = Qt.rgba(root.selectedColor.r, root.selectedColor.g, value / 255, 1);
|
||||
}
|
||||
}
|
||||
Binding {
|
||||
target: blueSpinBox
|
||||
property: "value"
|
||||
value: Math.round(root.selectedColor.b * 255)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
root.selectedColor = modelData;
|
||||
var hsv = ColorsConvert.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255);
|
||||
root.currentHue = hsv.h;
|
||||
root.currentSaturation = hsv.s;
|
||||
// Spacer
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
// --- HUE ---
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginM
|
||||
|
||||
NRadioButton {
|
||||
ButtonGroup.group: colorValues
|
||||
text: "H"
|
||||
font.weight: Font.Bold
|
||||
checked: true
|
||||
onClicked: root.editMode = "h"
|
||||
Layout.fillWidth: false
|
||||
}
|
||||
|
||||
NSpinBox {
|
||||
id: hueSpinBox
|
||||
from: 0
|
||||
to: 360
|
||||
|
||||
onValueChanged: {
|
||||
if (!selectedSlider.pressed && !fieldMouse.pressed && !hexInput.activeFocus && value !== Math.round(root.displayHue * 360)) {
|
||||
var newHue = value / 360;
|
||||
root.selectedColor = Qt.hsva(newHue, root.selectedColor.hsvSaturation, root.selectedColor.hsvValue, 1);
|
||||
root.stableHue = newHue;
|
||||
}
|
||||
}
|
||||
|
||||
Binding {
|
||||
target: hueSpinBox
|
||||
property: "value"
|
||||
value: Math.round(root.displayHue * 360)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- SATURATION ---
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginM
|
||||
|
||||
NRadioButton {
|
||||
ButtonGroup.group: colorValues
|
||||
text: "S"
|
||||
font.weight: Font.Bold
|
||||
onClicked: root.editMode = "s"
|
||||
Layout.fillWidth: false
|
||||
}
|
||||
|
||||
NSpinBox {
|
||||
id: satSpinBox
|
||||
from: 0
|
||||
to: 100
|
||||
|
||||
onValueChanged: {
|
||||
if (!selectedSlider.pressed && !fieldMouse.pressed && !hexInput.activeFocus && value !== Math.round(root.selectedColor.hsvSaturation * 100)) {
|
||||
root.selectedColor = Qt.hsva(root.selectedColor.hsvHue, value / 100, root.selectedColor.hsvValue, 1);
|
||||
}
|
||||
}
|
||||
Binding {
|
||||
target: satSpinBox
|
||||
property: "value"
|
||||
value: Math.round(root.selectedColor.hsvSaturation * 100)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- VALUE ---
|
||||
RowLayout {
|
||||
spacing: Style.marginM
|
||||
|
||||
NRadioButton {
|
||||
ButtonGroup.group: colorValues
|
||||
text: "V"
|
||||
font.weight: Font.Bold
|
||||
onClicked: root.editMode = "v"
|
||||
Layout.fillWidth: false
|
||||
}
|
||||
|
||||
NSpinBox {
|
||||
id: valSpinBox
|
||||
from: 0
|
||||
to: 100
|
||||
|
||||
onValueChanged: {
|
||||
if (!selectedSlider.pressed && !fieldMouse.pressed && !hexInput.activeFocus && value !== Math.round(root.selectedColor.hsvValue * 100)) {
|
||||
root.selectedColor = Qt.hsva(root.selectedColor.hsvHue, root.selectedColor.hsvSaturation, value / 100, 1);
|
||||
}
|
||||
}
|
||||
Binding {
|
||||
target: valSpinBox
|
||||
property: "value"
|
||||
value: Math.round(root.selectedColor.hsvValue * 100)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Spacer
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
// Hex input
|
||||
RowLayout {
|
||||
id: hexInput
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginM
|
||||
|
||||
NLabel {
|
||||
label: "Hex:" // I18n.tr("widgets.color-picker.hex.label")
|
||||
// description: I18n.tr("widgets.color-picker.hex.description")
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
NTextInput {
|
||||
text: root.selectedColor.toString().toUpperCase()
|
||||
fontFamily: Settings.data.ui.fontFixed
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: implicitWidth
|
||||
onEditingFinished: {
|
||||
if (/^#[0-9A-F]{6}$/i.test(text)) {
|
||||
root.selectedColor = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NBox {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: genericPalette.implicitHeight + Style.marginL * 2
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredWidth: 5
|
||||
Layout.alignment: Qt.AlignTop
|
||||
spacing: Style.marginS
|
||||
|
||||
ColumnLayout {
|
||||
id: genericPalette
|
||||
anchors.fill: parent
|
||||
anchors.margins: Style.marginL
|
||||
spacing: Style.marginS
|
||||
Layout.topMargin: Math.round(2 * Style.uiScaleRatio) //Shim to try and line up colorField with SpinBoxes
|
||||
|
||||
NLabel {
|
||||
label: I18n.tr("widgets.color-picker.palette.label")
|
||||
description: I18n.tr("widgets.color-picker.palette.description")
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
// --- SLIDER ---
|
||||
NColorSlider {
|
||||
id: selectedSlider
|
||||
Layout.fillHeight: true
|
||||
rainbowMode: root.editMode === "h"
|
||||
topColor: {
|
||||
if (rainbowMode)
|
||||
return "transparent";
|
||||
switch (root.editMode) {
|
||||
case "r":
|
||||
return "#FF0000";
|
||||
case "g":
|
||||
return "#00FF00";
|
||||
case "b":
|
||||
return "#0000FF";
|
||||
default:
|
||||
return "#FFFFFF";
|
||||
}
|
||||
}
|
||||
|
||||
Flow {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
spacing: 6
|
||||
flow: Flow.LeftToRight
|
||||
Binding {
|
||||
target: selectedSlider
|
||||
property: "value"
|
||||
when: !selectedSlider.pressed // Only update from model when NOT dragging
|
||||
value: {
|
||||
switch (root.editMode) {
|
||||
case "r":
|
||||
return root.selectedColor.r;
|
||||
case "g":
|
||||
return root.selectedColor.g;
|
||||
case "b":
|
||||
return root.selectedColor.b;
|
||||
case "h":
|
||||
return root.displayHue;
|
||||
case "s":
|
||||
return root.selectedColor.hsvSaturation;
|
||||
case "v":
|
||||
return root.selectedColor.hsvValue;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: ["#F44336", "#E91E63", "#9C27B0", "#673AB7", "#3F51B5", "#2196F3", "#03A9F4", "#00BCD4", "#009688", "#4CAF50", "#8BC34A", "#CDDC39", "#FFEB3B", "#FFC107", "#FF9800", "#FF5722", "#795548", "#9E9E9E", "#E74C3C", "#E67E22", "#F1C40F", "#2ECC71", "#1ABC9C", "#3498DB", "#2980B9", "#9B59B6", "#34495E", "#2C3E50", "#95A5A6", "#7F8C8D",
|
||||
Color.white, Color.black]
|
||||
onMoved: {
|
||||
var v = value;
|
||||
switch (root.editMode) {
|
||||
case "r":
|
||||
root.selectedColor = Qt.rgba(v, root.selectedColor.g, root.selectedColor.b, 1);
|
||||
break;
|
||||
case "g":
|
||||
root.selectedColor = Qt.rgba(root.selectedColor.r, v, root.selectedColor.b, 1);
|
||||
break;
|
||||
case "b":
|
||||
root.selectedColor = Qt.rgba(root.selectedColor.r, root.selectedColor.g, v, 1);
|
||||
break;
|
||||
case "h":
|
||||
root.selectedColor = Qt.hsva(v, root.selectedColor.hsvSaturation, root.selectedColor.hsvValue, 1);
|
||||
root.stableHue = v;
|
||||
break;
|
||||
case "s":
|
||||
root.selectedColor = Qt.hsva(root.selectedColor.hsvHue, v, root.selectedColor.hsvValue, 1);
|
||||
break;
|
||||
case "v":
|
||||
root.selectedColor = Qt.hsva(root.selectedColor.hsvHue, root.selectedColor.hsvSaturation, v, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Color Field
|
||||
Rectangle {
|
||||
width: 24
|
||||
height: 24
|
||||
radius: Style.radiusXXS
|
||||
color: modelData
|
||||
border.color: root.selectedColor === modelData ? Color.mPrimary : Color.mOutline
|
||||
border.width: Math.max(1, root.selectedColor === modelData ? Style.borderM : Style.borderS)
|
||||
id: colorField
|
||||
Layout.fillWidth: true
|
||||
|
||||
Layout.preferredHeight: width
|
||||
Layout.alignment: Qt.AlignTop
|
||||
|
||||
radius: 0
|
||||
border.color: Color.mOutline
|
||||
border.width: Style.borderS
|
||||
clip: true
|
||||
|
||||
ShaderEffect {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 1 // Avoid drawing over the border
|
||||
|
||||
fragmentShader: "../Shaders/qsb/color_picker.frag.qsb"
|
||||
|
||||
// Map strings to integers
|
||||
readonly property int modeInt: {
|
||||
switch (root.editMode) {
|
||||
case "r":
|
||||
return 0;
|
||||
case "g":
|
||||
return 1;
|
||||
case "b":
|
||||
return 2;
|
||||
case "h":
|
||||
return 3;
|
||||
case "s":
|
||||
return 4;
|
||||
case "v":
|
||||
return 5;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Pass which radio is selected
|
||||
readonly property real fixedVal: {
|
||||
switch (root.editMode) {
|
||||
case "r":
|
||||
return root.selectedColor.r;
|
||||
case "g":
|
||||
return root.selectedColor.g;
|
||||
case "b":
|
||||
return root.selectedColor.b;
|
||||
case "h":
|
||||
return root.displayHue;
|
||||
case "s":
|
||||
return root.selectedColor.hsvSaturation;
|
||||
case "v":
|
||||
return root.selectedColor.hsvValue;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Send as one vector because GPUs are so damn picky
|
||||
property vector4d params: Qt.vector4d(1.0, fixedVal, modeInt, 0)
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: fieldMouse
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
root.selectedColor = modelData;
|
||||
var hsv = ColorsConvert.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255);
|
||||
root.currentHue = hsv.h;
|
||||
root.currentSaturation = hsv.s;
|
||||
cursorShape: Qt.CrossCursor
|
||||
|
||||
// Update color when clicking or dragging
|
||||
function updateColor(mouse) {
|
||||
// Normalize X and Y (0.0 to 1.0)
|
||||
var xVal = Math.max(0, Math.min(1, mouse.x / width));
|
||||
var yVal = Math.max(0, Math.min(1, 1.0 - (mouse.y / height))); // Flip Y (0 at bottom)
|
||||
|
||||
// Get the current fixed value (from the slider)
|
||||
var fixed = 0.0;
|
||||
|
||||
switch (root.editMode) {
|
||||
case "r":
|
||||
fixed = root.selectedColor.r;
|
||||
root.selectedColor = Qt.rgba(fixed, xVal, yVal, 1);
|
||||
break;
|
||||
case "g":
|
||||
fixed = root.selectedColor.g;
|
||||
root.selectedColor = Qt.rgba(xVal, fixed, yVal, 1);
|
||||
break;
|
||||
case "b":
|
||||
fixed = root.selectedColor.b;
|
||||
root.selectedColor = Qt.rgba(xVal, yVal, fixed, 1);
|
||||
break;
|
||||
case "h":
|
||||
// Use stableHue to prevent flipping to -1
|
||||
fixed = root.displayHue;
|
||||
root.selectedColor = Qt.hsva(fixed, xVal, yVal, 1);
|
||||
root.stableHue = fixed;
|
||||
break;
|
||||
case "s":
|
||||
fixed = root.selectedColor.hsvSaturation;
|
||||
root.selectedColor = Qt.hsva(xVal, fixed, yVal, 1);
|
||||
// If we dragged Hue (xVal), update stableHue
|
||||
root.stableHue = yVal;
|
||||
break;
|
||||
case "v":
|
||||
fixed = root.selectedColor.hsvValue;
|
||||
root.selectedColor = Qt.hsva(xVal, yVal, fixed, 1);
|
||||
// If we dragged Hue (xVal), update stableHue
|
||||
root.stableHue = xVal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
onPressed: mouse => updateColor(mouse)
|
||||
onPositionChanged: mouse => updateColor(mouse)
|
||||
}
|
||||
|
||||
// Color Indicator
|
||||
Rectangle {
|
||||
width: 10
|
||||
height: 10
|
||||
radius: 5
|
||||
color: "transparent"
|
||||
border.color: root.selectedColor.hsvValue < 0.5 ? "white" : "black"
|
||||
border.width: 1
|
||||
|
||||
// Find position based on the current color
|
||||
readonly property point selectedPos: {
|
||||
switch (root.editMode) {
|
||||
case "r":
|
||||
return Qt.point(root.selectedColor.g, root.selectedColor.b);
|
||||
case "g":
|
||||
return Qt.point(root.selectedColor.r, root.selectedColor.b);
|
||||
case "b":
|
||||
return Qt.point(root.selectedColor.r, root.selectedColor.g);
|
||||
case "h":
|
||||
return Qt.point(root.selectedColor.hsvSaturation, root.selectedColor.hsvValue);
|
||||
case "s":
|
||||
return Qt.point(root.displayHue, root.selectedColor.hsvValue);
|
||||
case "v":
|
||||
return Qt.point(root.displayHue, root.selectedColor.hsvSaturation);
|
||||
default:
|
||||
return Qt.point(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert values to pixel position
|
||||
x: (selectedPos.x * parent.width) - width / 2
|
||||
y: ((1.0 - selectedPos.y) * parent.height) - height / 2
|
||||
}
|
||||
|
||||
// Redraw the border in case Color Indicator is near the edge
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
border.color: Color.mOutline
|
||||
border.width: Style.borderS
|
||||
antialiasing: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NCollapsible {
|
||||
id: paletteCollapsible
|
||||
label: I18n.tr("widgets.color-picker.palette.label")
|
||||
description: I18n.tr("widgets.color-picker.palette.description")
|
||||
|
||||
Layout.fillWidth: true
|
||||
contentSpacing: Style.marginS
|
||||
|
||||
GridLayout {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
columns: 15
|
||||
columnSpacing: 6
|
||||
rowSpacing: 6
|
||||
|
||||
Repeater {
|
||||
model: ColorList.colors
|
||||
|
||||
Rectangle {
|
||||
width: 24
|
||||
height: 24
|
||||
radius: Style.radiusXXS
|
||||
color: modelData.color
|
||||
border.color: root.selectedColor.toString() === modelData.color.toString() ? Color.mPrimary : Color.mOutline
|
||||
border.width: Math.max(1, root.selectedColor.toString() === modelData.color.toString() ? Style.borderM : Style.borderS)
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
hoverEnabled: true
|
||||
|
||||
onEntered: {
|
||||
TooltipService.show(screen, parent, modelData.name + "\n" + parent.color.toString().toUpperCase(), "auto");
|
||||
}
|
||||
onExited: {
|
||||
TooltipService.hide();
|
||||
}
|
||||
onClicked: {
|
||||
root.selectedColor = modelData.color;
|
||||
TooltipService.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NDivider {
|
||||
Layout.columnSpan: 15
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.marginXS
|
||||
Layout.bottomMargin: 0
|
||||
}
|
||||
|
||||
NLabel {
|
||||
Layout.columnSpan: 15
|
||||
Layout.fillWidth: true
|
||||
description: I18n.tr("widgets.color-picker.theme-colors.description")
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: [
|
||||
{
|
||||
name: "mPrimary",
|
||||
color: Color.mPrimary
|
||||
},
|
||||
{
|
||||
name: "mSecondary",
|
||||
color: Color.mSecondary
|
||||
},
|
||||
{
|
||||
name: "mTertiary",
|
||||
color: Color.mTertiary
|
||||
},
|
||||
{
|
||||
name: "mError",
|
||||
color: Color.mError
|
||||
},
|
||||
{
|
||||
name: "mSurface",
|
||||
color: Color.mSurface
|
||||
},
|
||||
{
|
||||
name: "mSurfaceVariant",
|
||||
color: Color.mSurfaceVariant
|
||||
},
|
||||
{
|
||||
name: "mOutline",
|
||||
color: Color.mOutline
|
||||
}
|
||||
]
|
||||
|
||||
Rectangle {
|
||||
width: 24
|
||||
height: 24
|
||||
radius: 4
|
||||
color: modelData.color
|
||||
border.color: root.selectedColor.toString() === modelData.color.toString() ? Color.mPrimary : Color.mOutline
|
||||
border.width: root.selectedColor.toString() === modelData.color.toString() ? 2 : 1
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
hoverEnabled: true
|
||||
|
||||
onEntered: {
|
||||
TooltipService.show(screen, parent, modelData.name + "\n" + parent.color.toString().toUpperCase(), "auto");
|
||||
}
|
||||
onExited: {
|
||||
TooltipService.hide();
|
||||
}
|
||||
onClicked: {
|
||||
root.selectedColor = modelData.color;
|
||||
TooltipService.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user