# Copy + paste color palettes into your program

**URL:** <https://openrndr.discourse.group/t/copy-paste-color-palettes-into-your-program/519>\
**Category:** Tutorials\
**Created:** [February 22, 2023, 10:11am UTC](https://openrndr.discourse.group/t/copy-paste-color-palettes-into-your-program/519 "2023-02-22T10:11:26Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [February 22, 2023, 10:11am UTC](https://openrndr.discourse.group/t/copy-paste-color-palettes-into-your-program/519/1 "2023-02-22T10:11:26Z")

</div>

I saw that Edwin just [added](https://github.com/openrndr/orx/commit/7014ef464b5085390033c008952aadb169b0e8bd) ctrl+v support for orx-panel to paste colors and I thought… wow, it would be cool to copy color palettes from any website and just paste them into my program, so I wrote this [PoC](https://en.wikipedia.org/wiki/Proof_of_concept):

```auto
import org.openrndr.KeyModifier
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.color.rgb
import org.openrndr.extra.shapes.grid

fun main() = application {
    program {
        val palette = mutableListOf(ColorRGBa.PINK)
        extend {
            if(palette.isNotEmpty()) {
                drawer.bounds.grid(palette.size, 1, 20.0, 20.0).flatten().forEachIndexed { i, rect ->
                    drawer.fill = palette[i]
                    drawer.rectangle(rect)
                }
            }
        }
        keyboard.keyDown.listen { ev ->
            if (KeyModifier.CTRL in ev.modifiers || KeyModifier.SUPER in ev.modifiers) {
                if (ev.name == "v") {
                    clipboard.contents?.let { pasted ->
                        val regex = """[#x]([0-9a-fA-F]{6})([^0-9a-fA-F]|$)""".toRegex()
                        val colors = regex.findAll(pasted).filter {
                            it.groupValues.size == 3
                        }.map {
                            it.groupValues[1]
                        }.distinct().map {
                            rgb(it)
                        }.toList()
                        palette.clear()
                        palette.addAll(colors)
                    }
                    ev.cancelPropagation()
                }
            }
        }
    }
}

```

So I can select some text in a website, press ctrl+c…  
 ![image](https://global.discourse-cdn.com/free1/uploads/openrndr/original/1X/aaa4ebaa494a01b01732b873db194f2864b585d1.png)

Then click on the window of the program above and press ctrl+v…  
 ![image](https://global.discourse-cdn.com/free1/uploads/openrndr/original/1X/6b7cec271ec41b79b213352a9ff79646a728b145.png)

In the past I used to copy the colors one by one into the source code and then run the program, but this is much more convenient! 🙂

The regular expression will try to parse the colors and ignore anything else, so copying a string like

```auto
I like #F5E6CA and also #FB9300 combined with 0xF54748 and 0x343F56

```

would also work 🙂

---

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [February 23, 2023, 10:40am UTC](https://openrndr.discourse.group/t/copy-paste-color-palettes-into-your-program/519/2 "2023-02-23T10:40:47Z")

</div>

As an `Extension`, to make it more reusable:

```auto
import org.openrndr.Extension
import org.openrndr.KeyModifier
import org.openrndr.Program
import org.openrndr.color.ColorRGBa
import org.openrndr.color.rgb

/**
 * OPENRNDR extension to enable
 * CTRL+V to paste a color palette copied from any website.
 * The extension searches in the clipboard for colors
 * formatted as #123456 or 0x123456.
 */

class PastePalette : Extension {
    override var enabled: Boolean = true

    val colors = mutableListOf<ColorRGBa>()

    var size = 0
        get() = colors.size

    fun isEmpty() = colors.isEmpty()
    fun isNotEmpty() = colors.isNotEmpty()

    override fun setup(program: Program) {
        println("Listening to CTRL+V")
        program.keyboard.keyDown.listen { ev ->
            if (KeyModifier.CTRL in ev.modifiers && ev.name == "v") {
                program.clipboard.contents?.let { pasted ->
                    val regex = """[#x]([0-9a-fA-F]{6})([^0-9a-fA-F]|$)""".toRegex()
                    val colors = regex.findAll(pasted).filter {
                        it.groupValues.size == 3
                    }.map {
                        it.groupValues[1]
                    }.distinct().map {
                        rgb(it)
                    }.toList()
                    this.colors.clear()
                    this.colors.addAll(colors)
                }
                ev.cancelPropagation()
            }
        }
    }
}

```

Then it can be used like this:

```auto
import PastePalette
import org.openrndr.application
import org.openrndr.extra.shapes.grid

fun main() = application {
    program {
        val palette = PastePalette()
        extend(palette)
        extend {
            if(palette.isNotEmpty()) {
                drawer.bounds.grid(palette.size, 1, 20.0, 20.0).flatten().forEachIndexed { i, rect ->
                    drawer.fill = palette.colors[i]
                    drawer.rectangle(rect)
                }
            }
        }
    }
}

```
