Sunday, November 26, 2006

Color picker example

I put together a short example showing how the "models" feature in the Factor UI can be used to wire together interfaces with very little code. The example displays a window with three sliders for changing the R/G/B values of the color shown in a preview pane. Also, a label displays numeric R/G/B values.

The code is in darcs, examples/color-picker.factor. Here is a walk-through:

We start with the usual vocabulary boilerplate:
IN: color-picker
USING: gadgets-sliders gadgets-labels gadgets models arrays
namespaces kernel math prettyprint sequences ;

We have a word which creates a slider with a maximum value of 255, and a scrolling increment of 1 when clicking the up/down arrows:
: <color-slider> ( -- gadget )
<x-slider>
1 over set-slider-line
255 over set-slider-max ;

Now, a word which creates a gadget whose fill color comes from a model:
: <color-preview> ( model -- gadget )
<gadget> { 100 100 } over set-rect-dim
[ set-gadget-interior ] <control> ;

A word which creates a model that wraps an underlying model, converting R/G/B triplets from 0 to 255 to an instance of the <solid> class, which can then be passed to set-gadget-interior:
: <color-model> ( model -- model )
[ [ 256 /f ] map 1 add <solid> ] <filter> ;

A word to create three slider gadgets, and a model holding the chosen R/G/B triple:
: <color-sliders> ( -- model gadget )
[
<color-slider> dup , control-model
<color-slider> dup , control-model
<color-slider> dup , control-model
3array <compose>
] { } make make-pile 1 over set-pack-fill ;

Finally, a word to put everything together; the color sliders, the color-changing preview gadget, and finally a label control which displays numeric R/G/B values:
: <color-picker> ( -- gadget )
{
{ [ <color-sliders> ] f f @top }
{ [ dup <color-model> <color-preview> ] f f @center }
{ [ [ unparse ] <filter> <label-control> ] f f @bottom }
} make-frame ;

And here is the module boilerplate:
PROVIDE: examples/color-picker ;

MAIN: examples/color-picker
<color-picker> "Color Picker" open-titled-window ;

A screenshot:

No comments: