Skip to main content

Synth Week, Bonus Day

Posted by gfx on September 16, 2005 at 3:15 PM PDT

Painters Aggregation

Synth lets you define a painter for each region of a component. A painter can be used, for instance, to draw a button's border or a tabbed pane's tabs. Here is a short example:

<style id="buttonStyle">
    <state>
        <imagePainter method="buttonBackground"
                         path="images/button.png"
                         sourceInsets="5 6 7 6" />
    </state>
</style>

This style declaration draws the background region of a button with an image painter. A painter is identified by its method (or the component's region to paint) and sometimes a direction. Scrollbars are a perfect example for the direction property:

<style id="scrollBarThumbStyle">
    <state>
        <imagePainter method="scrollBarThumbBackground"
                         direction="horizontal"
                         path="images/scrollBar-thumb-horizontal.png"
                         sourceInsets="0 7 0 7" />
        <imagePainter method="scrollBarThumbBackground"
                         direction="vertical"
                         path="images/scrollBar-thumb-vertical.png"
                         sourceInsets="7 0 7 0" />
    </state>
</style>

This style defines the painters for scrollbars thumbs. The pictures are stretched to match the size of the thumb they are associated to. The following pictures represent the image used as a source by the first painter and the result once applied to the component itself:

Everything works as expected. Unfortunately there is no way, using this stretching technique, to also draw a grip on the scrollbar thumb. Yet I managed to do it in the following application:

This application takes advantage of a new Sytnh feature in Mustang, painters aggregation. I you declare several equal painters in Tiger, only the last one will be used. Two painters are equal when they have the same method and the same direction. Mustang changes this behavior by aggregating them into a single painter. The resulting painter can be seen as a stack of painters, the first one declared in the XML file being at the bottom of the stack. Thus, we can achieve our "grip" effect in the scrollbar by changing our previous style:

<style id="scrollBarThumbStyle">
    <state>
        <imagePainter method="scrollBarThumbBackground"
                         direction="horizontal"
                         path="images/scrollBar-thumb-horizontal.png"
                         sourceInsets="0 7 0 7" />
        <imagePainter method="scrollBarThumbBackground"
                         direction="vertical"
                         path="images/scrollBar-thumb-vertical.png"
                         sourceInsets="7 0 7 0" />
        <imagePainter method="scrollBarThumbBackground"
                         direction="horizontal"
                         path="images/scrollBar-thumb-horizontal-grip.png"
                         center="true" />
        <imagePainter method="scrollBarThumbBackground"
                         direction="vertical"
                         path="images/scrollBar-thumb-vertical-grip.png"
                         center="true" />
    </state>
</style>

As you can see, we just create two new painters of the same method and direction as the original ones only in this case they use the property center="true" to prevent stretching.

Scrollbars thumbs are only one example of where aggregated painters come in handy and you can think of many other examples. For instance, you can easily compose a button with a gradient and a transparent gloss to create an Aqua style. By aggregating painters instead of compositing everything in one picture gives your more flexibility in case you need to modify part of the style. And remember you can aggregate more than two painters.

Related Topics >>