# SwingBuilder

version 2.4.21

`SwingBuilder` allows you to create full-fledged Swing GUIs in a declarative and concise fashion. It accomplishes this by employing a common idiom in Groovy, builders. Builders handle the busywork of creating complex objects for you, such as instantiating children, calling Swing methods, and attaching these children to their parents. As a consequence, your code is much more readable and maintainable, while still allowing you access to the full range of Swing components.

Here’s a simple example of using `SwingBuilder`:

    import groovy.swing.SwingBuilder
    import java.awt.BorderLayout as BL

    count = 0
    new SwingBuilder().edt {
      frame(title: 'Frame', size: [300, 300], show: true) {
        borderLayout()
        textlabel = label(text: 'Click the button!', constraints: BL.NORTH)
        button(text:'Click Me',
             actionPerformed: {count++; textlabel.text = "Clicked ${count} time(s)."; println "clicked"}, constraints:BL.SOUTH)
      }
    }

Here is what it will look like:

This hierarchy of components would normally be created through a series of repetitive instantiations, setters, and finally attaching this child to its respective parent. Using `SwingBuilder`, however, allows you to define this hierarchy in its native form, which makes the interface design understandable simply by reading the code.

The flexibility shown here is made possible by leveraging the many programming features built-in to Groovy, such as closures, implicit constructor calling, import aliasing, and string interpolation. Of course, these do not have to be fully understood in order to use `SwingBuilder`; as you can see from the code above, their uses are intuitive.

Here is a slightly more involved example, with an example of `SwingBuilder` code re-use via a closure.

    import groovy.swing.SwingBuilder
    import javax.swing.*
    import java.awt.*

    def swing = new SwingBuilder()

    def sharedPanel = {
         swing.panel() {
            label("Shared Panel")
        }
    }

    count = 0
    swing.edt {
        frame(title: 'Frame', defaultCloseOperation: JFrame.EXIT_ON_CLOSE, pack: true, show: true) {
            vbox {
                textlabel = label('Click the button!')
                button(
                    text: 'Click Me',
                    actionPerformed: {
                        count++
                        textlabel.text = "Clicked ${count} time(s)."
                        println "Clicked!"
                    }
                )
                widget(sharedPanel())
                widget(sharedPanel())
            }
        }
    }

Here’s another variation that relies on observable beans and binding:

    import groovy.swing.SwingBuilder
    import groovy.beans.Bindable

    class MyModel {
       @Bindable int count = 0
    }

    def model = new MyModel()
    new SwingBuilder().edt {
      frame(title: 'Java Frame', size: [100, 100], locationRelativeTo: null, show: true) {
        gridLayout(cols: 1, rows: 2)
        label(text: bind(source: model, sourceProperty: 'count', converter: { v ->  v? "Clicked $v times": ''}))
        button('Click me!', actionPerformed: { model.count++ })
      }
    }

@Bindable is one of the core AST Transformations. It generates all the required boilerplate code to turn a simple bean into an observable one. The `bind()` node creates appropriate `PropertyChangeListeners` that will update the interested parties whenever a `PropertyChangeEvent` is fired.