More skinable tk widgets

Buttons are easy to create, as we have seen in the last installment of
this series. What about more complex widgets? Both Xmms and Winamp® feature
a nice volume control. Is this possible with tcl code too?
Of course! This time I will show you how to do this. Let's look at the bitmap
for the several volume level states of the control:

The image have two main sections. The first section is an array of images
for the background of the control, for a quantized number of volume settings.
The second section have the slider button in two states, idle or while dragging
the control. The background images moreover, are 28, what means we must approximate
to one of two, when doing a fine adjust at the actual volume level.
The code to import those bitmaps in our tcl program is very easy. Each bitmap
is 15 pixels high, so we may write a loop to place each slice in a tk's image
object, which we will name is0, is1, ... is27.

Now we need to capture the slider images, as well. The code is not much more
difficult. We just have to take care of the offsets and determinate
the size of the slider images before coding. We will get those images asib0
and ib1.

Now we need to display both images, one for the background of the controle,
and the other for the slider. As we want the slider displayed over the background,
the choice of geometry managers will be the placer. Then we create
a container frame and place both images as labels, the slider image over
the background.

Here is how it looks like, just after being displayed:
Now, look at the same widget, as we move the slider:
Notice that, in the top image, the first background is being displayed. The
slider gets its first bitmap, or ib1, because the other will show
only when the mouse grabs it. The next step now is to define the bindings,
so it will behave as expected. There are two kind of bindings we need. First,
binding for the slider motion, so we set our background bitmap reflecting
its position change, and also place the slider in a new location when the
mouse buttons is released. The other binding is for when the user clicks
outside of the slider, in the background directly, which should result in
a quick change of the volume.
Let's look at the bindings for everything:

Ok, this is not practical to use as a widget yet, but I hope you got the
idea. Some suggestions to change this short tutorial in a real world widget
are, first change all the local variables into array components or regular
namespace variables, where each instance of the widget have its own private
variables. Second, when changing the slider position, store the (possibly
scaled) value of its new position in a user defined variable for the official
position (like -variable in regular tk's scale widget). This
is done near the end of .lb1 <B1-Motion> binding. Third, create
code for transparent creation and destruction of the widget.