Factor Language Blog

Color picker example

Sunday, November 26, 2006

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: