|
Groovy example source code file (SwingBuilderBindingsTest.groovy)
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: |
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.