move color funcs to their own file instead of appearance

This commit is contained in:
end-4
2025-05-19 23:13:17 +02:00
parent 80661d4f86
commit 14f7542a21
22 changed files with 229 additions and 131 deletions
@@ -1,5 +1,6 @@
import QtQuick
import Quickshell
import "root:/modules/common/functions/color_utils.js" as ColorUtils
pragma Singleton
pragma ComponentBehavior: Bound
@@ -14,69 +15,6 @@ Singleton {
property QtObject sizes
property string syntaxHighlightingTheme
function colorWithHueOf(color1, color2) {
// Convert both colors to HSV
var c1 = Qt.color(color1);
var c2 = Qt.color(color2);
// Helper to convert RGB to HSV
function rgb2hsv(c) {
var r = c.r, g = c.g, b = c.b;
var max = Math.max(r, g, b), min = Math.min(r, g, b);
var h, s, v = max;
var d = max - min;
s = max === 0 ? 0 : d / max;
if (max === min) {
h = 0;
} else {
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;
}
return {h: h, s: s, v: v, a: c.a};
}
// Helper to convert HSV to RGB
function hsv2rgb(h, s, v, a) {
var r, g, b;
var i = Math.floor(h * 6);
var f = h * 6 - i;
var p = v * (1 - s);
var q = v * (1 - f * s);
var t = v * (1 - (1 - f) * s);
switch(i % 6){
case 0: r = v, g = t, b = p; break;
case 1: r = q, g = v, b = p; break;
case 2: r = p, g = v, b = t; break;
case 3: r = p, g = q, b = v; break;
case 4: r = t, g = p, b = v; break;
case 5: r = v, g = p, b = q; break;
}
return Qt.rgba(r, g, b, a);
}
var hsv1 = rgb2hsv(c1);
var hsv2 = rgb2hsv(c2);
// Use hue from color2, saturation/value/alpha from color1
return hsv2rgb(hsv2.h, hsv1.s, hsv1.v, hsv1.a);
}
function mix(color1, color2, percentage) {
var c1 = Qt.color(color1);
var c2 = Qt.color(color2);
return Qt.rgba(percentage * c1.r + (1 - percentage) * c2.r, percentage * c1.g + (1 - percentage) * c2.g, percentage * c1.b + (1 - percentage) * c2.b, percentage * c1.a + (1 - percentage) * c2.a);
}
// Transparentize
function transparentize(color, percentage) {
var c = Qt.color(color);
return Qt.rgba(c.r, c.g, c.b, c.a * (1 - percentage));
}
m3colors: QtObject {
property bool darkmode: false
property bool transparent: false
@@ -160,37 +98,37 @@ Singleton {
property color colSubtext: m3colors.m3outline
property color colLayer0: m3colors.m3background
property color colOnLayer0: m3colors.m3onBackground
property color colLayer0Hover: mix(colLayer0, colOnLayer0, 0.9)
property color colLayer0Active: mix(colLayer0, colOnLayer0, 0.8)
property color colLayer0Hover: ColorUtils.mix(colLayer0, colOnLayer0, 0.9)
property color colLayer0Active: ColorUtils.mix(colLayer0, colOnLayer0, 0.8)
property color colLayer1: m3colors.m3surfaceContainerLow;
property color colOnLayer1: m3colors.m3onSurfaceVariant;
property color colOnLayer1Inactive: mix(colOnLayer1, colLayer1, 0.45);
property color colLayer2: mix(m3colors.m3surfaceContainer, m3colors.m3surfaceContainerHigh, 0.55);
property color colOnLayer1Inactive: ColorUtils.mix(colOnLayer1, colLayer1, 0.45);
property color colLayer2: ColorUtils.mix(m3colors.m3surfaceContainer, m3colors.m3surfaceContainerHigh, 0.55);
property color colOnLayer2: m3colors.m3onSurface;
property color colOnLayer2Disabled: mix(colOnLayer2, m3colors.m3background, 0.4);
property color colLayer3: mix(m3colors.m3surfaceContainerHigh, m3colors.m3onSurface, 0.96);
property color colOnLayer2Disabled: ColorUtils.mix(colOnLayer2, m3colors.m3background, 0.4);
property color colLayer3: ColorUtils.mix(m3colors.m3surfaceContainerHigh, m3colors.m3onSurface, 0.96);
property color colOnLayer3: m3colors.m3onSurface;
property color colLayer1Hover: mix(colLayer1, colOnLayer1, 0.92);
property color colLayer1Active: mix(colLayer1, colOnLayer1, 0.85);
property color colLayer2Hover: mix(colLayer2, colOnLayer2, 0.90);
property color colLayer2Active: mix(colLayer2, colOnLayer2, 0.80);
property color colLayer2Disabled: mix(colLayer2, m3colors.m3background, 0.8);
property color colLayer3Hover: mix(colLayer3, colOnLayer3, 0.90);
property color colLayer3Active: mix(colLayer3, colOnLayer3, 0.80);
property color colPrimaryHover: mix(m3colors.m3primary, colLayer1Hover, 0.85)
property color colPrimaryActive: mix(m3colors.m3primary, colLayer1Active, 0.7)
property color colPrimaryContainerHover: mix(m3colors.m3primaryContainer, colLayer1Hover, 0.7)
property color colPrimaryContainerActive: mix(m3colors.m3primaryContainer, colLayer1Active, 0.6)
property color colSecondaryHover: mix(m3colors.m3secondary, colLayer1Hover, 0.85)
property color colSecondaryActive: mix(m3colors.m3secondary, colLayer1Active, 0.4)
property color colSecondaryContainerHover: mix(m3colors.m3secondaryContainer, colLayer1Hover, 0.6)
property color colSecondaryContainerActive: mix(m3colors.m3secondaryContainer, colLayer1Active, 0.54)
property color colSurfaceContainerHighestHover: mix(m3colors.m3surfaceContainerHighest, m3colors.m3onSurface, 0.95)
property color colSurfaceContainerHighestActive: mix(m3colors.m3surfaceContainerHighest, m3colors.m3onSurface, 0.85)
property color colLayer1Hover: ColorUtils.mix(colLayer1, colOnLayer1, 0.92);
property color colLayer1Active: ColorUtils.mix(colLayer1, colOnLayer1, 0.85);
property color colLayer2Hover: ColorUtils.mix(colLayer2, colOnLayer2, 0.90);
property color colLayer2Active: ColorUtils.mix(colLayer2, colOnLayer2, 0.80);
property color colLayer2Disabled: ColorUtils.mix(colLayer2, m3colors.m3background, 0.8);
property color colLayer3Hover: ColorUtils.mix(colLayer3, colOnLayer3, 0.90);
property color colLayer3Active: ColorUtils.mix(colLayer3, colOnLayer3, 0.80);
property color colPrimaryHover: ColorUtils.mix(m3colors.m3primary, colLayer1Hover, 0.85)
property color colPrimaryActive: ColorUtils.mix(m3colors.m3primary, colLayer1Active, 0.7)
property color colPrimaryContainerHover: ColorUtils.mix(m3colors.m3primaryContainer, colLayer1Hover, 0.7)
property color colPrimaryContainerActive: ColorUtils.mix(m3colors.m3primaryContainer, colLayer1Active, 0.6)
property color colSecondaryHover: ColorUtils.mix(m3colors.m3secondary, colLayer1Hover, 0.85)
property color colSecondaryActive: ColorUtils.mix(m3colors.m3secondary, colLayer1Active, 0.4)
property color colSecondaryContainerHover: ColorUtils.mix(m3colors.m3secondaryContainer, colLayer1Hover, 0.6)
property color colSecondaryContainerActive: ColorUtils.mix(m3colors.m3secondaryContainer, colLayer1Active, 0.54)
property color colSurfaceContainerHighestHover: ColorUtils.mix(m3colors.m3surfaceContainerHighest, m3colors.m3onSurface, 0.95)
property color colSurfaceContainerHighestActive: ColorUtils.mix(m3colors.m3surfaceContainerHighest, m3colors.m3onSurface, 0.85)
property color colTooltip: "#3C4043" // m3colors.m3inverseSurface in the specs, but the m3 website actually uses this color
property color colOnTooltip: "#F8F9FA" // m3colors.m3inverseOnSurface in the specs, but the m3 website actually uses this color
property color colScrim: transparentize(m3colors.m3scrim, 0.5)
property color colShadow: transparentize(m3colors.m3shadow, 0.75)
property color colScrim: ColorUtils.transparentize(m3colors.m3scrim, 0.5)
property color colShadow: ColorUtils.transparentize(m3colors.m3shadow, 0.75)
}
rounding: QtObject {
@@ -0,0 +1,136 @@
// Utility functions for color manipulation.
/**
* Converts an RGB color object to HSV color space.
*
* @param {{r: number, g: number, b: number, a: number}} c - The color object with r, g, b, a properties (0-1).
* @returns {{h: number, s: number, v: number, a: number}} The HSV representation with alpha.
*/
function rgb2hsv(c) {
var r = c.r, g = c.g, b = c.b;
var max = Math.max(r, g, b), min = Math.min(r, g, b);
var h, s, v = max;
var d = max - min;
s = max === 0 ? 0 : d / max;
if (max === min) {
h = 0;
} else {
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;
}
return {h: h, s: s, v: v, a: c.a};
}
/**
* Converts an HSV color value to an RGBA color.
*
* @param {number} h - Hue component (0-1).
* @param {number} s - Saturation component (0-1).
* @param {number} v - Value component (0-1).
* @param {number} a - Alpha component (0-1).
* @returns {Qt.rgba} The resulting color as a Qt.rgba object.
*/
function hsv2rgb(h, s, v, a) {
var r, g, b;
var i = Math.floor(h * 6);
var f = h * 6 - i;
var p = v * (1 - s);
var q = v * (1 - f * s);
var t = v * (1 - (1 - f) * s);
switch(i % 6){
case 0: r = v, g = t, b = p; break;
case 1: r = q, g = v, b = p; break;
case 2: r = p, g = v, b = t; break;
case 3: r = p, g = q, b = v; break;
case 4: r = t, g = p, b = v; break;
case 5: r = v, g = p, b = q; break;
}
return Qt.rgba(r, g, b, a);
}
/**
* Returns a color with the hue of color2 and the saturation, value, and alpha of color1.
*
* @param {string} color1 - The base color (any Qt.color-compatible string).
* @param {string} color2 - The color to take hue from.
* @returns {Qt.rgba} The resulting color.
*/
function colorWithHueOf(color1, color2) {
// Convert both colors to HSV
var c1 = Qt.color(color1);
var c2 = Qt.color(color2);
var hsv1 = rgb2hsv(c1);
var hsv2 = rgb2hsv(c2);
// Use hue from color2, saturation/value/alpha from color1
return hsv2rgb(hsv2.h, hsv1.s, hsv1.v, hsv1.a);
}
/**
* Returns a color with the saturation of color2 and the hue/value/alpha of color1.
*
* @param {string} color1 - The base color (any Qt.color-compatible string).
* @param {string} color2 - The color to take saturation from.
* @returns {Qt.rgba} The resulting color.
*/
function colorWithSaturationOf(color1, color2) {
// Convert both colors to HSV
var c1 = Qt.color(color1);
var c2 = Qt.color(color2);
var hsv1 = rgb2hsv(c1);
var hsv2 = rgb2hsv(c2);
// Use hue from color2, saturation/value/alpha from color1
return hsv2rgb(hsv1.h, hsv2.s, hsv1.v, hsv1.a);
}
/**
* Adapts color1 to the accent (hue and saturation) of color2, keeping value and alpha from color1.
*
* @param {string} color1 - The base color (any Qt.color-compatible string).
* @param {string} color2 - The accent color.
* @returns {Qt.rgba} The resulting color.
*/
function adaptToAccent(color1, color2) {
// Convert both colors to HSV
var c1 = Qt.color(color1);
var c2 = Qt.color(color2);
var hsv1 = rgb2hsv(c1);
var hsv2 = rgb2hsv(c2);
// Use hue from color2, saturation/value/alpha from color1
return hsv2rgb(hsv2.h, hsv2.s, hsv1.v, hsv1.a);
}
/**
* Mixes two colors by a given percentage.
*
* @param {string} color1 - The first color (any Qt.color-compatible string).
* @param {string} color2 - The second color.
* @param {number} percentage - The mix ratio (0-1). 1 = all color1, 0 = all color2.
* @returns {Qt.rgba} The resulting mixed color.
*/
function mix(color1, color2, percentage) {
var c1 = Qt.color(color1);
var c2 = Qt.color(color2);
return Qt.rgba(percentage * c1.r + (1 - percentage) * c2.r, percentage * c1.g + (1 - percentage) * c2.g, percentage * c1.b + (1 - percentage) * c2.b, percentage * c1.a + (1 - percentage) * c2.a);
}
/**
* Transparentizes a color by a given percentage.
*
* @param {string} color - The color (any Qt.color-compatible string).
* @param {number} percentage - The amount to transparentize (0-1).
* @returns {Qt.rgba} The resulting color.
*/
function transparentize(color, percentage) {
var c = Qt.color(color);
return Qt.rgba(c.r, c.g, c.b, c.a * (1 - percentage));
}
@@ -1,4 +1,5 @@
import "root:/modules/common"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
@@ -17,7 +18,9 @@ Button {
background: Rectangle {
anchors.fill: parent
radius: Appearance.rounding.full
color: (button.down && button.enabled) ? Appearance.colors.colLayer1Active : ((button.hovered && button.enabled) ? Appearance.colors.colLayer1Hover : Appearance.transparentize(Appearance.m3colors.m3surfaceContainerHigh, 1))
color: (button.down && button.enabled) ? Appearance.colors.colLayer1Active :
((button.hovered && button.enabled) ? Appearance.colors.colLayer1Hover :
ColorUtils.transparentize(Appearance.m3colors.m3surfaceContainerHigh, 1))
Behavior on color {
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
@@ -1,4 +1,5 @@
import "root:/modules/common"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
@@ -16,9 +17,9 @@ Button {
background: Rectangle {
anchors.fill: parent
color: (button.down && button.enabled) ? Appearance.transparentize(Appearance.m3colors.m3onSurface, 0.84) :
((button.hovered && button.enabled) ? Appearance.transparentize(Appearance.m3colors.m3onSurface, 0.92) :
Appearance.transparentize(Appearance.m3colors.m3onSurface, 1))
color: (button.down && button.enabled) ? ColorUtils.transparentize(Appearance.m3colors.m3onSurface, 0.84) :
((button.hovered && button.enabled) ? ColorUtils.transparentize(Appearance.m3colors.m3onSurface, 0.92) :
ColorUtils.transparentize(Appearance.m3colors.m3onSurface, 1))
Behavior on color {
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
@@ -1,5 +1,6 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
@@ -30,7 +31,7 @@ Button {
radius: Appearance.rounding.full
color: toggled ?
(button.down ? Appearance.colors.colSecondaryContainerActive : button.hovered ? Appearance.colors.colSecondaryContainerHover : Appearance.m3colors.m3secondaryContainer) :
(button.down ? Appearance.colors.colLayer1Active : button.hovered ? Appearance.colors.colLayer1Hover : Appearance.transparentize(Appearance.colors.colLayer1Hover, 1))
(button.down ? Appearance.colors.colLayer1Active : button.hovered ? Appearance.colors.colLayer1Hover : ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1))
Behavior on color {
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
@@ -1,6 +1,7 @@
import "root:/modules/common"
import "root:/services"
import "root:/modules/common/functions/string_utils.js" as StringUtils
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import Qt5Compat.GraphicalEffects
import QtQuick
import QtQuick.Controls
@@ -187,7 +188,7 @@ Item {
height: notificationColumnLayout.implicitHeight
color: (notificationObject.urgency == NotificationUrgency.Critical) ?
Appearance.mix(Appearance.m3colors.m3secondaryContainer, Appearance.colors.colLayer2, 0.35) : Appearance.colors.colLayer2
ColorUtils.mix(Appearance.m3colors.m3secondaryContainer, Appearance.colors.colLayer2, 0.35) : Appearance.colors.colLayer2
radius: Appearance.rounding.normal
Behavior on x {
@@ -289,7 +290,7 @@ Item {
}
anchors.fill: parent
color: (notificationObject.urgency == NotificationUrgency.Critical) ?
Appearance.mix(Appearance.m3colors.m3onSecondary, Appearance.m3colors.m3onSecondaryContainer, 0.1) :
ColorUtils.mix(Appearance.m3colors.m3onSecondary, Appearance.m3colors.m3onSecondaryContainer, 0.1) :
Appearance.m3colors.m3onSecondaryContainer
iconSize: 27
horizontalAlignment: Text.AlignHCenter
@@ -422,7 +423,7 @@ Item {
background: Rectangle {
anchors.fill: parent
radius: Appearance.rounding.full
color: (expandButton.down) ? Appearance.colors.colLayer2Active : (expandButton.hovered ? Appearance.colors.colLayer2Hover : Appearance.transparentize(Appearance.colors.colLayer2, 1))
color: (expandButton.down) ? Appearance.colors.colLayer2Active : (expandButton.hovered ? Appearance.colors.colLayer2Hover : ColorUtils.transparentize(Appearance.colors.colLayer2, 1))
Behavior on color {
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
@@ -1,5 +1,6 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import Qt5Compat.GraphicalEffects
import QtQuick
import QtQuick.Controls
@@ -87,7 +88,7 @@ TabButton {
id: buttonBackground
radius: Appearance.rounding.small
implicitHeight: 50
color: (button.hovered ? Appearance.colors.colLayer1Hover : Appearance.transparentize(Appearance.colors.colLayer1Hover, 1))
color: (button.hovered ? Appearance.colors.colLayer1Hover : ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1))
layer.enabled: true
layer.effect: OpacityMask {
maskSource: Rectangle {
@@ -1,5 +1,6 @@
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/color_utils.js" as ColorUtils
import Qt5Compat.GraphicalEffects
import QtQuick
import QtQuick.Controls
@@ -89,7 +90,7 @@ TabButton {
id: buttonBackground
radius: Appearance.rounding.small
implicitHeight: 37
color: (button.hovered ? Appearance.colors.colLayer1Hover : Appearance.transparentize(Appearance.colors.colLayer1Hover, 1))
color: (button.hovered ? Appearance.colors.colLayer1Hover : ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1))
layer.enabled: true
layer.effect: OpacityMask {
maskSource: Rectangle {