# What is an efficient way of selecting multiple colors via Manipulate?

Background: The following snippet is what I (intend to) use in a Manipulate form where up to 12 different colors can be selected:

 Manipulate[{sliderCol1},
Row[{"Kleur 1: ", ColorSlider[
Dynamic[sliderCol1] ,
AppearanceElements -> {"SwatchSpectrum"},
ImageSize -> {200, 40},
BaselinePosition -> Scaled[.25]]}
]
]


To make this work with fields sliderCol1 to sliderColn (where $n$ = 2, …, 12), I see no other option than copying the code in Row so many times.

Question: Is there a less verbose way of implenting a multiple (here 12) color selector using color sliders?

-
Note you can create a swatch as simply as Manipulate[x, {x, Red}], or maybe Manipulate[x, {{x, Red, "Kleur 1"}, Red}]. –  Szabolcs Apr 9 '12 at 9:47
That gets me going a while. Thanks - ( I got the snippet from a Wolfram Demonstrations file!, anyway I 'll bang my head against the wall a few times. ) –  ndroock1 Apr 9 '12 at 9:54
I realize it does not answer your question---which is why I kept it as a comment. In general, it would be interesting to know how to implement custom controls which can be used in the standard way, i.e. control[Dynamic[var]] would set var. var in this case could be a list of colours. I feel rusty though so maybe this is just not the right approach ... –  Szabolcs Apr 9 '12 at 9:59
I feel a similar question was asked already, but can't find it. Maybe it's on SO. Maybe someone remembers. –  Vitaliy Kaurov Apr 9 '12 at 10:17

## 3 Answers

With this one you just click the circle to be color-edited. No need to pick an index number first.

DynamicModule[{x = 1},
Manipulate[c[[x]] = color;
Grid[
Table[
Setter[Dynamic[x, (color = c[[#1]]; x = #1) &], i*4 + j,
Graphics[{FaceForm[c[[i*4 + j]]], Disk[]}, ImageSize -> 40]
], {i, 0, 2}, {j, 4}
]
], {color, Red},
Initialization :> {c = ConstantArray[Black, 12]}]
]


Note that I used Dynamic's alternative syntax form, where you determine what should happen if the argument needs to be updated. In this case I use it to set the starting color of the color selector to be the current color of the circle being clicked. Otherwise the color of the circle would be set by the current setting of the color setter. This may be or may not be how you want the control to behave. Just change it to Dynamic[x] if you want to have the other behavior.

-
That's the one I will use, thank you. –  ndroock1 Apr 9 '12 at 10:53
Neat idea :) +1 –  Vitaliy Kaurov Apr 9 '12 at 18:14
To avoid having global variables in Manipulate you could add x and c to the list of controls with ControlType -> None. –  Heike Apr 10 '12 at 10:52
@Heike that, or use a DynamicModule. Will update tonight. –  Sjoerd C. de Vries Apr 10 '12 at 12:21

If to have multiple controls is not essential, to avoid interface overcrowding, one could try another approach. You do not need 12 controls to control 12 different things. You could just have 2 inter-connected controls: the color and the indexer telling the color which thing to change. Here is an example:

Manipulate[c[k] = color;
GraphicsGrid@Partition[Graphics /@Table[{c[a], Disk[],
Text[Style[ToString[a], Blue, 30]]}, {a, 12}], 4],
Button["Random Reset", Table[c[a] = Hue[RandomReal[1, 3]], {a, 12}]],
Button["Black Reset", Table[c[a] = Black , {a, 12}]],
{color, Red}, {{k, 1, "index"}, Range[12], Setter},
Initialization :> {Table[c[a] = Hue[RandomReal[1, 3]], {a, 12}]}]


Notice c[k] are global variables here - localize if leaks can cause problems.

-
Very neat indeed, if the index numbers were placed in a grid to match the physical layout of the colour disks, that would be even sweeter. –  image_doctor Apr 9 '12 at 10:25
@image_doctor thank you, done. –  Vitaliy Kaurov Apr 9 '12 at 10:35

This is one way to do this

With[{n = 12},
With[{names = ToExpression[Array["sl" <> ToString[#] &, n]]},
Manipulate[
GraphicsGrid[Partition[Graphics[{{#, Disk[]}}] & /@ names, 4],
Spacings -> {0, 0}],

Evaluate[Sequence @@
MapIndexed[
{{#, Hue[#2[[1]]/n], Row[{"Kleur ", #2[[1]]}]},
ColorSlider[#, AppearanceElements -> {"SwatchSpectrum"},
ImageSize -> {200, 40},
BaselinePosition -> Scaled[.25]] &} &, names]
]]]]


Here, names contains a list of variables {sl1,...,sl12}. This list is used to construct a sequence of controls. Since Manipulate has attribute HoldAll, we need Evaluate to construct the controls before they're used in Manipulate.

-