Skip to content

Instantly share code, notes, and snippets.

@mitchcurtis
Last active August 8, 2023 08:32
Show Gist options
  • Save mitchcurtis/de25c4c48dde647d406b26554d721673 to your computer and use it in GitHub Desktop.
Save mitchcurtis/de25c4c48dde647d406b26554d721673 to your computer and use it in GitHub Desktop.
Qt Quick palette legend
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
ApplicationWindow {
id: root
width: 640
height: 480
visible: true
readonly property var roles: [
"alternateBase",
"base",
"brightText",
"button",
"buttonText",
"dark",
"highlight",
"highlightedText",
"light",
"link",
"linkVisited",
"mid",
"midlight",
"placeholderText",
"shadow",
"text",
"toolTipBase",
"toolTipText",
"window",
"windowText"
]
TextMetrics {
id: roleColourTextMetrics
text: "#00000000"
}
// Based on https://stackoverflow.com/a/35970186/904422.
function invertHex(hex) {
if (hex.indexOf('#') === 0) {
hex = hex.slice(1);
}
// convert 3-digit hex to 6-digits.
if (hex.length === 3) {
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
}
if (hex.length !== 6 && hex.length !== 8) {
throw new Error(`Invalid HEX color of length ${hex.length}`);
}
var hasAlpha = hex.length === 8;
var a = hasAlpha ? parseInt(hex.slice(0, 2), 16) : 0;
var offset = hasAlpha ? 2 : 0
var r = parseInt(hex.slice(offset + 0, offset + 2), 16);
var g = parseInt(hex.slice(offset + 2, offset + 4), 16);
var b = parseInt(hex.slice(offset + 4, offset + 6), 16);
// invert color components
r = (255 - r).toString(16);
g = (255 - g).toString(16);
b = (255 - b).toString(16);
a = (255 - a).toString(16);
// pad each with zeros and return
return "#" + a.padStart(2, '0') + r.padStart(2, '0') + g.padStart(2, '0') + b.padStart(2, '0');
}
component PaletteRoleDelegate: Rectangle {
implicitWidth: roleColourTextMetrics.width
implicitHeight: roleColourTextMetrics.height
color: palette[groupName][modelData]
required property string groupName
required property string modelData
Label {
id: roleColourLabel
text: parent.color
color: {
print(groupName, modelData, text, root.invertHex(text), root.invertHex(text))
root.invertHex(text)
}
}
}
readonly property int labelSize: 100
component PaletteRolesColumn: Column {
id: rolesColumn
required property string groupName
Item {
implicitWidth: groupNameLabel.implicitHeight
implicitHeight: root.labelSize
Label {
id: groupNameLabel
text: groupName
y: width
width: parent.height
horizontalAlignment: Text.AlignLeft
leftPadding: 10
rotation: -90
transformOrigin: Item.TopLeft
}
}
Repeater {
model: root.roles
delegate: PaletteRoleDelegate {
groupName: rolesColumn.groupName
}
}
}
component PaletteLegend: Row {
Column {
Item {
width: 1
height: root.labelSize
}
Repeater {
model: root.roles
delegate: Label {
text: modelData
height: roleColourTextMetrics.height
required property string modelData
}
}
}
PaletteRolesColumn {
groupName: "active"
}
PaletteRolesColumn {
groupName: "disabled"
}
PaletteRolesColumn {
groupName: "inactive"
}
}
RowLayout {
anchors.fill: parent
PaletteLegend {
palette: checkBox.palette
}
CheckBox {
id: checkBox
text: "CheckBox"
checked: true
}
}
}
@mitchcurtis
Copy link
Author

mitchcurtis commented Aug 8, 2023

Similar legend for SystemPalette:

import QtQuick
import QtQuick.Layouts
import QtQuick.Controls

ApplicationWindow {
    id: root
    width: 640
    height: 480
    visible: true

    readonly property var roles: [
        "alternateBase",
        "base",
        "button",
        "buttonText",
        "dark",
        "highlight",
        "highlightedText",
        "light",
        "mid",
        "midlight",
        "placeholderText",
        "shadow",
        "text",
        "window",
        "windowText"
    ]

    TextMetrics {
        id: roleColourTextMetrics
        text: "#00000000"
    }

    // Based on https://stackoverflow.com/a/35970186/904422.
    function invertHex(hex) {
        if (hex.indexOf('#') === 0) {
            hex = hex.slice(1);
        }
        // convert 3-digit hex to 6-digits.
        if (hex.length === 3) {
            hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
        }
        if (hex.length !== 6 && hex.length !== 8) {
            throw new Error(`Invalid HEX color of length ${hex.length}`);
        }
        var hasAlpha = hex.length === 8;
        var a = hasAlpha ? parseInt(hex.slice(0, 2), 16) : 0;
        var offset = hasAlpha ? 2 : 0
        var r = parseInt(hex.slice(offset + 0, offset + 2), 16);
        var g = parseInt(hex.slice(offset + 2, offset + 4), 16);
        var b = parseInt(hex.slice(offset + 4, offset + 6), 16);

        // invert color components
        r = (255 - r).toString(16);
        g = (255 - g).toString(16);
        b = (255 - b).toString(16);
        a = (255 - a).toString(16);
        // pad each with zeros and return
        return "#" + a.padStart(2, '0') + r.padStart(2, '0') + g.padStart(2, '0') + b.padStart(2, '0');
    }

    component PaletteRoleDelegate: Rectangle {
        implicitWidth: roleColourTextMetrics.width
        implicitHeight: roleColourTextMetrics.height
        color: systemPalette[modelData]

        required property SystemPalette systemPalette
        required property string modelData

        Label {
            id: roleColourLabel
            text: parent.color
            color: root.invertHex(text)
        }
    }

    readonly property int labelSize: 100

    component PaletteRolesColumn: Column {
        id: rolesColumn

        required property SystemPalette systemPalette
        required property string groupName

        Item {
            implicitWidth: groupNameLabel.implicitHeight
            implicitHeight: root.labelSize

            Label {
                id: groupNameLabel
                text: groupName
                y: width
                width: parent.height
                horizontalAlignment: Text.AlignLeft
                leftPadding: 10
                rotation: -90
                transformOrigin: Item.TopLeft
            }
        }

        Repeater {
            model: root.roles
            delegate: PaletteRoleDelegate {
                systemPalette: rolesColumn.systemPalette
            }
        }
    }

    component PaletteLegend: Row {
        Column {
            Item {
                width: 1
                height: root.labelSize
            }

            Repeater {
                model: root.roles
                delegate: Label {
                    text: modelData
                    height: roleColourTextMetrics.height

                    required property string modelData
                }
            }
        }

        PaletteRolesColumn {
            groupName: "active"
            systemPalette: SystemPalette {
                colorGroup: SystemPalette.Active
            }
        }
        PaletteRolesColumn {
            groupName: "disabled"
            systemPalette: SystemPalette {
                colorGroup: SystemPalette.Disabled
            }
        }
        PaletteRolesColumn {
            groupName: "inactive"
            systemPalette: SystemPalette {
                colorGroup: SystemPalette.Inactive
            }
        }
    }

    PaletteLegend {}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment