Introduction
This article describes the implementation of a new element engine
for the Tk theme extension. The Tile extension exposes an API via
the tkTheme.h header and a stubs library
ttkstubs. Using the stubs library ensures that our
extension will be upwards compatible with future versions of tile
(although at the time of writing this is an alpha extension and the
API is subject to change until version 1 has been released). The
tkTheme API exposes enough functions to write a new element engine -
that is we can create a plugin to describe new ways of creating
themed elements. We shall test this feature using Microsoft's GDI+
API on Windows. On the right is an example of the tile
square widget with a GDI+ gradient background element and
the square element itself redefined using a gradient rectangle.
First lets see how we might like to define such elements and tie them into a widget layout. For more information about these terms see the previous article. We will use an SVG-like language to describe the shapes that we want drawn. In a more complete implementation it might be good to be able to fully use SVG to describe elements but this is beyond the scope of this article.
style element create gdi.background gdiplus { ellipse -cx 50 -cy 50 -rx 30 -ry 30 -fill {#404040 #f0f0f0} } style element create gdi.square gdiplus { rectangle -width 25 -height 25 -fill {SteelBlue4 LightSteelBlue} -stroke {black 1} } style layout TSquare { Square.gdi.background -sticky news Square.padding -sticky news -children { Square.gdi.square -sticky {} } }
In this style code we are creating two new elements using the gdiplus engine that we intend to create. The first will be an 60 pixel circle with a grey to near-white gradient fill. The second is a square with a solid black border and blue gradient fill. The widget layout is then rewritten to use the new elements. If we now create a ttk::square widget we will see something like the image above.
There are lots of things missing from this code. We need to be able to pick the color from the widget options. We will need to be able to get color descriptions that Tk does not normally support. Here we are using a multi-element list for the fill to get a gradient and for the stroke to specify the colour and width. But we will need to extend this to support gradient pens, alpha channel transparency and non-linear gradients. However this will do for now. Fortunately the design of Tile widgets permits us to receive any value and is not restricted to Tk colours so our engine code can implement parsing of colour descriptions.
We also need to be able to specify an alternate element drawing description based upon state. If we were doing an elliptical button then we would want to draw something different when the state is pressed or active.