Andres is a DZone Zone Leader and has posted 143 posts at DZone. You can read more from them at their website. View Full User Profile

# GraphicsBuilder Tutorial I: Shapes

02.02.2008
| 28284 views |

## Arrows

If you thought we would be finished by now, there are other shapes we can explore! Arrows can be found almost anywhere so it makes sense to have a shape for them. Arrows have a tail and a head, depth controls how much the tail and head share from the total width, rise controls how much the tail takes from the total height, finally arrows can also be quick rotated with an angle property.

`def values = [0,0.25,0.5,0.75]def colors = ['red','darkOrange','blue','darkGreen']def angles = [0,45,150,240](0..3).each { index ->   arrow( x: 10 + (index*110), y: 10, width: 80, height: 50, depth: values[index],          borderColor: 'black', fill: colors[index] )   arrow( x: 10 + (index*110), y: 80, width: 80, height: 50, rise: values[index],          borderColor: 'black', fill: colors[index] )   arrow( x: 10 + (index*110), y: 150, width: 90, height: 50, angle: angles[index],          borderColor: 'black', fill: colors[index] )}`

## Crosses

If arrows are common, crosses are too (nothing related to religious ones), you can find them as plus signs or as error indicators. they can have a round finish and can also be rotated with an angle property.

`def roundness = [0,0.5,1]def colors = ['red','blue','darkGreen']def angles = [0,45,60](0..2).each { index ->   cross( cx: 50 + (index*110), cy: 50, radius: 40, borderColor: 'black',          roundness: roundness[index], fill: colors[index] )   cross( cx: 50 + (index*110), cy: 160, radius: 40, borderColor: 'black',          roundness: roundness[index], fill: colors[index], angle: angles[index] )}`

## Pins

Pins can be described as a mix between a semi-circle and an isosceles triangle, you may find a similar shape while using an online map provider known for it's "do no evil" mantra. Pins can also be rotated with an angle property (see a trend here :-)) and they can change the height of the triangle.

`def heights = [40,10,60]def colors = ['red','blue','darkGreen']def angles = [0,45,60](0..2).each { index ->   pin( cx: 50 + (index*110), cy: 50, radius: 40, borderColor: 'black',          height: heights[index], fill: colors[index] )   pin( cx: 50 + (index*110), cy: 160, radius: 40, borderColor: 'black',          height: heights[index], fill: colors[index], angle: angles[index] )}`

## Multi Rounded Rectangles

The last shape (or is it?) is the multi rounded rectangle. It gives you more control over how each corner will or will not be rounded. Opposed to just arcWidth and arcHeight properties found on the rect shape, roundRect allows 2 round properties for each corner.

`roundRect( x: 10, y: 10, width: 140, height: 100, borderColor: 'black',   topLeftWidth: 20, bottomLeftWidth: 20, topRightWidth: 50, bottomRightWidth: 50,   fill: 'red' )roundRect( x: 160, y: 10, width: 140, height: 100, borderColor: 'black',   topLeftWidth: 20, topLeftHeight: 40, bottomLeftWidth: 40, bottomLeftHeight: 20,   topRightWidth: 0, topRightHeight: 0, bottomRightWidth: 60, bottomRightHeight: 70,   fill: 'blue' )}`

Published at DZone with permission of its author, Andres Almiray.
Tags:

### Christopher Brown replied on Mon, 2008/02/04 - 3:45am

Hi Andres,

How does this relate to https://scenegraph.dev.java.net/ ?

I'm assuming that with the Groovy graphics builder, you would need to use the builder on every UI repaint to completely repaint the image.  The scene graph API aims to create shapes that stay defined in memory between repaints, a bit like SVG without the XML, so with the SGAPI you define your circle once then have the choice of manipulating it through time.

Other questions: if not SGAPI-compatible, is there clipping support for the groovy graphics (i.e.: ways of making it easier to deal with) so that you don't waste time drawing shapes outside of the painting area?

Thanks,

Chris

### Mahesh Kumar Nayak replied on Fri, 2011/05/20 - 3:48pm

Hi,

I do complite agree with Christopher.

### Andres Almiray replied on Mon, 2008/02/04 - 12:44pm in response to: Christopher Brown

Chris, GraphicsBuilder and SceneGraph share many traits but they are essentially two different and unrelated implementations. When I saw the announcement of SceneGraph my first reaction was to rework GraphicsBuilder to support it but because their API is still in flux I refrained to do so. Perhaps when their API goes to 1.0 GraphicsBuilder will be able to export/import SGAPI code, that would be great.

On the UI repaint, it depends on what you are trying to accomplish, GB includes a basic component where you can place your drawings: GraphicsPanel. This component is smart enough to redraw whenever it needs to, and only those places that have actually changed, which means it honors the clip. All shapes take into consideration the curret clip, no need to waste cycles, there is also an option to specify custom clips with the clip() node. You can also render to images directly and use your own cache mechanism.

GB can also reuse shape definitions, either with a normal Groovy variable or with an special 'asShape' property which I didn't show in this tutorial, but now that the topic has surfaced I will make sure it is included in the next part.

If you care to know more about GraphicsBuilder before I finish the other parts of the tutorial, please visit the project's site, you will also find more info at my blog, you'll see that GB has more to offer that what has been shown so far here.

Cheers,
Andres

### Andres Almiray replied on Mon, 2008/02/04 - 12:48pm in response to: Christopher Brown

You may also find this link useful, the images are snapshots of GraphicsPanel in action, a custom clip has been set (so that the radial lines do not extend beyond the rounded rectangle), you will also see other options as paints (and multipaints, a unique feature so far).

Cheers,
Andres