11package org.elm.ide.color
22
3- import com.github.ajalt.colormath.*
3+ import com.github.ajalt.colormath.AngleUnit
4+ import com.github.ajalt.colormath.Color
5+ import com.github.ajalt.colormath.formatCssString
6+ import com.github.ajalt.colormath.hueOr
7+ import com.github.ajalt.colormath.model.HSL
8+ import com.github.ajalt.colormath.model.RGB
9+ import com.github.ajalt.colormath.parse
410import com.intellij.openapi.command.CommandProcessor
511import com.intellij.openapi.editor.ElementColorProvider
612import com.intellij.psi.PsiDocumentManager
@@ -10,15 +16,14 @@ import org.elm.lang.core.psi.ElmTypes.LOWER_CASE_IDENTIFIER
1016import org.elm.lang.core.psi.ElmTypes.REGULAR_STRING_PART
1117import org.elm.lang.core.psi.elementType
1218import org.elm.lang.core.psi.elements.*
13- import java.awt.Color
19+ import java.awt.Color as AwtColor
1420import java.util.Locale
15- import kotlin.math.roundToInt
1621
1722private val colorRegex = Regex (""" #[0-9a-fA-F]{3,8}\b|\b(?:rgb|hsl)a?\([^)]+\)""" )
1823
1924/* * Adds color blocks to the gutter when hex colors exist in a string */
2025class ElmColorProvider : ElementColorProvider {
21- override fun getColorFrom (element : PsiElement ): Color ? {
26+ override fun getColorFrom (element : PsiElement ): AwtColor ? {
2227 // Like all line markers, we should only provide colors on leaf elements
2328 if (element.firstChild != null ) return null
2429 return getCssColorFromString(element) ? : getColorFromFuncCall(element)
@@ -27,31 +32,31 @@ class ElmColorProvider : ElementColorProvider {
2732 // Parse a CSS color from any string that contains one, since "1px solid #1a2b3c" probably
2833 // contains a color. We don't parse color keywords, since "The red fire truck" is probably not
2934 // supposed to contain a color.
30- private fun getCssColorFromString (element : PsiElement ): Color ? {
35+ private fun getCssColorFromString (element : PsiElement ): AwtColor ? {
3136 if (element.elementType != REGULAR_STRING_PART ) return null
3237 return colorRegex.find(element.text)
33- ?.let { runCatching { ConvertibleColor .fromCss (it.value) }.getOrNull() }
38+ ?.let { runCatching { Color .parse (it.value) }.getOrNull() }
3439 ?.toAwtColor()
3540 }
3641
37- private fun getColorFromFuncCall (element : PsiElement ): Color ? {
42+ private fun getColorFromFuncCall (element : PsiElement ): AwtColor ? {
3843 val call = getFuncCall(element) ? : return null
3944 val color = runCatching {
4045 // color constructors will throw if the args are out of bounds
4146 when (call.name) {
4247 " rgb" , " rgba" -> {
4348 if (call.a == null && call.name == " rgba" ) return null
4449 if (call.useFloat) RGB (call.c1, call.c2, call.c3, call.a ? : 1f )
45- else RGB (call.c1.toInt(), call.c2.toInt(), call.c3.toInt(), call.a ? : 1f )
50+ else RGB .from255 (call.c1.toInt(), call.c2.toInt(), call.c3.toInt(), (( call.a ? : 1f ) * 255 ).toInt() )
4651 }
47- " rgb255" -> RGB (call.c1.toInt(), call.c2.toInt(), call.c3.toInt())
48- " rgba255" -> RGB (call.c1.toInt(), call.c2.toInt(), call.c3.toInt(), call.a ? : return null )
52+ " rgb255" -> RGB .from255 (call.c1.toInt(), call.c2.toInt(), call.c3.toInt())
53+ " rgba255" -> RGB .from255 (call.c1.toInt(), call.c2.toInt(), call.c3.toInt(), (( call.a ? : 1f ) * 255 ).toInt() )
4954 " hsl" -> HSL (call.c1, call.c2, call.c3)
5055 " hsla" -> HSL (call.c1, call.c2, call.c3, call.a ? : return null )
5156 else -> return null
52- }
57+ }.toAwtColor()
5358 }.getOrNull()
54- return color?.toAwtColor()
59+ return color
5560 }
5661
5762 private fun getFuncCall (element : PsiElement ): FuncCall ? {
@@ -82,7 +87,7 @@ class ElmColorProvider : ElementColorProvider {
8287 )
8388 }
8489
85- override fun setColorTo (element : PsiElement , color : Color ) {
90+ override fun setColorTo (element : PsiElement , color : AwtColor ) {
8691 if (element.firstChild != null ) return
8792 val command = stringColorSettingRunnable(element, color)
8893 ? : functionColorSettingRunnable(element, color)
@@ -99,13 +104,13 @@ class ElmColorProvider : ElementColorProvider {
99104 )
100105 }
101106
102- private fun functionColorSettingRunnable (element : PsiElement , color : Color ): Runnable ? {
107+ private fun functionColorSettingRunnable (element : PsiElement , color : AwtColor ): Runnable ? {
103108 val funcCall = getFuncCall(element)
104109 val call = funcCall ? : return null
105110 return Runnable { setColorInFunctionCall(element, color, call) }
106111 }
107112
108- private fun setColorInFunctionCall (element : PsiElement , color : Color , call : FuncCall ) {
113+ private fun setColorInFunctionCall (element : PsiElement , color : AwtColor , call : FuncCall ) {
109114 val factory = ElmPsiFactory (element.project)
110115
111116 fun ElmNumberConstantExpr.replace (c : Int , float : Boolean ) {
@@ -115,9 +120,9 @@ class ElmColorProvider : ElementColorProvider {
115120
116121 if (call.name.startsWith(" hsl" )) {
117122 val hsl = color.toRGB().toHSL()
118- call.args[0 ].replace(factory.createNumberConstant(hsl.h.toFloat( ).render()))
119- call.args[1 ].replace(factory.createNumberConstant(( hsl.s / 100f ) .render()))
120- call.args[2 ].replace(factory.createNumberConstant(( hsl.l / 100f ) .render()))
123+ call.args[0 ].replace(factory.createNumberConstant(hsl.hueOr( 0 ).render()))
124+ call.args[1 ].replace(factory.createNumberConstant(hsl.s.render()))
125+ call.args[2 ].replace(factory.createNumberConstant(hsl.l.render()))
121126 } else {
122127 call.args[0 ].replace(color.red, call.useFloat)
123128 call.args[1 ].replace(color.green, call.useFloat)
@@ -127,12 +132,12 @@ class ElmColorProvider : ElementColorProvider {
127132 call.args.getOrNull(3 )?.replace(color.alpha, true )
128133 }
129134
130- private fun stringColorSettingRunnable (element : PsiElement , color : Color ): Runnable ? {
135+ private fun stringColorSettingRunnable (element : PsiElement , color : AwtColor ): Runnable ? {
131136 if (element.elementType != REGULAR_STRING_PART ) return null
132137 return Runnable { setCssColorInString(element, color) }
133138 }
134139
135- private fun setCssColorInString (element : PsiElement , color : Color ) {
140+ private fun setCssColorInString (element : PsiElement , color : AwtColor ) {
136141 val parent = element.parent as ? ElmStringConstantExpr ? : return
137142 val match = colorRegex.find(element.text)?.value ? : return
138143
@@ -142,15 +147,15 @@ class ElmColorProvider : ElementColorProvider {
142147
143148 val newColor = when {
144149 match.startsWith(" #" ) -> rgb.toHex()
145- match.startsWith(" rgb" ) -> rgb.toCssRgb (
146- commas = commas,
147- namedRgba = match.startsWith(" rgba" ),
148- rgbPercent = percentCount > 1 ,
150+ match.startsWith(" rgb" ) -> rgb.formatCssString (
151+ legacyFormat = commas,
152+ legacyName = match.startsWith(" rgba" ),
153+ unitsPercent = percentCount > 1 ,
149154 alphaPercent = percentCount == 1 || percentCount == 4
150155 )
151- match.startsWith(" hsl" ) -> rgb.toCssHsl (
152- commas = commas,
153- namedHsla = match.startsWith(" hsla" ),
156+ match.startsWith(" hsl" ) -> rgb.toHSL().formatCssString (
157+ legacyFormat = commas,
158+ legacyName = match.startsWith(" hsla" ),
154159 hueUnit = when {
155160 " deg" in match -> AngleUnit .DEGREES
156161 " grad" in match -> AngleUnit .GRADIANS
@@ -189,14 +194,14 @@ private data class FuncCall(
189194 }
190195}
191196
192- fun com.github.ajalt.colormath. Color.toAwtColor (): Color = toRGB ().let {
193- Color (it.r, it.g, it.b, ( it.a * 255 ).roundToInt() )
197+ fun Color.toAwtColor (): AwtColor = toSRGB ().let {
198+ AwtColor (it.r, it.g, it.b, it.alpha )
194199}
195200
196- private fun Color .toRGB () = RGB (red, green, blue, alpha / 255f )
201+ private fun AwtColor .toRGB () = RGB .from255 (red, green, blue, alpha)
197202
198203private fun Float.render (): String = when (this ) {
199204 0f -> " 0"
200205 1f -> " 1"
201- else -> String .format(Locale .ENGLISH , " %.4f " , this ).trimEnd(' 0' ).trimEnd(' .' )
206+ else -> String .format(Locale .ENGLISH , " %.2f " , this ).trimEnd(' 0' ).trimEnd(' .' )
202207}
0 commit comments