home | career | drupal | java | mac | mysql | perl | scala | uml | unix

Groovy example source code file (SwingBuilderBindingsTest.groovy)

This example Groovy source code file (SwingBuilderBindingsTest.groovy) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Groovy tags/keywords

alpha, awt, bean, boston, bravo, bravo, button, charlie, charlie, checkbox, chicago, delta, delta, denver, gui, javabean, swing, swingbuilder, swingbuilder, text

The Groovy SwingBuilderBindingsTest.groovy source code

/*
 * $Id: SwingBuilderBindingsTest.groovy 20649 2010-08-23 15:11:45Z aalmiray $
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package groovy.swing

import java.awt.event.ActionEvent
import java.beans.PropertyChangeEvent
import java.beans.PropertyVetoException
import javax.swing.DefaultBoundedRangeModel
import javax.swing.DefaultButtonModel
import javax.swing.text.PlainDocument
import java.text.SimpleDateFormat
import groovy.beans.Bindable
import groovy.beans.Vetoable
import javax.swing.SpinnerNumberModel
import javax.swing.ListSelectionModel
import javax.swing.DefaultListModel

public class SwingBuilderBindingsTest extends GroovySwingTestCase {

    public void testSliderValueBinding() {
      testInEDT {
        SwingBuilder swing = new SwingBuilder()

        swing.actions() {
            slider(id:'sl')
            textField(id:'txt', text:bind(source:sl, sourceProperty:'value', id:'binding'))
            slider(id:'slReverse', value:bind(source:sl, sourceProperty:'value', id:'bindingReverse'))
            // need to use a second slider for reverse test, because string->int autobox, not so happy
        }

        swing.sl.value = 10
        assert swing.txt.text == '10'
        swing.sl.value = 95
        assert swing.txt.text == '95'

        swing.binding.rebind()
        swing.sl.value = 42
        assert swing.txt.text == '42'
        swing.binding.unbind()
        swing.sl.value = 13
        assert swing.txt.text == '42'
        swing.binding.bind()
        assert swing.txt.text == '42'
        swing.binding.update()
        assert swing.txt.text == '13'

        swing.sl.model = new DefaultBoundedRangeModel(30, 1, 20, 40)
        assert swing.txt.text == '30'

        // first make sure we've been fireing
        assert swing.slReverse.value == 30
        swing.slReverse.value = 21
        swing.bindingReverse.reverseUpdate()
        assert swing.sl.value == 21
      }
    }

    public void testSpinnerValueBinding() {
      testInEDT {
        SwingBuilder swing = new SwingBuilder()

        swing.actions() {
            spinner(id:'sp', model:spinnerNumberModel(minimum:0, maximum:100, stepSize:5))
            textField(id:'txt', text:bind(source:sp, sourceProperty:'value', id:'binding'))
            spinner(id:'spReverse', value:bind(source:sp, sourceProperty:'value', id:'bindingReverse'))
            // need to use a second spinner for reverse test, because string->int autobox, not so happy
        }

        swing.sp.value = 10
        assert swing.txt.text == '10'
        swing.sp.value = 95
        assert swing.txt.text == '95'

        swing.binding.rebind()
        swing.sp.value = 42
        assert swing.txt.text == '42'
        swing.binding.unbind()
        swing.sp.value = 13
        assert swing.txt.text == '42'
        swing.binding.bind()
        assert swing.txt.text == '42'
        swing.binding.update()
        assert swing.txt.text == '13'

        swing.sp.model = new SpinnerNumberModel(30, 20, 40, 1)
        assert swing.txt.text == '30'

        // first make sure we've been fireing
        assert swing.spReverse.value == 30
        swing.spReverse.value = 21
        swing.bindingReverse.reverseUpdate()
        assert swing.sp.value == 21
      }
    }

    public void testScrollBarValueBinding() {
      testInEDT {
        SwingBuilder swing = new SwingBuilder()

        swing.actions() {
            scrollBar(id:'sb')
            textField(id:'txt', text:bind(source:sb, sourceProperty:'value', id:'binding'))
            scrollBar(id:'sbReverse', value:bind(source:sb, sourceProperty:'value', id:'bindingReverse'))
            // need to use a second scrollBar for reverse test, because string->int autobox, not so happy
        }

        swing.sb.value = 10
        assert swing.txt.text == '10'
        swing.sb.value = 85
        assert swing.txt.text == '85'

        swing.binding.rebind()
        swing.sb.value = 42
        assert swing.txt.text == '42'
        swing.binding.unbind()
        swing.sb.value = 13
        assert swing.txt.text == '42'
        swing.binding.bind()
        assert swing.txt.text == '42'
        swing.binding.update()
        assert swing.txt.text == '13'

        swing.sb.model = new DefaultBoundedRangeModel(30, 1, 20, 40)
        assert swing.txt.text == '30'

        // first make sure we've been fireing
        assert swing.sbReverse.value == 30
        swing.sbReverse.value = 21
        swing.bindingReverse.reverseUpdate()
        assert swing.sb.value == 21
      }
    }

    public void testTextFieldTextBinding() {
      testInEDT {
        SwingBuilder swing = new SwingBuilder()

        swing.actions() {
            textField('Bind', id:'txts')
            textField(id:'txt', text:bind(source:txts, sourceProperty:'text', id:'binding'))
        }

        assert swing.txt.text == 'Bind'
        swing.txts.text = 'Text'
        assert swing.txt.text == 'Text'
        swing.txts.text = 'Easily'
        assert swing.txt.text == 'Easily'

        swing.binding.rebind()
        swing.txts.text = 'With'
        assert swing.txt.text == 'With'
        swing.binding.unbind()
        swing.txts.text = 'bind()'
        assert swing.txt.text == 'With'
        swing.binding.bind()
        assert swing.txt.text == 'With'
        swing.binding.update()
        assert swing.txt.text == 'bind()'

        swing.txt.text = 'reversal'
        swing.binding.reverseUpdate()
        assert swing.txts.text == 'reversal'

        PlainDocument doc = new PlainDocument()
        doc.insertString(0, '{}', null)
        swing.txts.document = doc
        assert swing.txt.text == '{}'
      }
    }

    public void testCheckboxSelectedBinding() {
      testInEDT {
        SwingBuilder swing = new SwingBuilder()

        swing.actions() {
            checkBox(id:'cb')
            textField(id:'txt', enabled:bind(source:cb, sourceProperty:'selected', id:'binding'))
        }

        assert swing.txt.enabled == swing.cb.selected
        swing.cb.selected = !swing.cb.selected
        assert swing.txt.enabled == swing.cb.selected
        swing.cb.selected = !swing.cb.selected
        assert swing.txt.enabled == swing.cb.selected

        swing.binding.rebind()
        swing.cb.selected = !swing.cb.selected
        assert swing.txt.enabled == swing.cb.selected
        swing.binding.unbind()
        swing.cb.selected = !swing.cb.selected
        assert swing.txt.enabled != swing.cb.selected
        swing.binding.bind()
        assert swing.txt.enabled != swing.cb.selected
        swing.binding.update()
        assert swing.txt.enabled == swing.cb.selected

        DefaultButtonModel md = new DefaultButtonModel()
        md.enabled = !swing.txt.enabled
        swing.cb.model = md
        assert swing.txt.enabled == swing.cb.selected

        swing.txt.enabled = !swing.txt.enabled
        swing.binding.reverseUpdate()
        assert swing.txt.enabled == swing.cb.selected
      }
    }

    public void testComboBoxBindSyntheticProperties() {
      testInEDT {
        SwingBuilder swing = new SwingBuilder()
        def comboData = ['Alpha', 'Bravo', 'Charlie', 'Delta']

        def vectorData = ['Adams', 'Boston', 'Chicago', 'Denver']


        swing.frame() {
            comboBox(id: 'combo01', items:comboData)
            comboBox(id: 'combo02', model: new javax.swing.DefaultComboBoxModel(new Vector(vectorData)))

            t1e  = label(text:bind {combo01.elements})
            t1sx = label(text:bind {combo01.selectedIndex})
            t1se = label(text:bind {combo01.selectedElement})
            t1si = label(text:bind {combo01.selectedItem})

            t2e  = label(text:bind {combo02.elements})
            t2sx = label(text:bind {combo02.selectedIndex})
            t2se = label(text:bind {combo02.selectedElement})
            t2si = label(text:bind {combo02.selectedItem})
        }

        assert swing.t1e.text == '[Alpha, Bravo, Charlie, Delta]'
        assert swing.t1sx.text == '0'
        assert swing.t1se.text == 'Alpha'
        assert swing.t1si.text == 'Alpha'

        assert swing.t2e.text == '[Adams, Boston, Chicago, Denver]'
        assert swing.t2sx.text == '0'
        assert swing.t2se.text == 'Adams'
        assert swing.t2si.text == 'Adams'


        swing.combo01.selectedIndex = 1
        assert swing.t1e.text == '[Alpha, Bravo, Charlie, Delta]'
        assert swing.t1sx.text == '1'
        assert swing.t1se.text == 'Bravo'
        assert swing.t1si.text == 'Bravo'

        swing.combo02.selectedIndex = 1
        assert swing.t2e.text == '[Adams, Boston, Chicago, Denver]'
        assert swing.t2sx.text == '1'
        assert swing.t2se.text == 'Boston'
        assert swing.t2si.text == 'Boston'

        swing.combo01.selectedIndex = -1
        assert swing.t1e.text == '[Alpha, Bravo, Charlie, Delta]'
        assert swing.t1sx.text == '-1'
        assert swing.t1se.text == null
        assert swing.t1si.text == null

        swing.combo02.selectedIndex = -1
        assert swing.t2e.text == '[Adams, Boston, Chicago, Denver]'
        assert swing.t2sx.text == '-1'
        assert swing.t2se.text == null
        assert swing.t2si.text == null

        swing.combo01.selectedItem = 'Charlie'
        assert swing.t1e.text == '[Alpha, Bravo, Charlie, Delta]'
        assert swing.t1sx.text == '2'
        assert swing.t1se.text == 'Charlie'
        assert swing.t1si.text == 'Charlie'

        swing.combo02.selectedItem = 'Chicago'
        assert swing.t2e.text == '[Adams, Boston, Chicago, Denver]'
        assert swing.t2sx.text == '2'
        assert swing.t2se.text == 'Chicago'
        assert swing.t2si.text == 'Chicago'

        swing.combo01.selectedItem = 'Fox Trot'
        assert swing.t1e.text == '[Alpha, Bravo, Charlie, Delta]'
        assert swing.t1sx.text == '2'
        assert swing.t1se.text == 'Charlie'
        assert swing.t1si.text == 'Charlie'

        swing.combo02.selectedItem = 'Frank'
        assert swing.t2e.text == '[Adams, Boston, Chicago, Denver]'
        assert swing.t2sx.text == '2'
        assert swing.t2se.text == 'Chicago'
        assert swing.t2si.text == 'Chicago'


        swing.combo01.selectedElement = 'Delta'
        assert swing.t1e.text == '[Alpha, Bravo, Charlie, Delta]'
        assert swing.t1sx.text == '3'
        assert swing.t1se.text == 'Delta'
        assert swing.t1si.text == 'Delta'

        swing.combo02.selectedElement = 'Denver'
        assert swing.t2e.text == '[Adams, Boston, Chicago, Denver]'
        assert swing.t2sx.text == '3'
        assert swing.t2se.text == 'Denver'
        assert swing.t2si.text == 'Denver'

        swing.combo01.selectedElement = 'Golf'
        assert swing.t1e.text == '[Alpha, Bravo, Charlie, Delta]'
        assert swing.t1sx.text == '3'
        assert swing.t1se.text == 'Delta'
        assert swing.t1si.text == 'Delta'

        swing.combo02.selectedElement = 'George'
        assert swing.t2e.text == '[Adams, Boston, Chicago, Denver]'
        assert swing.t2sx.text == '3'
        assert swing.t2se.text == 'Denver'
        assert swing.t2si.text == 'Denver'

        swing.combo01.model.addElement('Echo')
        assert swing.t1e.text == '[Alpha, Bravo, Charlie, Delta, Echo]'

        swing.combo02.model.addElement('Easy')
        assert swing.t2e.text == '[Adams, Boston, Chicago, Denver, Easy]'

        swing.combo01.model.removeElement('Bravo')
        assert swing.t1e.text == '[Alpha, Charlie, Delta, Echo]'

        swing.combo02.model.removeElement('Adams')
        assert swing.t2e.text == '[Boston, Chicago, Denver, Easy]'
      }
    }

    public void testListBindSyntheticProperties() {
      testInEDT {
        SwingBuilder swing = new SwingBuilder()
        def listModel = new DefaultListModel()
        ['Alpha', 'Bravo', 'Charlie', 'Delta'].each {listModel << it}
        def map = [sis:null, ses: null, svs: null] as ObservableMap

        swing.frame() {
            list(id: 'list01', model: listModel, selectionMode: ListSelectionModel.SINGLE_SELECTION)

            t1e  = label(text:bind {list01.elements})
            t1sx = label(text:bind {list01.selectedIndex})
            t1se = label(text:bind {list01.selectedElement})
            t1si = label(text:bind {list01.selectedValue})
            bean(map, sis:bind {list01.selectedIndices},
                      ses:bind {list01.selectedElements},
                      svs:bind {list01.selectedValues})
        }

        assert swing.t1e.text == '[Alpha, Bravo, Charlie, Delta]'
        swing.list01.selectedIndex = -1
        assert swing.t1sx.text == '-1'
        assert swing.t1se.text == null
        assert swing.t1si.text == null
        assert map.sis == []
        assert map.ses == []
        assert map.svs == []

        swing.list01.selectedIndex = 0
        assert swing.t1e.text == '[Alpha, Bravo, Charlie, Delta]'
        assert swing.t1sx.text == '0'
        assert swing.t1se.text == 'Alpha'
        assert swing.t1si.text == 'Alpha'
        assert map.sis == [0]
        assert map.ses == ['Alpha']
        assert map.svs == ['Alpha']

        swing.list01.selectedIndex = 1
        assert swing.t1e.text == '[Alpha, Bravo, Charlie, Delta]'
        assert swing.t1sx.text == '1'
        assert swing.t1se.text == 'Bravo'
        assert swing.t1si.text == 'Bravo'
        assert map.sis == [1]
        assert map.ses == ['Bravo']
        assert map.svs == ['Bravo']

        swing.list01.selectedValue = 'Charlie'
        assert swing.t1e.text == '[Alpha, Bravo, Charlie, Delta]'
        assert swing.t1sx.text == '2'
        assert swing.t1se.text == 'Charlie'
        assert swing.t1si.text == 'Charlie'
        assert map.sis == [2]
        assert map.ses == ['Charlie']
        assert map.svs == ['Charlie']

        swing.list01.selectedValue = 'Fox Trot'
        assert swing.t1e.text == '[Alpha, Bravo, Charlie, Delta]'
        assert swing.t1sx.text == '2'
        assert swing.t1se.text == 'Charlie'
        assert swing.t1si.text == 'Charlie'
        assert map.sis == [2]
        assert map.ses == ['Charlie']
        assert map.svs == ['Charlie']

        swing.list01.selectedElement = 'Delta'
        assert swing.t1e.text == '[Alpha, Bravo, Charlie, Delta]'
        assert swing.t1sx.text == '3'
        assert swing.t1se.text == 'Delta'
        assert swing.t1si.text == 'Delta'
        assert map.sis == [3]
        assert map.ses == ['Delta']
        assert map.svs == ['Delta']

        swing.list01.selectedElement = 'Golf'
        assert swing.t1e.text == '[Alpha, Bravo, Charlie, Delta]'
        assert swing.t1sx.text == '3'
        assert swing.t1se.text == 'Delta'
        assert swing.t1si.text == 'Delta'
        assert map.sis == [3]
        assert map.ses == ['Delta']
        assert map.svs == ['Delta']

        swing.list01.selectionMode = ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
        swing.list01.selectedIndices = ([1i, 3i] as int[])
        assert swing.t1sx.text == '1'
        assert swing.t1se.text == 'Bravo'
        assert swing.t1si.text == 'Bravo'
        assert map.sis == [1, 3]
        assert map.ses == ['Bravo', 'Delta']
        assert map.svs == ['Bravo', 'Delta']

        swing.list01.model.addElement('Echo')
        assert swing.t1e.text == '[Alpha, Bravo, Charlie, Delta, Echo]'

        swing.list01.model.removeElement('Bravo')
        assert swing.t1e.text == '[Alpha, Charlie, Delta, Echo]'
      }
    }


    public void testEventBinding() {
      testInEDT {
        SwingBuilder swing = new SwingBuilder()
        def capture
        swing.actions() {
            button('Button!', id:'b')
            textField(id:'txt', text:bind(source:b, sourceEvent:'actionPerformed', sourceValue:{b.text}))
            textField(id:'txt2', text:bind(source:b, sourceEvent:'actionPerformed', sourceValue:{evt->capture=evt; 'Captured!'}))
        }

        assert swing.txt.text == 'Button!'
        swing.b.text = 'Pressed!'
        // not pressed yet...
        assert swing.txt.text == 'Button!'
        swing.b.doClick()
        //ok, now it's pressed
        assert swing.txt.text == 'Pressed!'
        //check that we get evet as closure arg
        assert swing.txt2.text == 'Captured!'
        assert capture instanceof ActionEvent
      }
    }

    public void testPropertyBinding() {
      testInEDT {
        SwingBuilder swing = new SwingBuilder()

        swing.actions() {
            checkBox('Button!', id:'cb')
            textField(id:'txt', enabled:bind(source:cb, sourceProperty:'enabled', id:'binding'))
        }
        assert swing.txt.enabled == swing.cb.enabled
        swing.cb.enabled = !swing.cb.enabled
        assert swing.txt.enabled == swing.cb.enabled
        swing.cb.enabled = !swing.cb.enabled
        assert swing.txt.enabled == swing.cb.enabled

        swing.binding.rebind()
        swing.cb.enabled = !swing.cb.enabled
        assert swing.txt.enabled == swing.cb.enabled
        swing.binding.unbind()
        swing.cb.enabled = !swing.cb.enabled
        assert swing.txt.enabled != swing.cb.enabled
        swing.binding.bind()
        assert swing.txt.enabled != swing.cb.enabled
        swing.binding.update()
        assert swing.txt.enabled == swing.cb.enabled

        swing.txt.enabled = !swing.txt.enabled
        swing.binding.reverseUpdate()
        assert swing.txt.enabled == swing.cb.enabled

        DefaultButtonModel md = new DefaultButtonModel()
        md.enabled = !swing.txt.enabled
        swing.cb.model = md
        assert swing.txt.enabled == swing.cb.enabled
      }
    }

    public void testBindGroup() {
      testInEDT {
        SwingBuilder swing = new SwingBuilder()

        int enabledChangeCount = 1
        swing.actions() {
            bindGroup(id:'testGroup')
            checkBox('Button!', id:'cb')
            textField(id:'txt1', text:bind(source:cb, sourceProperty:'text', group:testGroup))
            textField(id:'txt2', text:bind(source:cb, sourceProperty:'text', sourceValue: {enabledChangeCount++}, group:testGroup))
            textField(id:'txt3', text:bind(source:cb, sourceProperty:'text', group:testGroup))
        }
        assert swing.txt1.text == 'Button!'
        assert swing.txt2.text == '1'
        assert swing.txt3.text == 'Button!'

        swing.testGroup.unbind()
        swing.cb.text = 'CheckBox!'
        swing.cb.selected = true

        assert swing.txt1.text == 'Button!'
        assert swing.txt2.text == '1'
        assert swing.txt3.text == 'Button!'

        swing.testGroup.update()
        assert swing.txt1.text == 'CheckBox!'
        assert swing.txt2.text == '2'
        assert swing.txt3.text == 'CheckBox!'

        swing.testGroup.bind()
        swing.cb.text = 'ComboBox!'
        swing.cb.selected = true
        assert swing.txt1.text == 'ComboBox!'
        assert swing.txt2.text == '3'
        assert swing.txt3.text == 'ComboBox!'

        // test auto-bind
        // test explicit true
        swing.actions() {
            bindGroup(id:'testGroup', bind:true)
            checkBox('Button!', id:'cb')
            textField(id:'txt1', text:bind(source:cb, sourceProperty:'text', group:testGroup))
        }

        assert swing.txt1.text == 'Button!'
        swing.cb.text = 'CheckBox!'
        assert swing.txt1.text == 'CheckBox!'

          // test explicit false
        swing.actions() {
            bindGroup(id:'testGroup', bind:false)
            checkBox('Button!', id:'cb')
            textField(id:'txt1', text:bind(source:cb, sourceProperty:'text', group:testGroup))
        }

        assert swing.txt1.text == 'Button!'
        swing.cb.text = 'CheckBox!'
        assert swing.txt1.text == 'Button!'

        // test implied = true
        swing.actions() {
        bindGroup(id:'testGroup')
        checkBox('Button!', id:'cb')
        textField(id:'txt1', text:bind(source:cb, sourceProperty:'text', group:testGroup))
        }

        assert swing.txt1.text == 'Button!'
        swing.cb.text = 'CheckBox!'
        assert swing.txt1.text == 'CheckBox!'
      }
    }

    public void testPropertyEventBinding() {
      testInEDT {
        SwingBuilder swing = new SwingBuilder()

        int enabledChangeCount = 1
        swing.actions() {
            checkBox('Button!', id:'cb')
            textField(id:'txtp', text:bind(source:cb, sourceProperty:'text',))
            textField(id:'txtpv', text:bind(source:cb, sourceProperty:'text', sourceValue: {enabledChangeCount++}))
            textField(id:'txtep', text:bind(source:cb, sourceEvent:'stateChanged', sourceProperty:'text'))
        }
        shouldFail {
            swing.actions() {
                // all three are pointless
                textField(id:'txtepv', enabled:bind(source:cb, sourceEvent:'stateChanged', sourceProperty:'text', sourceValue: {enabledChangeCount++}))
            }
        }
        shouldFail {
            swing.actions() {
                // just value isn't enough info
                textField(id:'txtv', enabled:bind(source:cb, sourceValue: {enabledChangeCount++}))
            }
        }
        shouldFail {
            swing.actions() {
                // just event isn't enough
                textField(id:'txtepv', enabled:bind(source:cb, sourceEvent:'stateChanged'))
            }
        }

        assert swing.txtp.text == 'Button!'
        assert swing.txtpv.text == '1'
        assert swing.txtep.text == 'Button!'

        swing.cb.text = 'CheckBox!'
        assert swing.txtp.text == 'CheckBox!'
        assert swing.txtpv.text == '2'
        assert swing.txtep.text == 'Button!'

        swing.cb.selected = true
        assert swing.txtp.text == 'CheckBox!'
        assert swing.txtpv.text == '2'
        assert swing.txtep.text == 'CheckBox!'

      }
    }

    public void testReversePropertyBinding() {
      testInEDT {
        SwingBuilder swing = new SwingBuilder()

        swing.actions() {
            textField(id:'txt')
            checkBox('Button!', id:'cb', enabled:bind(target:txt, targetProperty:'enabled', id:'binding'))
        }
        assert swing.txt.enabled == swing.cb.enabled
        swing.cb.enabled = !swing.cb.enabled
        assert swing.txt.enabled == swing.cb.enabled
        swing.cb.enabled = !swing.cb.enabled
        assert swing.txt.enabled == swing.cb.enabled

        swing.binding.rebind()
        swing.cb.enabled = !swing.cb.enabled
        assert swing.txt.enabled == swing.cb.enabled
        swing.binding.unbind()
        swing.cb.enabled = !swing.cb.enabled
        assert swing.txt.enabled != swing.cb.enabled
        swing.binding.bind()
        assert swing.txt.enabled != swing.cb.enabled
        swing.binding.update()
        assert swing.txt.enabled == swing.cb.enabled

        swing.txt.enabled = !swing.txt.enabled
        swing.binding.reverseUpdate()
        assert swing.txt.enabled == swing.cb.enabled

        DefaultButtonModel md = new DefaultButtonModel()
        md.enabled = !swing.txt.enabled
        swing.cb.model = md
        assert swing.txt.enabled == swing.cb.enabled
      }
    }

    public void testValueNodeBinding() {
      testInEDT {
        SwingBuilder swing = new SwingBuilder()

        swing.actions() {
            checkBox(id:'cb1')
            checkBox('Button!', id:'cb2', selected:bind(source:cb1, 'selected', id:'binding1'))
            checkBox(id:'cb3')
            checkBox('Button!', id:'cb4', selected:bind(target:cb3, 'selected', id:'binding2'))
        }
        assert !swing.cb1.selected
        assert !swing.cb2.selected
        swing.cb1.selected=true
        assert swing.cb1.selected
        assert swing.cb2.selected
        swing.cb2.selected=false
        assert swing.cb1.selected
        assert !swing.cb2.selected
        swing.cb1.selected=false
        swing.cb1.selected=true
        assert swing.cb1.selected
        assert swing.cb2.selected

        assert !swing.cb3.selected
        assert !swing.cb4.selected
        swing.cb3.selected=true
        assert swing.cb3.selected
        assert !swing.cb4.selected
        swing.cb4.selected=true
        assert swing.cb3.selected
        assert swing.cb4.selected
        swing.cb4.selected=false
        assert !swing.cb3.selected
        assert !swing.cb4.selected
      }
    }

    public void testReversePropertyPropertites() {
      testInEDT {
        SwingBuilder swing = new SwingBuilder()

        swing.actions() {
            textField(id:'txt')
            checkBox('Button!', id:'cb1', enabled:bind(target:txt, targetProperty:'enabled', converter: {it}, id:'binding1'))
            checkBox('Button!', id:'cb2', enabled:bind(target:txt, targetProperty:'enabled', id:'binding2'))
        }
        assert swing.binding1.converter != null
        assert swing.binding2.converter == null
      }
    }

    public void testConverters() {
      testInEDT {
        SwingBuilder swing = new SwingBuilder()

        swing.actions() {
            checkBox(id:'doner')
            checkBox(id:'cb1', enabled:bind(source:doner, sourceProperty:'enabled', converter: {it}, id:'binding1'))
            checkBox(id:'cb2', enabled:bind(source:doner, sourceProperty:'enabled', id:'binding2') {it})
            checkBox(id:'cb3', enabled:bind(source:doner, sourceProperty:'enabled', id:'binding3'))
        }
        assert swing.binding1.converter != null
        assert swing.binding2.converter != null
        assert swing.binding3.converter == null
        // check double duty
        shouldFail(RuntimeException) {
            swing.actions() {
                checkBox(id:'doner')
                checkBox(id:'cb1', enabled:bind(source:doner, sourceProperty:'enabled', converter: {it}, id:'binding1') {it})
            }
        }

        // check reversed bindings
        swing.actions() {
            checkBox(id:'doner')
            checkBox(id:'cb1', enabled:bind(target:doner, targetProperty:'enabled', converter: {it}, id:'binding1'))
            checkBox(id:'cb2', enabled:bind(target:doner, targetProperty:'enabled', id:'binding2') {it})
            checkBox(id:'cb3', enabled:bind(target:doner, targetProperty:'enabled', id:'binding3'))
        }
        assert swing.binding1.converter != null
        assert swing.binding2.converter != null
        assert swing.binding3.converter == null
        // check double duty
        shouldFail(RuntimeException) {
            swing.actions() {
                checkBox(id:'doner')
                checkBox(id:'cb1', enabled:bind(target:doner, targetProperty:'enabled', converter: {it}, id:'binding1') {it})
            }
        }

      }
    }

    public void testDateConverters() {
      testInEDT {
        BindableBean model = new BindableBean()
        model.date = new Date()
        def dateConverter = { dateString ->
                new SimpleDateFormat("dd.MM.yyyy").parse(dateString)
        }

        def dateValidator = { dateString ->
                try {
                        def parser = new SimpleDateFormat("dd.MM.yyyy")
                        parser.lenient = false
                        parser.parse(dateString)
                }
                catch (Exception e) {
                        return false
                }
                return true
        }


        SwingBuilder swing = new SwingBuilder()

        swing.actions() {
            tf1 = textField('01.01.1970', id:'birthdayText', columns:20,
              text:bind (
                 validator: dateValidator,
                 converter: dateConverter,
                 target:model, targetProperty:'birthday'
                 ))
            tf2 = textField('01.01.1970', id:'birthdayText', columns:20)
            binding = bind (
                  source: tf2,
                  sourceProperty: 'text',
                  validator: dateValidator,
                  converter: dateConverter,
                  target:model,
                  targetProperty:'birthday'
                  )

        }
      }
    }

    public void testPropertyValuePassthrough() {
      testInEDT {
        SwingBuilder swing = new SwingBuilder()

        swing.actions() {
            spinner(id:'spin1', value:4)
            spinner(id:'spin2', value:8)
            slider(id:'s1', value:bind(target:spin1, targetProperty:'value', id:'binding1', value:15))
            slider(id:'s2', value:bind(source:spin2, sourceProperty:'value', id:'binding2', value:16))
        }
        // s1 is the source, so it's value should be reflected
        assert swing.s1.value == 15
        // s2 is target, not source, so it's value setting should have no effect
        assert swing.s2.value == 8

        swing.actions() {
            slider(id:'s3', value:4)
            slider(id:'s4', value:8)
            textArea(id:'t1', text:bind(target:s3, targetProperty:'value',
                id:'binding3', value:'15',
                converter: {Integer.parseInt(it)}))
            textArea(id:'t2', text:bind(source:s4, sourceProperty:'value',
                id:'binding4', value:'16',
                converter: {Integer.parseInt(it)}))
        }
        // s1 is the source, so it's value should be reflected
        assert swing.s3.value == 15
        // s2 is target, not source, so it's value setting should have no effect
        assert swing.s4.value == 8


      }
    }

    public void testModel() {
      testInEDT {
        SwingBuilder swing = new SwingBuilder()

        def bean = new org.codehaus.groovy.runtime.DummyBean()

        swing.bindProxy(bean, id:'dummyBean')

        // test initial binding
        swing.textField(id:'textField', text:swing.dummyBean.name)
        assert swing.textField.text == bean.name

        // test no live update by default
        bean.name = 'Jochen'
        assert swing.textField.text != bean.name

        // test for no update on bean change
        bean = new org.codehaus.groovy.runtime.DummyBean()
        bean.name = 'Alex'
        swing.dummyBean.setModel(bean)
        assert swing.textField.text != bean.name


        //test for auto-update
        swing.bindProxy(bean, id:'boundDummyBean', bind:true)
        swing.textField(id:'boundTextField', text:swing.boundDummyBean.name)
        assert swing.boundTextField.text == bean.name
        bean.name = 'Danno'
        assert swing.boundTextField.text == bean.name

        // old model binding could be listening...
        assert swing.textField.text != bean.name
      }
    }

    public void testModelUpdate() {
      testInEDT {
        SwingBuilder swing = new SwingBuilder()

        def bean = new org.codehaus.groovy.runtime.DummyBean()

        swing.bindProxy(bean, id:'dummyBean', bind:true)

        // test initial binding
        bean.name = 'Jochen'
        swing.textField(id:'textField', text:swing.dummyBean.name)
        assert swing.textField.text == bean.name

        // test for update on bean change
        bean = new org.codehaus.groovy.runtime.DummyBean()
        bean.name = 'Alex'

        swing.dummyBean.setModel(bean)
        assert swing.textField.text == bean.name

        // now simply one more live update: test fails here because
        // setModel() has called rebind() instead of bind()!
        bean.name = 'Danno'
        assert swing.textField.text == bean.name

        // test unbound, nothing should update no matter what we do
        swing.dummyBean.unbind()
        bean.name = 'Guillaume'
        assert swing.textField.text != bean.name

        bean = new org.codehaus.groovy.runtime.DummyBean()
        bean.name = 'Andres'

        swing.dummyBean.setModel(bean)
        assert swing.textField.text != bean.name

        bean.name = 'James'
        assert swing.textField.text != bean.name

        // but a manual update should work
        swing.dummyBean.update()
        assert swing.textField.text == bean.name
      }
    }


    def mutualPropertyShortWorkout = { source, sourceProperty, sourceMutators,
        target, targetProperty, targetMutators, binding ->

      sourceMutators[0]()
      targetMutators[0]()

      // test forward binding
      assert source[sourceProperty] == target[targetProperty]
      sourceMutators[1]()
      assert source[sourceProperty] == target[targetProperty]
      sourceMutators[0]()
      assert source[sourceProperty] == target[targetProperty]
                                                                                                                        
      // test reverse binding
      targetMutators[1]()
      assert source[sourceProperty] == target[targetProperty]
      targetMutators[0]()
      assert source[sourceProperty] == target[targetProperty]
    }

    def mutualPropertyWorkout = { source, sourceProperty, sourceMutators,
      target, targetProperty, targetMutators, binding ->

      mutualPropertyShortWorkout(source, sourceProperty, sourceMutators,
        target, targetProperty, targetMutators, binding)

      // test rebound
      binding.rebind()
      targetMutators[1]()
      assert source[sourceProperty] == target[targetProperty]
      sourceMutators[0]()
      assert source[sourceProperty] == target[targetProperty]

      // test unbound not updating
      binding.unbind()
      sourceMutators[1]()
      assert source[sourceProperty] != target[targetProperty]
      targetMutators[1]()
      assert source[sourceProperty] == target[targetProperty]
      sourceMutators[0]()
      assert source[sourceProperty] != target[targetProperty]

      // test manual forward update
      sourceMutators[0]()
      assert source[sourceProperty] != target[targetProperty]
      binding.update()
      assert source[sourceProperty] == target[targetProperty]

      // test manual reverse update
      sourceMutators[1]()
      assert source[sourceProperty] != target[targetProperty]
      binding.reverseUpdate()
      assert source[sourceProperty] == target[targetProperty]
    }
  
    public void testMutualPropertyBinding() {
      testInEDT {
        ['full', 'source', 'target'].each { mode -> // contextual bind mode
          ['prop', 'synth'].each { target -> // target binding
            ['prop', 'synth'].each { source -> // source binding
              println "Trying $mode binding on $source source and $target target"

              SwingBuilder swing = new SwingBuilder()

              def sProp, tProp
              swing.actions() {
                switch (source) {
                  case 'prop':
                    sProp = 'enabled'
                    st = new BindableBean(text:'Baz')
                    break
                  case 'synth':
                    sProp = 'selected'
                    st = textField(text:'Baz')
                    break
                  default: fail()
                }
                switch (target) {
                  case 'prop':
                    tProp = 'enabled'
                    tt = new BindableBean(text:'Baz')
                    break
                  case 'synth':
                    tProp = 'selected'
                    tt = textField(text:'Baz')
                    break
                  default: fail()
                }
                
                switch (mode) {
                  case 'full':
                    checkBox(id:'cb1')
                    checkBox(id:'cb2')
                    bind(source: cb1, sourceProperty: sProp,
                         target: cb2, targetProperty: tProp,
                         id:'binding', mutual:'true')

                    bind('text', source: st, target: tt,
                         id:'textBinding', mutual:'true')

                    break
                  case 'source':
                    checkBox(id:'cb2')
                    checkBox(id:'cb1', "$sProp": bind(
                         target: cb2, targetProperty:tProp,
                         id:'binding', mutual:'true'))

                    bean(st, text:bind(
                         target: tt, 'text',
                         id:'textBinding', mutual:'true'))
                    break
                  case 'target':
                    checkBox(id:'cb1')
                    checkBox(id:'cb2', "$tProp": bind(
                         source: cb1, sourceProperty:sProp,
                         id:'binding', mutual:'true'))

                    bean(tt, text:bind(
                         source: st, 'text',
                         id:'textBinding', mutual:'true'))
                  break
                  default: fail()
                }
              }
              mutualPropertyWorkout(swing.cb1, sProp, [{swing.cb1[sProp] = true}, {swing.cb1[sProp] = false}],
                swing.cb2, tProp, [{swing.cb2[tProp] = true}, {swing.cb2[tProp] = false}],
                swing.binding)

              mutualPropertyWorkout(swing.st, 'text', [{swing.st.text = "Foo"}, {swing.st.text = "Bar"}],
                swing.tt, 'text', [{swing.tt.text = "Foo"}, {swing.tt.text = "Bar"}],
                swing.textBinding)
            }
            if (mode != 'source') {
              println "Trying $mode binding on event source and $target target"

              SwingBuilder swing = new SwingBuilder()

              def tProp
              swing.actions() {
                st = button(actionCommand:'Baz')

                switch (target) {
                  case 'prop':
                    tProp = 'enabled'
                    tt = new BindableBean(text:'Baz')
                    break
                  case 'synth':
                    tProp = 'selected'
                    tt = textField(text:'Baz')
                    break
                  default: fail()
                }
                switch (mode) {
                  case 'full':
                    checkBox(id:'cb1')
                    checkBox(id:'cb2')
                    bind(source: cb1, sourceEvent: 'actionPerformed', sourceProperty: 'borderPaintedFlat',
                         target: cb2, targetProperty: tProp,
                         id:'binding', mutual:'true')

                    bind('text', source: st, sourceEvent: 'actionPerformed', sourceProperty:'actionCommand', target: tt,
                         id:'textBinding', mutual:'true')

                    break
                  case 'target':
                    checkBox(id:'cb1')
                    checkBox(id:'cb2', "$tProp": bind(  source: cb1,
                         sourceEvent: 'actionPerformed', sourceProperty: 'borderPaintedFlat',
                         id:'binding', mutual:'true'))

                    bean(tt, text:bind(
                         source: st, 'actionCommand', sourceEvent: 'actionPerformed',
                         id:'textBinding', mutual:'true'))
                  break
                  default: fail()
                }
                mutualPropertyShortWorkout(swing.cb1, 'borderPaintedFlat', [{swing.cb1.borderPaintedFlat = true; swing.cb1.doClick()}, {swing.cb1.borderPaintedFlat = false; swing.cb1.doClick()}],
                  swing.cb2, tProp, [{swing.cb2[tProp] = true}, {swing.cb2[tProp] = false}],
                  swing.binding)

                mutualPropertyShortWorkout(swing.st, 'actionCommand', [{swing.st.actionCommand = "Foo"; swing.st.doClick()}, {swing.st.actionCommand = "Bar"; swing.st.doClick()}],
                  swing.tt, 'text', [{swing.tt.text = "Foo"}, {swing.tt.text = "Bar"}],
                  swing.textBinding)
              }
            }
          }
        }

        println "finished all permutations successfully"

      }
    }

    public void testConverter() {
      testInEDT {
        SwingBuilder swing = new SwingBuilder()
        def model = new BindableBean()

        def toNumber = { v ->
          if( v == null || v == "" ) return null
          try { return new Integer(v) }
          catch( x ) { return null }
        }

        swing.actions {

          frame( title: "Binding test", size: [100,60]) {
            textField( id: "t1", text: bind(target:model,
            targetProperty: "value", converter: {toNumber(it)}) )
          textField( id: "t2", text: bind(target:model,
            'floatValue', value:'1234', converter: { Float.parseFloat(it) * 2 }))
          }
        }
        assert model.floatValue == 2468
        swing.t1.text = '1234'
        assert model.value == 1234
      }
    }

    public void testValidator() {
      testInEDT {
        SwingBuilder swing = new SwingBuilder()
        def model = new BindableBean()

        def isInteger = { v ->
          try {
              Float.parseFloat(v)
              return true
          } catch (NumberFormatException ignore) {
              return false
          }
        }

        swing.actions {
          frame( title: "Binding test", size: [100,60]) {
            textField( id: "t1", text: bind(target:model, value:'123',
              targetProperty: "value", validator: isInteger, converter: Integer.&parseInt) )
          }
        }
        assert model.value == 123
        swing.t1.text = '1234'
        assert model.value == 1234
        swing.t1.text = 'Bogus'
        assert model.value == 1234
        swing.t1.text = '12345'
        assert model.value == 12345
      }
    }

    public void testBindableVetoable() {
      testInEDT {
        def bbean = new BindableBean()
        bbean.vetoableChange = { PropertyChangeEvent pce ->
          if( pce.newValue ==~ /.*[ ]+.*/ ) {
            throw new PropertyVetoException( "No spaces allowed", pce )
          }
        }
        def abean = null
        SwingBuilder.build {
            abean = bean(new BindableBean(), text:'text', id:'tf')
            bean(bbean, vetoField:bind { tf.text } )
        }
        abean.text = "test1"
        assert abean.text == bbean.vetoField

        abean.text = "this should fail"
        assert abean.text != bbean.vetoField

      }
    }
}

@Bindable class BindableBean {
    boolean enabled
    Integer value
    float floatValue
    int pvalue
    String text
    Date date
    @Vetoable String vetoField
}

Other Groovy examples (source code examples)

Here is a short list of links related to this Groovy SwingBuilderBindingsTest.groovy source code file:

new blog posts

 

Copyright 1998-2014 Alvin Alexander, alvinalexander.com
All Rights Reserved.