While SwingBuilder comes with almost all of the standard Swing widgets, sometimes you need to add custom or extended components. There are several ways to accomplish this.

Use a Pass-Through Element

SwingBuilder has two 'magic' elements that pass through the value argument or the named attribute to the parent container. The widget element has been in Groovy since 1.0. New in Groovy 1.1Beta2 is the container element. Currently they are identical in behavior and should be used mostly to increases code readability: elements that can contain children should use container while widget elements should contain no children. (in a future build this restriction may be enforced at the builder level).

To use the widget or container elements you pass in the desired custom widget or custom container object as the value argument or the widget: or container: attributes respectively.

swing.frame() {
    container(new MyCustomDocingPanel(), constraints:BorderLayout.CENTER) {
        widget(new CustomMappingComponent())
    }
    container(container:new CustomOutlookBar(), constraints:BorderLayout.WEST) {
        widget(widget:new MyCustomButton())
    }
}


Value Argument Replacement (new in 1.1Beta2)

Most widgets accept a widget of the appropriate type in the value argument of the swing builder element. If your extended component extends a common swing widget type you can supply an instance of that component in the value argument.

swing.frame() {
    button(new MyCustomButton("custom constructor"), enabled:false)
}


Register a Bean Factory (new in 1.1Beta2)

If your custom component follows the JavaBeans specification, specifically having a no-argument public constructor, then you can register your component directly with the SwingBuilder and use it as a first class element. To do this call the registerBeanFactory(String, Class) method with the desired element name and Bean class.

swing.registerBeanFactory('magicButton', MagicButton.class)
swing.frame() {
    magicButton("It's Magical!")
}


Register a Custom Factory (new in 1.1Beta2)

Sometimes you will need greater interaction with the supplied values in the SwingBuilder, or you want to accomplish richer things with the supplied arguments. In this case you can register a custom factory. Custom factories implement groovy.swing.factory.Factory and are registered via the registerFactory(String, Factory) method.

All of the elements that do interesting things with their argument values and that need to access different constructors or lack no-argument constructors utilize this interface. Tricks such as accessing the Action constructors in the button type widgets, using the javax.swing.Box factory methods are two such real world examples.

// a bit of a goofy example, we forcefully make the button blue
swing.registerFactory('blueButton',
    [newInstance:{builder, name, value, attrs ->
        attrs.remove('color')
        builder.button(value, color:Color.BLUE)}
    ] as groovy.swing.factory.Factory)

swing.frame() {
    blueButton('I want to be red!', color:Color.RED)
}