GraphicsBuilder Tutorial I: Shapes
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' )
}
- Login or register to post comments
- 11387 reads
- Printer-friendly version
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)










Comments
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 Mon, 2008/02/04 - 5:46am
Hi,
I do complite agree with Christopher.
http://www.forum.eatak.com
Andres Almiray replied on Mon, 2008/02/04 - 12:44pm
in response to: chrisbrown
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: chrisbrown
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